112891Swpaul/* 212891Swpaul * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 312891Swpaul * 450479Speter * SPDX-License-Identifier: GPL-2.0-only 512891Swpaul */ 612891Swpaul 712891Swpaul#pragma once 812891Swpaul 912891Swpaul#include <config.h> 1012891Swpaul 1112891Swpaul#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 1212891Swpaul 1312891Swpaul#include <arch/object/vcpu.h> 14194968Sbrian#include <drivers/timer/arm_generic.h> 15194968Sbrian 16194968Sbrian/* Note that the HCR_DC for ARMv8 disables S1 translation if enabled */ 17194968Sbrian#ifdef CONFIG_DISABLE_WFI_WFE_TRAPS 1812891Swpaul/* Trap SMC and override CPSR.AIF */ 1912891Swpaul#define HCR_COMMON ( HCR_VM | HCR_RW | HCR_AMO | HCR_IMO | HCR_FMO ) 2012891Swpaul#else 21194968Sbrian/* Trap WFI/WFE/SMC and override CPSR.AIF */ 22194968Sbrian#define HCR_COMMON ( HCR_TWI | HCR_TWE | HCR_VM | HCR_RW | HCR_AMO | HCR_IMO | HCR_FMO ) 23194968Sbrian#endif 24194968Sbrian 25194968Sbrian/* Allow native tasks to run at EL0, but restrict access */ 2612891Swpaul#define HCR_NATIVE ( HCR_COMMON | HCR_TGE | HCR_TVM | HCR_TTLB | HCR_DC \ 2712891Swpaul | HCR_TAC | HCR_SWIO | HCR_TSC | HCR_IMO | HCR_FMO | HCR_AMO) 28194968Sbrian#define HCR_VCPU ( HCR_COMMON | HCR_TSC) 29194968Sbrian 30194968Sbrian#define SCTLR_EL1_UCI BIT(26) /* Enable EL0 access to DC CVAU, DC CIVAC, DC CVAC, 31194968Sbrian and IC IVAU in AArch64 state */ 32194968Sbrian#define SCTLR_EL1_C BIT(2) /* Enable data and unified caches */ 33194968Sbrian#define SCTLR_EL1_I BIT(12) /* Enable instruction cache */ 34194968Sbrian#define SCTLR_EL1_CP15BEN BIT(5) /* AArch32 CP15 barrier enable */ 3512891Swpaul#define SCTLR_EL1_UTC BIT(15) /* Enable EL0 access to CTR_EL0 */ 3612891Swpaul#define SCTLR_EL1_NTWI BIT(16) /* WFI executed as normal */ 3712891Swpaul#define SCTLR_EL1_NTWE BIT(18) /* WFE executed as normal */ 3819161Swpaul 3919161Swpaul/* Disable MMU, SP alignment check, and alignment check */ 40194968Sbrian/* A57 default value */ 41194968Sbrian#define SCTLR_EL1_RES 0x30d00800 /* Reserved value */ 4219161Swpaul#define SCTLR_EL1 ( SCTLR_EL1_RES | SCTLR_EL1_CP15BEN | SCTLR_EL1_UTC \ 4319161Swpaul | SCTLR_EL1_NTWI | SCTLR_EL1_NTWE ) 44194968Sbrian#define SCTLR_EL1_NATIVE (SCTLR_EL1 | SCTLR_EL1_C | SCTLR_EL1_I | SCTLR_EL1_UCI) 45194968Sbrian#define SCTLR_EL1_VM (SCTLR_EL1 | SCTLR_EL1_UCI) 46194968Sbrian#define SCTLR_DEFAULT SCTLR_EL1_NATIVE 47194968Sbrian 4819161Swpaul#define UNKNOWN_FAULT 0x2000000 4919161Swpaul#define ESR_EC_TFP 0x7 /* Trap instructions that access FPU registers */ 5012891Swpaul#define ESR_EC_CPACR 0x18 /* Trap access to CPACR */ 5112891Swpaul#define ESR_EC(x) (((x) & 0xfc000000) >> 26) 5212891Swpaul 5312891Swpaul#define VTCR_EL2_T0SZ(x) ((x) & 0x3f) 5412891Swpaul#define VTCR_EL2_SL0(x) (((x) & 0x3) << 6) 5512891Swpaul#define VTCR_EL2_IRGN0(x) (((x) & 0x3) << 8) 5612891Swpaul#define VTCR_EL2_ORGN0(x) (((x) & 0x3) << 10) 5715426Swpaul#define VTCR_EL2_SH0(x) (((x) & 0x3) << 12) 5833100Swpaul#define VTCR_EL2_TG0(x) (((x) & 0x3) << 14) 5912891Swpaul#define VTCR_EL2_PS(x) (((x) & 0x7) << 16) 6017220Sadam 6117220Sadam/* Physical address size */ 6212891Swpaul#define PS_4G 0 6315426Swpaul#define PS_64G 1 6413398Swpaul#define PS_1T 2 6513896Swpaul#define PS_4T 3 6612891Swpaul#define PS_16T 4 6713896Swpaul#define PS_256T 5 6813896Swpaul 6913896Swpaul/* Translation granule size */ 7012891Swpaul#define TG0_4K 0 7133100Swpaul#define TG0_64K 1 7212891Swpaul#define TG0_16K 2 7317220Sadam 7417220Sadam#define ID_AA64MMFR0_EL1_PARANGE(x) ((x) & 0xf) 7515426Swpaul#define ID_AA64MMFR0_TGRAN4(x) (((x) >> 28u) & 0xf) 7615426Swpaul 7712891Swpaul/* Shareability attributes */ 7831110Swpaul#define SH0_NONE 0 7912891Swpaul#define SH0_OUTER 2 8031110Swpaul#define SH0_INNER 3 8131110Swpaul 8231110Swpaul/* Cacheability attributes */ 8312891Swpaul#define NORMAL_NON_CACHEABLE 0 8412891Swpaul#define NORMAL_WB_WA_CACHEABLE 1 /* write-back, write-allocate */ 8512891Swpaul#define NORMAL_WT_CACHEABLE 2 /* write-through */ 8612891Swpaul#define NORMAL_WB_NWA_CACHEABLE 3 /* write-back, no write-allocate */ 8772091Sasmodai 8812891Swpaul/* Start level */ 8912891Swpaul#define SL0_4K_L2 0 /* 4K, start at level 2 */ 9012891Swpaul#define SL0_4K_L1 1 /* 4K, start at level 1 */ 9112891Swpaul#define SL0_4K_L0 2 /* 4K, start at level 0 */ 9212891Swpaul 9337819Sphk#define REG_SCTLR_EL1 "sctlr_el1" 9437819Sphk#define REG_TTBR0_EL1 "ttbr0_el1" 9512891Swpaul#define REG_TTBR1_EL1 "ttbr1_el1" 9612891Swpaul#define REG_TCR_EL1 "tcr_el1" 9712891Swpaul#define REG_MAIR_EL1 "mair_el1" 9812891Swpaul#define REG_AMAIR_EL1 "amair_el1" 9912891Swpaul#define REG_CONTEXTIDR_EL1 "contextidr_el1" 10012891Swpaul#define REG_ACTLR_EL1 "actlr_el1" 10112891Swpaul#define REG_AFSR0_EL1 "afsr0_el1" 10212891Swpaul#define REG_AFSR1_EL1 "afsr1_el1" 10312891Swpaul#define REG_ESR_EL1 "esr_el1" 10412891Swpaul#define REG_FAR_EL1 "far_el1" 10512891Swpaul#define REG_ISR_EL1 "isr_el1" 10612891Swpaul#define REG_VBAR_EL1 "vbar_el1" 10712891Swpaul#define REG_TPIDR_EL1 "tpidr_el1" 108145801Sume#define REG_SP_EL1 "sp_el1" 10912891Swpaul#define REG_ELR_EL1 "elr_el1" 11012891Swpaul#define REG_SPSR_EL1 "spsr_el1" 11112891Swpaul#define REG_CPACR_EL1 "cpacr_el1" 11212891Swpaul#define REG_CNTV_TVAL_EL0 "cntv_tval_el0" 113112458Srobert#define REG_CNTV_CTL_EL0 "cntv_ctl_el0" 11412891Swpaul#define REG_CNTV_CVAL_EL0 "cntv_cval_el0" 11576621Sgshapiro#define REG_CNTVOFF_EL2 "cntvoff_el2" 11615426Swpaul#define REG_CNTKCTL_EL1 "cntkctl_el1" 11712891Swpaul#define REG_HCR_EL2 "hcr_el2" 11812891Swpaul#define REG_VTCR_EL2 "vtcr_el2" 11912891Swpaul#define REG_VMPIDR_EL2 "vmpidr_el2" 12012891Swpaul#define REG_ID_AA64MMFR0_EL1 "id_aa64mmfr0_el1" 12112891Swpaul 12212891Swpaul/* for EL1 SCTLR */ 12312891Swpaulstatic inline word_t getSCTLR(void) 12412891Swpaul{ 12516732Swpaul return readSystemControlRegister(); 12690320Smarkm} 12712891Swpaul 128194968Sbrianstatic inline void setSCTLR(word_t sctlr) 129194968Sbrian{ 130194968Sbrian writeSystemControlRegister(sctlr); 131194968Sbrian} 132194968Sbrian 133194968Sbrianstatic inline word_t readTTBR0(void) 134194968Sbrian{ 135194968Sbrian word_t reg; 136194968Sbrian MRS(REG_TTBR0_EL1, reg); 137194968Sbrian return reg; 138194968Sbrian} 13931110Swpaul 14031110Swpaulstatic inline void writeTTBR0(word_t reg) 14131110Swpaul{ 142112458Srobert MSR(REG_TTBR0_EL1, reg); 14331110Swpaul} 14431110Swpaul 14531110Swpaulstatic inline word_t readTTBR1(void) 14631110Swpaul{ 14731110Swpaul word_t reg; 14831110Swpaul MRS(REG_TTBR1_EL1, reg); 14931110Swpaul return reg; 15031110Swpaul} 15131110Swpaul 15231110Swpaulstatic inline void writeTTBR1(word_t reg) 15331110Swpaul{ 15431110Swpaul MSR(REG_TTBR1_EL1, reg); 15531110Swpaul} 15631110Swpaul 15731110Swpaulstatic inline word_t readTCR(void) 15831110Swpaul{ 15931110Swpaul word_t reg; 16031110Swpaul MRS(REG_TCR_EL1, reg); 16131110Swpaul return reg; 16231110Swpaul} 16331110Swpaul 16431110Swpaulstatic inline void writeTCR(word_t reg) 16531110Swpaul{ 16631110Swpaul MSR(REG_TCR_EL1, reg); 16731110Swpaul} 16831110Swpaul 169194968Sbrianstatic inline word_t readMAIR(void) 170194968Sbrian{ 171194968Sbrian word_t reg; 17231110Swpaul MRS(REG_MAIR_EL1, reg); 17331110Swpaul return reg; 17431110Swpaul} 17531110Swpaul 17631110Swpaulstatic inline void writeMAIR(word_t reg) 17731110Swpaul{ 17831110Swpaul MSR(REG_MAIR_EL1, reg); 17931110Swpaul} 18031110Swpaul 18131110Swpaulstatic inline word_t readAMAIR(void) 18231110Swpaul{ 18331110Swpaul word_t reg; 18490320Smarkm MRS(REG_AMAIR_EL1, reg); 18531110Swpaul return reg; 18631110Swpaul} 18731110Swpaul 18831110Swpaulstatic inline void writeAMAIR(word_t reg) 189145801Sume{ 190145801Sume MSR(REG_AMAIR_EL1, reg); 191145801Sume} 192145801Sume 193145801Sumestatic inline word_t readCIDR(void) 194145801Sume{ 19531110Swpaul uint32_t reg; 19612891Swpaul MRS(REG_CONTEXTIDR_EL1, reg); 19712891Swpaul return (word_t)reg; 19812891Swpaul} 19912891Swpaul 200145801Sumestatic inline void writeCIDR(word_t reg) 20112891Swpaul{ 20212891Swpaul MSR(REG_CONTEXTIDR_EL1, (uint32_t)reg); 20312891Swpaul} 20412891Swpaul 20512891Swpaulstatic inline word_t readACTLR(void) 206194968Sbrian{ 20712891Swpaul word_t reg; 20812891Swpaul MRS(REG_ACTLR_EL1, reg); 20912891Swpaul return reg; 21012891Swpaul} 21112891Swpaul 21215426Swpaulstatic inline void writeACTLR(word_t reg) 21312891Swpaul{ 21412891Swpaul MSR(REG_ACTLR_EL1, reg); 21512891Swpaul} 21616118Swpaul 21716118Swpaulstatic inline word_t readAFSR0(void) 21816118Swpaul{ 21916118Swpaul uint32_t reg; 22016118Swpaul MRS(REG_AFSR0_EL1, reg); 22116118Swpaul return (word_t)reg; 22216118Swpaul} 22316118Swpaul 22416118Swpaulstatic inline void writeAFSR0(word_t reg) 22516118Swpaul{ 22616118Swpaul MSR(REG_AFSR0_EL1, (uint32_t)reg); 227194968Sbrian} 228194968Sbrian 229194968Sbrianstatic inline word_t readAFSR1(void) 230194968Sbrian{ 23116118Swpaul uint32_t reg; 23216118Swpaul MRS(REG_AFSR1_EL1, reg); 23316118Swpaul return (word_t)reg; 23431110Swpaul} 23531110Swpaul 23631110Swpaulstatic inline void writeAFSR1(word_t reg) 23731110Swpaul{ 23831110Swpaul MSR(REG_AFSR1_EL1, (uint32_t)reg); 23931110Swpaul} 24031110Swpaul 24131110Swpaulstatic inline word_t readESR(void) 24231110Swpaul{ 24331110Swpaul uint32_t reg; 24431110Swpaul MRS(REG_ESR_EL1, reg); 24531110Swpaul return (word_t)reg; 24648199Sn_hibma} 24731110Swpaul 24831110Swpaulstatic inline void writeESR(word_t reg) 24931110Swpaul{ 25015426Swpaul MSR(REG_ESR_EL1, (uint32_t)reg); 25115426Swpaul} 25217220Sadam 25317481Sadamstatic inline word_t readFAR(void) 25433100Swpaul{ 25533100Swpaul word_t reg; 25615426Swpaul MRS(REG_FAR_EL1, reg); 25716044Swpaul return reg; 25816044Swpaul} 25912891Swpaul 26015426Swpaulstatic inline void writeFAR(word_t reg) 26112891Swpaul{ 26212891Swpaul MSR(REG_FAR_EL1, reg); 263116301Sru} 264116301Sru 26533100Swpaul/* ISR is read-only */ 26633100Swpaulstatic inline word_t readISR(void) 26715426Swpaul{ 26812891Swpaul uint32_t reg; 26912891Swpaul MRS(REG_ISR_EL1, reg); 27012891Swpaul return (word_t)reg; 27112891Swpaul} 27212891Swpaul 27331110Swpaulstatic inline word_t readVBAR(void) 27431110Swpaul{ 27531110Swpaul word_t reg; 276116301Sru MRS(REG_VBAR_EL1, reg); 277116301Sru return reg; 27833100Swpaul} 27915426Swpaul 28017268Speterstatic inline void writeVBAR(word_t reg) 28112891Swpaul{ 28231110Swpaul MSR(REG_VBAR_EL1, reg); 28312891Swpaul} 28412891Swpaul 28512891Swpaulstatic inline word_t readSP_EL1(void) 28631110Swpaul{ 28731110Swpaul word_t reg; 28831110Swpaul MRS(REG_SP_EL1, reg); 289116301Sru return reg; 290116301Sru} 29133100Swpaul 29215426Swpaulstatic inline void writeSP_EL1(word_t reg) 29312891Swpaul{ 29412891Swpaul MSR(REG_SP_EL1, reg); 29531110Swpaul} 29612891Swpaul 29712891Swpaulstatic inline word_t readELR_EL1(void) 29812891Swpaul{ 29912891Swpaul word_t reg; 30031110Swpaul MRS(REG_ELR_EL1, reg); 30131110Swpaul return reg; 30231110Swpaul} 303116301Sru 304116301Srustatic inline void writeELR_EL1(word_t reg) 30533100Swpaul{ 30615426Swpaul MSR(REG_ELR_EL1, reg); 30712891Swpaul} 30812891Swpaul 30931110Swpaulstatic inline word_t readSPSR_EL1(void) 31012891Swpaul{ 31112891Swpaul word_t reg; 31212891Swpaul MRS(REG_SPSR_EL1, reg); 31312891Swpaul return reg; 31431110Swpaul} 31531110Swpaul 31631110Swpaulstatic inline void writeSPSR_EL1(word_t reg) 317116301Sru{ 318116301Sru MSR(REG_SPSR_EL1, reg); 31933100Swpaul} 32015426Swpaul 32112891Swpaulstatic inline word_t readCPACR_EL1(void) 32212891Swpaul{ 32331110Swpaul word_t reg; 32412891Swpaul MRS(REG_CPACR_EL1, reg); 32512891Swpaul return reg; 32612891Swpaul} 32712891Swpaul 32831110Swpaulstatic inline void writeCPACR_EL1(word_t reg) 32931110Swpaul{ 33031110Swpaul MSR(REG_CPACR_EL1, reg); 331116301Sru} 33232775Ssteve 333116301Srustatic inline word_t readCNTV_TVAL_EL0(void) 33433100Swpaul{ 33515426Swpaul word_t reg; 33612891Swpaul MRS(REG_CNTV_TVAL_EL0, reg); 33712891Swpaul return reg; 33831110Swpaul} 33912891Swpaul 34012891Swpaulstatic inline void writeCNTV_TVAL_EL0(word_t reg) 34112891Swpaul{ 34212891Swpaul MSR(REG_CNTV_TVAL_EL0, reg); 34331110Swpaul} 34431110Swpaul 34531110Swpaulstatic inline word_t readCNTV_CTL_EL0(void) 346116301Sru{ 34732775Ssteve word_t reg; 348116301Sru MRS(REG_CNTV_CTL_EL0, reg); 34933100Swpaul return reg; 35015426Swpaul} 35112891Swpaul 35212891Swpaulstatic inline void writeCNTV_CTL_EL0(word_t reg) 35331110Swpaul{ 35412891Swpaul MSR(REG_CNTV_CTL_EL0, reg); 35512891Swpaul} 35612891Swpaul 35712891Swpaulstatic inline word_t readCNTV_CVAL_EL0(void) 358116301Sru{ 359116301Sru word_t reg; 36033100Swpaul MRS(REG_CNTV_CVAL_EL0, reg); 36115426Swpaul return reg; 36212891Swpaul} 36312891Swpaul 36412891Swpaulstatic inline void writeCNTV_CVAL_EL0(word_t reg) 36515426Swpaul{ 36612891Swpaul MSR(REG_CNTV_CVAL_EL0, reg); 36712891Swpaul} 368116301Sru 36933100Swpaulstatic inline word_t readCNTVOFF_EL2(void) 37033100Swpaul{ 37115426Swpaul word_t reg; 37212891Swpaul MRS(REG_CNTVOFF_EL2, reg); 37312891Swpaul return reg; 37412891Swpaul} 37512891Swpaul 376145801Sumestatic inline void writeCNTVOFF_EL2(word_t reg) 377145801Sume{ 378145801Sume MSR(REG_CNTVOFF_EL2, reg); 379145801Sume} 380145801Sume 381145801Sumestatic inline word_t readCNTKCTL_EL1(void) 382145801Sume{ 383145801Sume word_t reg; 384145801Sume MRS(REG_CNTKCTL_EL1, reg); 385145801Sume return reg; 386145801Sume} 387145801Sume 388145801Sumestatic inline void writeCNTKCTL_EL1(word_t reg) 389145801Sume{ 390145801Sume MSR(REG_CNTKCTL_EL1, reg); 391145801Sume} 392145801Sume 393145801Sumestatic inline word_t readVMPIDR_EL2(void) 394145801Sume{ 395145801Sume word_t reg; 396145801Sume MRS(REG_VMPIDR_EL2, reg); 397145801Sume return reg; 398145801Sume} 399145801Sume 400145801Sumestatic inline void writeVMPIDR_EL2(word_t reg) 401145801Sume{ 402145801Sume MSR(REG_VMPIDR_EL2, reg); 403145801Sume} 40412891Swpaul 40512891Swpaulstatic word_t vcpu_hw_read_reg(word_t reg_index) 406116301Sru{ 40732775Ssteve word_t reg = 0; 40832775Ssteve switch (reg_index) { 40912891Swpaul case seL4_VCPUReg_SCTLR: 410116301Sru return getSCTLR(); 411116301Sru case seL4_VCPUReg_TTBR0: 41233100Swpaul return readTTBR0(); 41315426Swpaul case seL4_VCPUReg_TTBR1: 41412891Swpaul return readTTBR1(); 41512891Swpaul case seL4_VCPUReg_TCR: 41612891Swpaul return readTCR(); 41712891Swpaul case seL4_VCPUReg_MAIR: 41812891Swpaul return readMAIR(); 41912891Swpaul case seL4_VCPUReg_AMAIR: 420116301Sru return readAMAIR(); 42133100Swpaul case seL4_VCPUReg_CIDR: 42233100Swpaul return readCIDR(); 42315426Swpaul case seL4_VCPUReg_ACTLR: 42412891Swpaul return readACTLR(); 42512891Swpaul case seL4_VCPUReg_CPACR: 42612891Swpaul return readCPACR_EL1(); 42712891Swpaul case seL4_VCPUReg_AFSR0: 42812891Swpaul return readAFSR0(); 42912891Swpaul case seL4_VCPUReg_AFSR1: 430116301Sru return readAFSR1(); 43132775Ssteve case seL4_VCPUReg_ESR: 43232775Ssteve return readESR(); 43312891Swpaul case seL4_VCPUReg_FAR: 434116301Sru return readFAR(); 43533100Swpaul case seL4_VCPUReg_ISR: 43615426Swpaul return readISR(); 43712891Swpaul case seL4_VCPUReg_VBAR: 43812891Swpaul return readVBAR(); 43912891Swpaul case seL4_VCPUReg_TPIDR_EL1: 44012891Swpaul return readTPIDR_EL1(); 44112891Swpaul case seL4_VCPUReg_SP_EL1: 44212891Swpaul return readSP_EL1(); 443116301Sru case seL4_VCPUReg_ELR_EL1: 44433100Swpaul return readELR_EL1(); 44533100Swpaul case seL4_VCPUReg_SPSR_EL1: 44615426Swpaul return readSPSR_EL1(); 44712891Swpaul case seL4_VCPUReg_CNTV_CTL: 44812891Swpaul return readCNTV_CTL_EL0(); 44912891Swpaul case seL4_VCPUReg_CNTV_CVAL: 45012891Swpaul return readCNTV_CVAL_EL0(); 45112891Swpaul case seL4_VCPUReg_CNTVOFF: 45212891Swpaul return readCNTVOFF_EL2(); 453116301Sru case seL4_VCPUReg_CNTKCTL_EL1: 45432775Ssteve return readCNTKCTL_EL1(); 45532775Ssteve#ifdef ENABLE_SMP_SUPPORT 45612891Swpaul case seL4_VCPUReg_VMPIDR_EL2: 457116301Sru return readVMPIDR_EL2(); 45833100Swpaul#endif /* ENABLE_SMP_SUPPORT */ 45915426Swpaul default: 46012891Swpaul fail("ARM/HYP: Invalid register index"); 46112891Swpaul } 46212891Swpaul 46312891Swpaul return reg; 46412891Swpaul} 46512891Swpaul 466116301Srustatic void vcpu_hw_write_reg(word_t reg_index, word_t reg) 46733100Swpaul{ 46833100Swpaul switch (reg_index) { 46915426Swpaul case seL4_VCPUReg_SCTLR: 47012891Swpaul return setSCTLR(reg); 47112891Swpaul case seL4_VCPUReg_TTBR0: 47212891Swpaul return writeTTBR0(reg); 47312891Swpaul case seL4_VCPUReg_TTBR1: 47412891Swpaul return writeTTBR1(reg); 47512891Swpaul case seL4_VCPUReg_TCR: 476116301Sru return writeTCR(reg); 47732775Ssteve case seL4_VCPUReg_MAIR: 47833300Swpaul return writeMAIR(reg); 47933300Swpaul case seL4_VCPUReg_AMAIR: 48033536Swpaul return writeAMAIR(reg); 48133300Swpaul case seL4_VCPUReg_CIDR: 48233300Swpaul return writeCIDR(reg); 483116301Sru case seL4_VCPUReg_ACTLR: 484116301Sru return writeACTLR(reg); 48533100Swpaul case seL4_VCPUReg_CPACR: 48615426Swpaul return writeCPACR_EL1(reg); 48712891Swpaul case seL4_VCPUReg_AFSR0: 48812891Swpaul return writeAFSR0(reg); 48912891Swpaul case seL4_VCPUReg_AFSR1: 490159394Smaxim return writeAFSR1(reg); 491112458Srobert case seL4_VCPUReg_ESR: 492116301Sru return writeESR(reg); 493116301Sru case seL4_VCPUReg_FAR: 494116301Sru return writeFAR(reg); 495112458Srobert case seL4_VCPUReg_ISR: 496112458Srobert /* ISR is read-only */ 497112458Srobert return; 498112458Srobert case seL4_VCPUReg_VBAR: 49912891Swpaul return writeVBAR(reg); 50012891Swpaul case seL4_VCPUReg_TPIDR_EL1: 50112891Swpaul return writeTPIDR_EL1(reg); 50231110Swpaul case seL4_VCPUReg_SP_EL1: 50331110Swpaul return writeSP_EL1(reg); 50431110Swpaul case seL4_VCPUReg_ELR_EL1: 505116301Sru return writeELR_EL1(reg); 50633100Swpaul case seL4_VCPUReg_SPSR_EL1: 50733100Swpaul return writeSPSR_EL1(reg); 50815426Swpaul case seL4_VCPUReg_CNTV_CTL: 50912891Swpaul return writeCNTV_CTL_EL0(reg); 51012891Swpaul case seL4_VCPUReg_CNTV_CVAL: 51131110Swpaul return writeCNTV_CVAL_EL0(reg); 51212891Swpaul case seL4_VCPUReg_CNTVOFF: 51312891Swpaul return writeCNTVOFF_EL2(reg); 51412891Swpaul case seL4_VCPUReg_CNTKCTL_EL1: 51512891Swpaul return writeCNTKCTL_EL1(reg); 51612891Swpaul#ifdef ENABLE_SMP_SUPPORT 51762210Sbrian case seL4_VCPUReg_VMPIDR_EL2: 518116301Sru return writeVMPIDR_EL2(reg); 51912891Swpaul#endif /* ENABLE_SMP_SUPPORT */ 520116301Sru default: 52162210Sbrian fail("ARM/HYP: Invalid register index"); 522116301Sru } 52312891Swpaul 52412891Swpaul return; 52512891Swpaul} 52612891Swpaul 52712891Swpaulstatic inline void vcpu_init_vtcr(void) 528116301Sru{ 529116301Sru 53050159Swpaul /* check that the processor supports the configuration */ 53133100Swpaul uint32_t val; 53215426Swpaul MRS(REG_ID_AA64MMFR0_EL1, val); 53312891Swpaul uint32_t pa_range = ID_AA64MMFR0_EL1_PARANGE(val); 53412891Swpaul if (config_set(CONFIG_ARM_PA_SIZE_BITS_40) && pa_range < PS_1T) { 53512891Swpaul fail("Processor does not support a 40 bit PA"); 53615426Swpaul } 53712891Swpaul if (config_set(CONFIG_ARM_PA_SIZE_BITS_44) && pa_range < PS_16T) { 53812891Swpaul fail("Processor does not support a 44 bit PA"); 539116301Sru } 540116301Sru uint32_t granule = ID_AA64MMFR0_TGRAN4(val); 54150159Swpaul if (granule) { 54233100Swpaul fail("Processor does not support 4KB"); 54315426Swpaul } 54412891Swpaul 54512891Swpaul /* Set up the stage-2 translation control register for cores supporting 44-bit PA */ 54612891Swpaul uint32_t vtcr_el2; 54712891Swpaul#ifdef CONFIG_ARM_PA_SIZE_BITS_40 54812891Swpaul vtcr_el2 = VTCR_EL2_T0SZ(24); // 40-bit input IPA 54912891Swpaul vtcr_el2 |= VTCR_EL2_PS(PS_1T); // 40-bit PA size 550116301Sru vtcr_el2 |= VTCR_EL2_SL0(SL0_4K_L1); // 4KiB, start at level 1 551116301Sru#else 55250159Swpaul vtcr_el2 = VTCR_EL2_T0SZ(20); // 44-bit input IPA 55333100Swpaul vtcr_el2 |= VTCR_EL2_PS(PS_16T); // 44-bit PA size 55415426Swpaul vtcr_el2 |= VTCR_EL2_SL0(SL0_4K_L0); // 4KiB, start at level 0 55512891Swpaul#endif 55612891Swpaul vtcr_el2 |= VTCR_EL2_IRGN0(NORMAL_WB_WA_CACHEABLE); // inner write-back, read/write allocate 55712891Swpaul vtcr_el2 |= VTCR_EL2_ORGN0(NORMAL_WB_WA_CACHEABLE); // outer write-back, read/write allocate 55812891Swpaul vtcr_el2 |= VTCR_EL2_SH0(SH0_INNER); // inner shareable 55912891Swpaul vtcr_el2 |= VTCR_EL2_TG0(TG0_4K); // 4KiB page size 56012891Swpaul vtcr_el2 |= BIT(31); // reserved as 1 561116301Sru 562116301Sru MSR(REG_VTCR_EL2, vtcr_el2); 56350159Swpaul isb(); 56433100Swpaul} 56515426Swpaul 56612891Swpaulstatic inline void armv_vcpu_boot_init(void) 56712891Swpaul{ 56812891Swpaul word_t hcr_el2 = 0; 56912891Swpaul 570157722Sru vcpu_init_vtcr(); 57112891Swpaul 57216732Swpaul hcr_el2 = HCR_NATIVE; 57333100Swpaul MSR(REG_HCR_EL2, hcr_el2); 57433100Swpaul isb(); 57515426Swpaul 57612891Swpaul /* set the SCTLR_EL1 for running native seL4 threads */ 57712891Swpaul MSR(REG_SCTLR_EL1, SCTLR_EL1_NATIVE); 57812891Swpaul isb(); 57912891Swpaul} 58012891Swpaul 58112891Swpaulstatic inline void armv_vcpu_save(vcpu_t *vcpu, UNUSED bool_t active) 58231110Swpaul{ 58331110Swpaul vcpu_save_reg_range(vcpu, seL4_VCPUReg_TTBR0, seL4_VCPUReg_SPSR_EL1); 58431110Swpaul} 585116301Sru 586116301Srustatic inline void vcpu_enable(vcpu_t *vcpu) 58750159Swpaul{ 58833100Swpaul MSR(REG_HCR_EL2, HCR_VCPU); 58915426Swpaul isb(); 59012891Swpaul vcpu_restore_reg(vcpu, seL4_VCPUReg_SCTLR); 59112891Swpaul isb(); 59231110Swpaul 59312891Swpaul set_gic_vcpu_ctrl_hcr(vcpu->vgic.hcr); 59412891Swpaul#ifdef CONFIG_HAVE_FPU 59512891Swpaul vcpu_restore_reg(vcpu, seL4_VCPUReg_CPACR); 59612891Swpaul#endif 59731110Swpaul /* Restore virtual timer state */ 59831110Swpaul restore_virt_timer(vcpu); 59931110Swpaul} 600116301Sru 601116301Srustatic inline void vcpu_disable(vcpu_t *vcpu) 60250159Swpaul{ 60333100Swpaul 60415426Swpaul uint32_t hcr; 60512891Swpaul dsb(); 60612891Swpaul if (likely(vcpu)) { 60731110Swpaul hcr = get_gic_vcpu_ctrl_hcr(); 60817266Speter vcpu->vgic.hcr = hcr; 60931110Swpaul vcpu_save_reg(vcpu, seL4_VCPUReg_SCTLR); 610194968Sbrian#ifdef CONFIG_HAVE_FPU 611194968Sbrian vcpu_save_reg(vcpu, seL4_VCPUReg_CPACR); 612194968Sbrian#endif 613194968Sbrian isb(); 614194968Sbrian } 615194968Sbrian /* Turn off the VGIC */ 616194968Sbrian set_gic_vcpu_ctrl_hcr(0); 617194968Sbrian isb(); 618194968Sbrian 619194968Sbrian /* Stage 1 MMU off */ 620194968Sbrian setSCTLR(SCTLR_DEFAULT); 621194968Sbrian isb(); 622194968Sbrian MSR(REG_HCR_EL2, HCR_NATIVE); 623194968Sbrian isb(); 624194968Sbrian 625194968Sbrian#ifdef CONFIG_HAVE_FPU 626194968Sbrian /* Allow FPU instructions in EL0 and EL1 for native 627194968Sbrian * threads by setting the CPACR_EL1. The CPTR_EL2 is 628194968Sbrian * used to trap the FPU instructions to EL2. 629194968Sbrian */ 630194968Sbrian enableFpuEL01(); 631194968Sbrian#endif 632194968Sbrian if (likely(vcpu)) { 633194968Sbrian /* Save virtual timer state */ 634194968Sbrian save_virt_timer(vcpu); 635194968Sbrian /* Mask the virtual timer interrupt */ 636194968Sbrian maskInterrupt(true, CORE_IRQ_TO_IRQT(CURRENT_CPU_INDEX(), INTERRUPT_VTIMER_EVENT)); 637194968Sbrian } 638194968Sbrian} 639194968Sbrian 64090320Smarkmstatic inline void armv_vcpu_init(vcpu_t *vcpu) 64117266Speter{ 642116301Sru vcpu_write_reg(vcpu, seL4_VCPUReg_SCTLR, SCTLR_EL1_VM); 64317266Speter} 64417266Speter 64517266Speterstatic inline bool_t armv_handleVCPUFault(word_t hsr) 64617266Speter{ 64717266Speter#ifdef CONFIG_HAVE_FPU 64817266Speter if ((ESR_EC(hsr) == ESR_EC_TFP || ESR_EC(hsr) == ESR_EC_CPACR) && !isFpuEnable()) { 64917266Speter handleFPUFault(); 65017266Speter setNextPC(NODE_STATE(ksCurThread), getRestartPC(NODE_STATE(ksCurThread))); 65117266Speter return true; 652116301Sru } 65333100Swpaul#endif 65433100Swpaul 65517266Speter if (hsr == UNKNOWN_FAULT) { 65617266Speter handleUserLevelFault(getESR(), 0); 65717266Speter return true; 658 } 659 660 return false; 661} 662 663#endif /* End of CONFIG_ARM_HYPERVISOR_SUPPORT */ 664 665 666