| /* |
| * Copyright 2019 The Hafnium Authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "sysregs.h" |
| |
| #include "msr.h" |
| |
| /** |
| * RAS Extension version. |
| */ |
| #define ID_AA64PFR0_EL1_RAS (UINT64_C(0xf) << 28) |
| |
| /** |
| * Returns true if the current processor supports the RAS extension. |
| */ |
| static bool has_ras_support(void) |
| { |
| return read_msr(ID_AA64PFR0_EL1) & ID_AA64PFR0_EL1_RAS; |
| } |
| |
| /** |
| * Returns the value for HCR_EL2 for the particular VM. |
| * For now, the primary VM has one value and all secondary VMs share a value. |
| */ |
| uintreg_t get_hcr_el2_value(ffa_vm_id_t vm_id) |
| { |
| uintreg_t hcr_el2_value = 0; |
| |
| /* Baseline values for all VMs. */ |
| |
| /* |
| * Trap access to registers in ID group 3. These registers report on |
| * the underlying support for CPU features. Because Hafnium restricts |
| * certain features, e.g., RAS, it should emulate access to these |
| * registers to report the correct set of features supported. |
| */ |
| hcr_el2_value |= HCR_EL2_TID3; |
| |
| /* Execution state for EL1 is AArch64. */ |
| hcr_el2_value |= HCR_EL2_RW; |
| |
| /* Trap implementation registers and functionality. */ |
| hcr_el2_value |= HCR_EL2_TACR | HCR_EL2_TIDCP; |
| |
| /* Trap SMC instructions. */ |
| hcr_el2_value |= HCR_EL2_TSC; |
| |
| /* |
| * Translation table access made as part of a stage 1 translation |
| * table walk is subject to a stage 2 translation; |
| */ |
| hcr_el2_value |= HCR_EL2_PTW; |
| |
| /* Enable stage 2 address translation;*/ |
| hcr_el2_value |= HCR_EL2_VM; |
| |
| /* Trap cache maintenance instructions that operate by Set/Way. */ |
| hcr_el2_value |= HCR_EL2_TSW; |
| |
| /* Do *not* trap PAuth. APK and API bits *disable* trapping when set. */ |
| hcr_el2_value |= HCR_EL2_APK | HCR_EL2_API; |
| |
| /* Baseline values for all secondary VMs. */ |
| if (vm_id != HF_PRIMARY_VM_ID) { |
| /* |
| * Set the minimum shareability domain to barrier instructions |
| * as inner shareable. |
| */ |
| hcr_el2_value |= HCR_EL2_BSU_INNER_SHAREABLE; |
| |
| /* |
| * Broadcast instructions related to invalidating the TLB within |
| * the Inner Shareable domain. |
| */ |
| hcr_el2_value |= HCR_EL2_FB; |
| |
| /* |
| * Route physical IRQ/FIQ interrupts to EL2. Do not route |
| * SError exceptions to EL2 (AMO). Instead let each VM handle |
| * it. Not setting AMO requires explicit Error Synchronisation |
| * Barrier instructions (esb) on hypervisor entry/exit, or |
| * implicit barriers (SCTLR_EL2_IESB is set). |
| */ |
| hcr_el2_value |= HCR_EL2_IMO | HCR_EL2_FMO; |
| |
| if (!has_ras_support()) { |
| /* |
| * Trap SErrors into EL2 if the processor does not |
| * support RAS, because without error synchronization |
| * barriers, isolating SErrors could impose a high |
| * overhead. RAS is mandatory from Armv8.2, so this |
| * should not be common. |
| */ |
| hcr_el2_value |= HCR_EL2_AMO; |
| } |
| |
| /* Trap wait for event/interrupt instructions. */ |
| hcr_el2_value |= HCR_EL2_TWE | HCR_EL2_TWI; |
| } |
| |
| return hcr_el2_value; |
| } |
| |
| /** |
| * Returns the default value for MDCR_EL2. |
| */ |
| uintreg_t get_mdcr_el2_value(void) |
| { |
| uintreg_t mdcr_el2_value = read_msr(MDCR_EL2); |
| uintreg_t pmcr_el0 = read_msr(PMCR_EL0); |
| |
| /* Baseline values for all VMs. */ |
| |
| /* Disable cycle and event counting at EL2. */ |
| mdcr_el2_value |= MDCR_EL2_HCCD | MDCR_EL2_HPMD; |
| |
| /* All available event counters accessible from all exception levels. */ |
| mdcr_el2_value |= GET_PMCR_EL0_N(pmcr_el0) & MDCR_EL2_HPMN; |
| |
| return mdcr_el2_value; |
| } |
| |
| /** |
| * Returns the value for CPTR_EL2 for the CPU. |
| */ |
| uintreg_t get_cptr_el2_value(void) |
| { |
| return CPTR_EL2_TTA; |
| } |
| |
| /** |
| * Returns the value for SCTLR_EL2 for the CPU. |
| */ |
| uintreg_t get_sctlr_el2_value(void) |
| { |
| uintreg_t sctlr_el2_value = 0; |
| |
| /* |
| * Implicit Error Synchronization Barrier (Armv8.2-IESB). This feature |
| * is mandatory from Armv8.2 onwards. |
| * Hafnium uses it to ensure that all SError exceptions are caught by |
| * the VM responsible for it. |
| */ |
| sctlr_el2_value |= SCTLR_EL2_IESB; |
| |
| /* MMU-related bits. */ |
| sctlr_el2_value |= SCTLR_EL2_M; |
| sctlr_el2_value |= SCTLR_EL2_A; |
| sctlr_el2_value |= SCTLR_EL2_C; |
| sctlr_el2_value |= SCTLR_EL2_SA; |
| sctlr_el2_value |= SCTLR_EL2_I; |
| sctlr_el2_value |= SCTLR_EL2_WXN; |
| |
| /* RES1 Bits. */ |
| sctlr_el2_value |= SCTLR_EL2_B4; |
| sctlr_el2_value |= SCTLR_EL2_B16; |
| sctlr_el2_value |= SCTLR_EL2_B18; |
| sctlr_el2_value |= SCTLR_EL2_B28; |
| |
| /* Unsupported features that otherwise are RES1. */ |
| sctlr_el2_value |= SCTLR_EL2_EOS; |
| sctlr_el2_value |= SCTLR_EL2_EIS; |
| |
| return sctlr_el2_value; |
| } |