Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
@@ -0,0 +1,250 @@
From f526797b83113cc64e3e658c22d8a5d269896a2a Mon Sep 17 00:00:00 2001
From: Ben Horgan <ben.horgan@arm.com>
Date: Fri, 4 Mar 2022 16:48:14 +0000
Subject: [PATCH] feat: emulate cntp timer register accesses using cnthps
Upstream-Status: Inappropriate [Experimental feature]
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Change-Id: I67508203273baf3bd8e6be2d99717028db945715
---
Makefile | 3 +-
src/arch/aarch64/hypervisor/BUILD.gn | 1 +
src/arch/aarch64/hypervisor/cpu.c | 11 ++-
src/arch/aarch64/hypervisor/handler.c | 6 ++
src/arch/aarch64/hypervisor/timer_el1.c | 104 ++++++++++++++++++++++++
src/arch/aarch64/hypervisor/timer_el1.h | 20 +++++
src/arch/aarch64/msr.h | 8 ++
7 files changed, 150 insertions(+), 3 deletions(-)
create mode 100644 src/arch/aarch64/hypervisor/timer_el1.c
create mode 100644 src/arch/aarch64/hypervisor/timer_el1.h
diff --git a/Makefile b/Makefile
index 95cab9a5..21cca938 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,8 @@ CHECKPATCH := $(CURDIR)/third_party/linux/scripts/checkpatch.pl \
# debug_el1.c : uses XMACROS, which checkpatch doesn't understand.
# perfmon.c : uses XMACROS, which checkpatch doesn't understand.
# feature_id.c : uses XMACROS, which checkpatch doesn't understand.
-CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c"
+# timer_el1.c : uses XMACROS, which checkpatch doesn't understand.
+CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c\|src/arch/aarch64/hypervisor/timer_el1.c"
OUT ?= out/$(PROJECT)
OUT_DIR = out/$(PROJECT)
diff --git a/src/arch/aarch64/hypervisor/BUILD.gn b/src/arch/aarch64/hypervisor/BUILD.gn
index 6068d1e8..de1a414d 100644
--- a/src/arch/aarch64/hypervisor/BUILD.gn
+++ b/src/arch/aarch64/hypervisor/BUILD.gn
@@ -45,6 +45,7 @@ source_set("hypervisor") {
"handler.c",
"perfmon.c",
"psci_handler.c",
+ "timer_el1.c",
"vm.c",
]
diff --git a/src/arch/aarch64/hypervisor/cpu.c b/src/arch/aarch64/hypervisor/cpu.c
index bcf5ffce..d2df77d8 100644
--- a/src/arch/aarch64/hypervisor/cpu.c
+++ b/src/arch/aarch64/hypervisor/cpu.c
@@ -98,13 +98,20 @@ void arch_regs_reset(struct vcpu *vcpu)
if (is_primary) {
/*
* cnthctl_el2 is redefined when VHE is enabled.
- * EL1PCTEN, don't trap phys cnt access.
- * EL1PCEN, don't trap phys timer access.
+ * EL1PCTEN, don't trap phys cnt access. Except when in
+ * secure world without vhe.
+ * EL1PCEN, don't trap phys timer access. Except when in
+ * secure world without vhe.
*/
if (has_vhe_support()) {
cnthctl |= (1U << 10) | (1U << 11);
} else {
+#if SECURE_WORLD == 1
+ cnthctl &= ~(1U << 0);
+ cnthctl &= ~(1U << 1);
+#else
cnthctl |= (1U << 0) | (1U << 1);
+#endif
}
}
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 4bd8a3b4..4c1b6e48 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -34,6 +34,7 @@
#include "psci_handler.h"
#include "smc.h"
#include "sysregs.h"
+#include "timer_el1.h"
/**
* Hypervisor Fault Address Register Non-Secure.
@@ -1277,6 +1278,11 @@ void handle_system_register_access(uintreg_t esr_el2)
inject_el1_unknown_exception(vcpu, esr_el2);
return;
}
+ } else if (timer_el1_is_register_access(esr_el2)) {
+ if (!timer_el1_process_access(vcpu, vm_id, esr_el2)) {
+ inject_el1_unknown_exception(vcpu, esr_el2);
+ return;
+ }
} else {
inject_el1_unknown_exception(vcpu, esr_el2);
return;
diff --git a/src/arch/aarch64/hypervisor/timer_el1.c b/src/arch/aarch64/hypervisor/timer_el1.c
new file mode 100644
index 00000000..c30e5543
--- /dev/null
+++ b/src/arch/aarch64/hypervisor/timer_el1.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2022 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "timer_el1.h"
+
+#include "hf/dlog.h"
+
+#include "msr.h"
+#include "sysregs.h"
+
+/*
+ * Physical timer (CNTP) register encodings as defined in
+ * table D13-8 of the ARMv8 ARM (DDI0487F).
+ * TYPE, op0, op1, crn, crm, op2
+ * The register names are the concatenation of
+ * "CNTP_", TYPE and "_EL2".
+ */
+#define CNTP_REGISTERS \
+ X(CTL, 3, 3, 14, 2, 1) \
+ X(CVAL, 3, 3, 14, 2, 2) \
+ X(TVAL, 3, 3, 14, 2, 0) \
+
+bool timer_el1_is_register_access(uintreg_t esr)
+{
+ uintreg_t sys_register = GET_ISS_SYSREG(esr);
+ bool is_timer_access;
+ switch (sys_register) {
+#define X(type, op0, op1, crn, crm, op2) \
+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
+ is_timer_access = true; \
+ break;
+ CNTP_REGISTERS
+#undef X
+ case (GET_ISS_ENCODING(3, 3, 14, 0, 1)):
+ is_timer_access = true;
+ break;
+ default:
+ is_timer_access = false;
+ }
+
+ return is_timer_access;
+}
+
+/* Accesses to CNTP timer emulated with CNTHPS */
+bool timer_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
+ uintreg_t esr)
+{
+ uintreg_t sys_register = GET_ISS_SYSREG(esr);
+ uintreg_t rt_register = GET_ISS_RT(esr);
+ uintreg_t value;
+
+ if (ISS_IS_READ(esr)) {
+ switch (sys_register) {
+#define X(type, op0, op1, crn, crm, op2) \
+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
+ value = read_msr(MSR_CNTHPS_##type##_EL2); \
+ vcpu->regs.r[rt_register] = value; \
+ break;
+ CNTP_REGISTERS
+#undef X
+ case (GET_ISS_ENCODING(3, 3, 14, 0, 1)):
+ value = read_msr(cntpct_el0);
+ vcpu->regs.r[rt_register] = value;
+ break;
+ default:
+ dlog_notice(
+ "Unsupported timer register "
+ "read: "
+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
+ "rt=%d.\n",
+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
+ GET_ISS_OP2(esr), GET_ISS_RT(esr));
+ break;
+ }
+ } else {
+ value = vcpu->regs.r[rt_register];
+ switch (sys_register) {
+#define X(type, op0, op1, crn, crm, op2) \
+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
+ write_msr(MSR_CNTHPS_##type##_EL2, value); \
+ break;
+ CNTP_REGISTERS
+#undef X
+ default:
+ dlog_notice(
+ "Unsupported timer register "
+ "write: "
+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
+ "rt=%d, value=%d.\n",
+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
+ GET_ISS_OP2(esr), GET_ISS_RT(esr), value);
+ break;
+ }
+ }
+
+ return true;
+}
diff --git a/src/arch/aarch64/hypervisor/timer_el1.h b/src/arch/aarch64/hypervisor/timer_el1.h
new file mode 100644
index 00000000..04a43b6c
--- /dev/null
+++ b/src/arch/aarch64/hypervisor/timer_el1.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#pragma once
+
+#include "hf/arch/types.h"
+
+#include "hf/cpu.h"
+
+#include "vmapi/hf/ffa.h"
+
+bool timer_el1_is_register_access(uintreg_t esr);
+
+bool timer_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
+ uintreg_t esr);
diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h
index cd6778b4..55e78330 100644
--- a/src/arch/aarch64/msr.h
+++ b/src/arch/aarch64/msr.h
@@ -126,3 +126,11 @@
#define MSR_ELR_EL12 S3_5_C4_C0_1
#endif
+
+/*
+ * Secure EL2 Physical timer (CNTHPS) register encodings as defined in
+ * table D13-8 of the ARMv8 ARM (DDI0487F).
+ */
+#define MSR_CNTHPS_CTL_EL2 S3_4_C14_C5_1
+#define MSR_CNTHPS_CVAL_EL2 S3_4_C14_C5_2
+#define MSR_CNTHPS_TVAL_EL2 S3_4_C14_C5_0
@@ -0,0 +1,27 @@
From 613dea068fa546956717ce0b60328e39d451f661 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 29 Apr 2022 20:07:50 +0100
Subject: [PATCH] tc: increase heap pages
Upstream-Status: Pending
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
---
BUILD.gn | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/BUILD.gn b/BUILD.gn
index 6b9b383..62ba763 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -235,7 +235,7 @@ aarch64_toolchains("secure_tc") {
gicd_base_address = "0x30000000"
gicr_base_address = "0x30080000"
gicr_frames = 8
- heap_pages = 60
+ heap_pages = 120
max_cpus = 8
max_vms = 16
branch_protection = "standard"
--
2.30.2
@@ -0,0 +1,157 @@
From 97a8ca1835f5d9512dacda497540d5523e56c7dd Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Tue, 26 Apr 2022 14:43:58 +0100
Subject: [PATCH] feat: emulate interrupt controller register access
This emulates ICC_SGI1R_EL1 and ICC_IGRPEN1_EL1 register
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I0c11f034f3676067597461a183a341c809adcaa4
Upstream-Status: Inappropriate [Experimental feature]
---
src/arch/aarch64/hypervisor/handler.c | 5 ++
src/arch/aarch64/hypervisor/perfmon.c | 84 +++++++++++++++++++++++++++
src/arch/aarch64/hypervisor/perfmon.h | 5 ++
src/arch/aarch64/msr.h | 3 +
4 files changed, 97 insertions(+)
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 4c1b6e48..cd5146bd 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -1283,6 +1283,11 @@ void handle_system_register_access(uintreg_t esr_el2)
inject_el1_unknown_exception(vcpu, esr_el2);
return;
}
+ } else if (intr_ctrl_is_register_access(esr_el2)) {
+ if (!intr_ctrl_el1_process_access(vcpu, vm_id, esr_el2)) {
+ inject_el1_unknown_exception(vcpu, esr_el2);
+ return;
+ }
} else {
inject_el1_unknown_exception(vcpu, esr_el2);
return;
diff --git a/src/arch/aarch64/hypervisor/perfmon.c b/src/arch/aarch64/hypervisor/perfmon.c
index f13b0354..05e216c8 100644
--- a/src/arch/aarch64/hypervisor/perfmon.c
+++ b/src/arch/aarch64/hypervisor/perfmon.c
@@ -116,6 +116,10 @@
X(PMEVTYPER30_EL0 , 3, 3, 14, 15, 6) \
X(PMCCFILTR_EL0 , 3, 3, 14, 15, 7)
+#define INTR_CTRL_REGISTERS \
+ X(ICC_IGRPEN1_EL1 , 3, 0, 12, 12, 7) \
+ X(ICC_SGI1R_EL1 , 3, 0, 12, 11, 5) \
+
/* clang-format on */
/**
@@ -232,3 +236,83 @@ uintreg_t perfmon_get_pmccfiltr_el0_init_value(ffa_vm_id_t vm_id)
return 0;
}
+
+bool intr_ctrl_is_register_access(uintreg_t esr)
+{
+ uintreg_t op0 = GET_ISS_OP0(esr);
+ uintreg_t op1 = GET_ISS_OP1(esr);
+ uintreg_t crn = GET_ISS_CRN(esr);
+ uintreg_t crm = GET_ISS_CRM(esr);
+
+ if (op0 == 3 && op1 == 0 && crn == 12 && crm == 12) {
+ return true;
+ }
+
+ if (op0 == 3 && op1 == 0 && crn == 12 && crm == 11) {
+ return true;
+ }
+
+ return false;
+}
+
+bool intr_ctrl_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
+ uintreg_t esr)
+{
+ uintreg_t sys_register = GET_ISS_SYSREG(esr);
+ uintreg_t rt_register = GET_ISS_RT(esr);
+ uintreg_t value;
+
+ /* +1 because Rt can access register XZR */
+ CHECK(rt_register < NUM_GP_REGS + 1);
+
+ if (ISS_IS_READ(esr)) {
+ switch (sys_register) {
+#define X(reg_name, op0, op1, crn, crm, op2) \
+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
+ value = read_msr(reg_name); \
+ break;
+ INTR_CTRL_REGISTERS
+#undef X
+ default:
+ value = vcpu->regs.r[rt_register];
+ dlog_notice(
+ "Unsupported interrupt control register "
+ "read: "
+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
+ "rt=%d.\n",
+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
+ GET_ISS_OP2(esr), GET_ISS_RT(esr));
+ break;
+ }
+ if (rt_register != RT_REG_XZR) {
+ vcpu->regs.r[rt_register] = value;
+ }
+ } else {
+ if (rt_register != RT_REG_XZR) {
+ value = vcpu->regs.r[rt_register];
+ } else {
+ value = 0;
+ }
+ switch (sys_register) {
+#define X(reg_name, op0, op1, crn, crm, op2) \
+ case (GET_ISS_ENCODING(op0, op1, crn, crm, op2)): \
+ write_msr(reg_name, value); \
+ break;
+ INTR_CTRL_REGISTERS
+#undef X
+ default:
+ dlog_notice(
+ "Unsupported interrupt control register "
+ "write: "
+ "op0=%d, op1=%d, crn=%d, crm=%d, op2=%d, "
+ "rt=%d.\n",
+ GET_ISS_OP0(esr), GET_ISS_OP1(esr),
+ GET_ISS_CRN(esr), GET_ISS_CRM(esr),
+ GET_ISS_OP2(esr), GET_ISS_RT(esr));
+ break;
+ }
+ }
+
+ return true;
+}
diff --git a/src/arch/aarch64/hypervisor/perfmon.h b/src/arch/aarch64/hypervisor/perfmon.h
index 81669ba1..c90d45bf 100644
--- a/src/arch/aarch64/hypervisor/perfmon.h
+++ b/src/arch/aarch64/hypervisor/perfmon.h
@@ -70,3 +70,8 @@ bool perfmon_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
uintreg_t esr_el2);
uintreg_t perfmon_get_pmccfiltr_el0_init_value(ffa_vm_id_t vm_id);
+
+bool intr_ctrl_is_register_access(uintreg_t esr);
+
+bool intr_ctrl_el1_process_access(struct vcpu *vcpu, ffa_vm_id_t vm_id,
+ uintreg_t esr);
diff --git a/src/arch/aarch64/msr.h b/src/arch/aarch64/msr.h
index 55e78330..82aa8846 100644
--- a/src/arch/aarch64/msr.h
+++ b/src/arch/aarch64/msr.h
@@ -134,3 +134,6 @@
#define MSR_CNTHPS_CTL_EL2 S3_4_C14_C5_1
#define MSR_CNTHPS_CVAL_EL2 S3_4_C14_C5_2
#define MSR_CNTHPS_TVAL_EL2 S3_4_C14_C5_0
+
+#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
+#define ICC_SGI1R_EL1 S3_0_C12_C11_5
@@ -0,0 +1,31 @@
From 1fef5bd2504ce3a203c56a3b66dba773cd4893c6 Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Thu, 8 Sep 2022 10:47:10 +0530
Subject: [PATCH] feat(vhe): enable vhe and disable branch protection for TC
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: I60cd607d9f2bf0114b482980e7ca68e24aaf4d1f
Upstream-Status: Pending [Not submitted to upstream yet]
---
BUILD.gn | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/BUILD.gn b/BUILD.gn
index 62ba763..f26ce03 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -238,7 +238,6 @@ aarch64_toolchains("secure_tc") {
heap_pages = 120
max_cpus = 8
max_vms = 16
- branch_protection = "standard"
toolchain_args = {
plat_ffa = "//src/arch/aarch64/plat/ffa:spmc"
plat_psci = "//src/arch/aarch64/plat/psci:spmc"
@@ -247,5 +246,6 @@ aarch64_toolchains("secure_tc") {
secure_world = "1"
pl011_base_address = "0x7ff80000"
enable_mte = "1"
+ enable_vhe = "1"
}
}
@@ -0,0 +1,318 @@
From 1c4d28493faed6cf189c75fa91d19131e6a34e04 Mon Sep 17 00:00:00 2001
From: Olivier Deprez <olivier.deprez@arm.com>
Date: Mon, 8 Aug 2022 19:14:23 +0200
Subject: [PATCH] feat: disable alignment check for EL0 partitions
Relax hw alignment check specifically for (S-)EL0 partitions when
Hafnium runs with VHE enabled. EL1 partitions have a specific control
for EL1 and EL0 with respect to alignment check.
Create a hyp_state structure (from already defined flying registers)
within the vCPU context to hold the Hypervisor EL2 static configuration
applied when a vCPU runs. This state is switched back and forth when
running the Hypervisor or the VM.
Add SCTLR_EL2 to this context. An EL0 partition context is initialized
with SCTLR_EL2.A=0 such that alignment check is disabled when EL0 runs
in the EL2&0 translation regime. SCTLR_EL2.A is set back when returning
to the Hypervisor such that Hypervisor execution runs with aligment
check enabled at EL2.
Remove HCR_EL2 saving from vCPU exit path provided this register state
is static and doesn't change while a vCPU runs.
The rationale for such change is to permit running upstream SW stacks
such as the EDKII/StandaloneMm [1] for which default build assumes
unaligned accesses are permitted. Similar query exists for running
Trusted Services on top of Hafnium [2].
[1] https://github.com/tianocore/edk2/tree/master/StandaloneMmPkg
[2] https://trusted-services.readthedocs.io/en/integration/
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: I2906f4c712425fcfb31adbf89e2e3b9ca293f181
Upstream-Status: Submitted [https://review.trustedfirmware.org/c/hafnium/hafnium/+/16195]
---
src/arch/aarch64/hypervisor/cpu.c | 9 ++++---
src/arch/aarch64/hypervisor/exceptions.S | 32 ++++++++++++++++--------
src/arch/aarch64/hypervisor/feature_id.c | 6 ++---
src/arch/aarch64/hypervisor/handler.c | 18 +++++++------
src/arch/aarch64/inc/hf/arch/types.h | 9 +++++--
src/arch/aarch64/mm.c | 2 +-
src/arch/aarch64/sysregs.c | 11 ++++++--
src/arch/aarch64/sysregs.h | 2 +-
8 files changed, 59 insertions(+), 30 deletions(-)
diff --git a/src/arch/aarch64/hypervisor/cpu.c b/src/arch/aarch64/hypervisor/cpu.c
index d2df77d8..a000159b 100644
--- a/src/arch/aarch64/hypervisor/cpu.c
+++ b/src/arch/aarch64/hypervisor/cpu.c
@@ -115,7 +115,9 @@ void arch_regs_reset(struct vcpu *vcpu)
}
}
- r->hcr_el2 = get_hcr_el2_value(vm_id, vcpu->vm->el0_partition);
+ r->hyp_state.hcr_el2 =
+ get_hcr_el2_value(vm_id, vcpu->vm->el0_partition);
+ r->hyp_state.sctlr_el2 = get_sctlr_el2_value(vcpu->vm->el0_partition);
r->lazy.cnthctl_el2 = cnthctl;
if (vcpu->vm->el0_partition) {
CHECK(has_vhe_support());
@@ -125,10 +127,11 @@ void arch_regs_reset(struct vcpu *vcpu)
* are ignored and treated as 0. There is no need to mask the
* VMID (used as asid) to only 8 bits.
*/
- r->ttbr0_el2 = pa_addr(table) | ((uint64_t)vm_id << 48);
+ r->hyp_state.ttbr0_el2 =
+ pa_addr(table) | ((uint64_t)vm_id << 48);
r->spsr = PSR_PE_MODE_EL0T;
} else {
- r->ttbr0_el2 = read_msr(ttbr0_el2);
+ r->hyp_state.ttbr0_el2 = read_msr(ttbr0_el2);
r->lazy.vtcr_el2 = arch_mm_get_vtcr_el2();
r->lazy.vttbr_el2 = pa_addr(table) | ((uint64_t)vm_id << 48);
#if SECURE_WORLD == 1
diff --git a/src/arch/aarch64/hypervisor/exceptions.S b/src/arch/aarch64/hypervisor/exceptions.S
index 539e196d..d3732f86 100644
--- a/src/arch/aarch64/hypervisor/exceptions.S
+++ b/src/arch/aarch64/hypervisor/exceptions.S
@@ -20,6 +20,9 @@
#define ID_AA64PFR0_SVE_SHIFT (32)
#define ID_AA64PFR0_SVE_LENGTH (4)
+#define SCTLR_EL2_A_SHIFT (1)
+#define HCR_EL2_TGE_SHIFT (27)
+
/**
* Saves the volatile registers into the register buffer of the current vCPU.
*/
@@ -51,8 +54,6 @@
mrs x1, elr_el2
mrs x2, spsr_el2
stp x1, x2, [x18, #VCPU_REGS + 8 * 31]
- mrs x1, hcr_el2
- str x1, [x18, #VCPU_REGS + 8 * 33]
.endm
/**
@@ -871,12 +872,13 @@ vcpu_restore_volatile_and_run:
msr elr_el2, x1
msr spsr_el2, x2
- ldr x1, [x0, #VCPU_REGS + 8 * 33]
+ ldp x1, x2, [x0, #VCPU_REGS + 8 * 33]
msr hcr_el2, x1
+ msr ttbr0_el2, x2
isb
- ldr x1, [x0, #VCPU_REGS + 8 * 34]
- msr ttbr0_el2, x1
+ ldr x1, [x0, #VCPU_REGS + 8 * 35]
+ msr sctlr_el2, x1
isb
/* Restore x0..x3, which we have used as scratch before. */
@@ -886,15 +888,17 @@ vcpu_restore_volatile_and_run:
#if ENABLE_VHE
enable_vhe_tge:
+ mrs x0, id_aa64mmfr1_el1
+ tst x0, #0xf00
+ b.eq 1f
+
/**
* Switch to host mode ({E2H, TGE} = {1,1}) when VHE is enabled.
* Note that E2H is always set when VHE is enabled.
*/
- mrs x0, id_aa64mmfr1_el1
- tst x0, #0xf00
- b.eq 1f
- orr x1, x1, #(1 << 27)
- msr hcr_el2, x1
+ mrs x0, hcr_el2
+ orr x0, x0, #(1 << HCR_EL2_TGE_SHIFT)
+ msr hcr_el2, x0
isb
/**
@@ -905,6 +909,14 @@ enable_vhe_tge:
ldr x0, [x0]
msr ttbr0_el2, x0
isb
+
+ /**
+ * Enable alignment check while Hypervisor runs.
+ */
+ mrs x0, sctlr_el2
+ orr x0, x0, #(1 << SCTLR_EL2_A_SHIFT)
+ msr sctlr_el2, x0
+ isb
1:
ret
#endif
diff --git a/src/arch/aarch64/hypervisor/feature_id.c b/src/arch/aarch64/hypervisor/feature_id.c
index ed3bf8f1..57f32627 100644
--- a/src/arch/aarch64/hypervisor/feature_id.c
+++ b/src/arch/aarch64/hypervisor/feature_id.c
@@ -175,7 +175,7 @@ void feature_set_traps(struct vm *vm, struct arch_regs *regs)
~(ID_AA64MMFR1_EL1_VH_MASK << ID_AA64MMFR1_EL1_VH_SHIFT);
if (features & HF_FEATURE_RAS) {
- regs->hcr_el2 |= HCR_EL2_TERR;
+ regs->hyp_state.hcr_el2 |= HCR_EL2_TERR;
vm->arch.tid3_masks.id_aa64mmfr1_el1 &=
~ID_AA64MMFR1_EL1_SPEC_SEI;
vm->arch.tid3_masks.id_aa64pfr0_el1 &= ~ID_AA64PFR0_EL1_RAS;
@@ -221,14 +221,14 @@ void feature_set_traps(struct vm *vm, struct arch_regs *regs)
}
if (features & HF_FEATURE_LOR) {
- regs->hcr_el2 |= HCR_EL2_TLOR;
+ regs->hyp_state.hcr_el2 |= HCR_EL2_TLOR;
vm->arch.tid3_masks.id_aa64mmfr1_el1 &= ~ID_AA64MMFR1_EL1_LO;
}
if (features & HF_FEATURE_PAUTH) {
/* APK and API bits *enable* trapping when cleared. */
- regs->hcr_el2 &= ~(HCR_EL2_APK | HCR_EL2_API);
+ regs->hyp_state.hcr_el2 &= ~(HCR_EL2_APK | HCR_EL2_API);
vm->arch.tid3_masks.id_aa64isar1_el1 &= ~ID_AA64ISAR1_EL1_GPI;
vm->arch.tid3_masks.id_aa64isar1_el1 &= ~ID_AA64ISAR1_EL1_GPA;
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index cd5146bd..8a3d6289 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -272,9 +272,9 @@ noreturn void sync_current_exception_noreturn(uintreg_t elr, uintreg_t spsr)
static void set_virtual_irq(struct arch_regs *r, bool enable)
{
if (enable) {
- r->hcr_el2 |= HCR_EL2_VI;
+ r->hyp_state.hcr_el2 |= HCR_EL2_VI;
} else {
- r->hcr_el2 &= ~HCR_EL2_VI;
+ r->hyp_state.hcr_el2 &= ~HCR_EL2_VI;
}
}
@@ -283,14 +283,15 @@ static void set_virtual_irq(struct arch_regs *r, bool enable)
*/
static void set_virtual_irq_current(bool enable)
{
- uintreg_t hcr_el2 = current()->regs.hcr_el2;
+ struct vcpu *vcpu = current();
+ uintreg_t hcr_el2 = vcpu->regs.hyp_state.hcr_el2;
if (enable) {
hcr_el2 |= HCR_EL2_VI;
} else {
hcr_el2 &= ~HCR_EL2_VI;
}
- current()->regs.hcr_el2 = hcr_el2;
+ vcpu->regs.hyp_state.hcr_el2 = hcr_el2;
}
/**
@@ -300,9 +301,9 @@ static void set_virtual_irq_current(bool enable)
static void set_virtual_fiq(struct arch_regs *r, bool enable)
{
if (enable) {
- r->hcr_el2 |= HCR_EL2_VF;
+ r->hyp_state.hcr_el2 |= HCR_EL2_VF;
} else {
- r->hcr_el2 &= ~HCR_EL2_VF;
+ r->hyp_state.hcr_el2 &= ~HCR_EL2_VF;
}
}
@@ -311,14 +312,15 @@ static void set_virtual_fiq(struct arch_regs *r, bool enable)
*/
static void set_virtual_fiq_current(bool enable)
{
- uintreg_t hcr_el2 = current()->regs.hcr_el2;
+ struct vcpu *vcpu = current();
+ uintreg_t hcr_el2 = vcpu->regs.hyp_state.hcr_el2;
if (enable) {
hcr_el2 |= HCR_EL2_VF;
} else {
hcr_el2 &= ~HCR_EL2_VF;
}
- current()->regs.hcr_el2 = hcr_el2;
+ vcpu->regs.hyp_state.hcr_el2 = hcr_el2;
}
#if SECURE_WORLD == 1
diff --git a/src/arch/aarch64/inc/hf/arch/types.h b/src/arch/aarch64/inc/hf/arch/types.h
index 6379d73e..6b8b24f1 100644
--- a/src/arch/aarch64/inc/hf/arch/types.h
+++ b/src/arch/aarch64/inc/hf/arch/types.h
@@ -79,8 +79,13 @@ struct arch_regs {
uintreg_t r[NUM_GP_REGS];
uintreg_t pc;
uintreg_t spsr;
- uintreg_t hcr_el2;
- uintreg_t ttbr0_el2;
+
+ /* Hypervisor configuration while a vCPU runs. */
+ struct {
+ uintreg_t hcr_el2;
+ uintreg_t ttbr0_el2;
+ uintreg_t sctlr_el2;
+ } hyp_state;
/*
* System registers.
diff --git a/src/arch/aarch64/mm.c b/src/arch/aarch64/mm.c
index 8ee65ca0..487ae353 100644
--- a/src/arch/aarch64/mm.c
+++ b/src/arch/aarch64/mm.c
@@ -886,7 +886,7 @@ bool arch_mm_init(paddr_t table)
#endif
(0xff << (8 * STAGE1_NORMALINDX)),
- .sctlr_el2 = get_sctlr_el2_value(),
+ .sctlr_el2 = get_sctlr_el2_value(false),
.vstcr_el2 = (1U << 31) | /* RES1. */
(0 << 30) | /* SA. */
(0 << 29) | /* SW. */
diff --git a/src/arch/aarch64/sysregs.c b/src/arch/aarch64/sysregs.c
index e8c154b1..087ba4ed 100644
--- a/src/arch/aarch64/sysregs.c
+++ b/src/arch/aarch64/sysregs.c
@@ -159,7 +159,7 @@ uintreg_t get_cptr_el2_value(void)
/**
* Returns the value for SCTLR_EL2 for the CPU.
*/
-uintreg_t get_sctlr_el2_value(void)
+uintreg_t get_sctlr_el2_value(bool is_el0_partition)
{
uintreg_t sctlr_el2_value = 0;
@@ -173,7 +173,14 @@ uintreg_t get_sctlr_el2_value(void)
/* MMU-related bits. */
sctlr_el2_value |= SCTLR_EL2_M;
- sctlr_el2_value |= SCTLR_EL2_A;
+
+ /*
+ * Alignment check enabled, but in the case of an EL0 partition
+ * with VHE enabled.
+ */
+ if (!(has_vhe_support() && is_el0_partition)) {
+ sctlr_el2_value |= SCTLR_EL2_A;
+ }
sctlr_el2_value |= SCTLR_EL2_C;
sctlr_el2_value |= SCTLR_EL2_SA;
sctlr_el2_value |= SCTLR_EL2_I;
diff --git a/src/arch/aarch64/sysregs.h b/src/arch/aarch64/sysregs.h
index babd2375..6fdab58e 100644
--- a/src/arch/aarch64/sysregs.h
+++ b/src/arch/aarch64/sysregs.h
@@ -668,7 +668,7 @@ uintreg_t get_mdcr_el2_value(void);
uintreg_t get_cptr_el2_value(void);
-uintreg_t get_sctlr_el2_value(void);
+uintreg_t get_sctlr_el2_value(bool is_el0_partition);
/**
* Branch Target Identification mechanism support in AArch64 state.
@@ -0,0 +1,41 @@
From 4b59905d2fec01cc17038b1c167b4e57e7835adf Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Thu, 7 Oct 2021 12:20:08 +0530
Subject: [PATCH] feat(vhe): set STAGE1_NS while mapping memory from NWd to SWd
If the memory is shared by a VM executing in non secure world, attribute
MM_MODE_NS had to be set while mapping that in a S-EL0 SP executing in
secure world. It will not be needed for a S-EL1 SP since the NS bit is
available only for the stage 1 translations and the stage 1 translations
for a S-EL1 SP will be handled by a trusted OS running in S-EL1.
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: I074e2d5a50a659bd3c097d797c4901f08d210b1b
Upstream-Status: Pending [Not submitted to upstream yet]
---
src/ffa_memory.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/ffa_memory.c b/src/ffa_memory.c
index 048cca9c..8910cc79 100644
--- a/src/ffa_memory.c
+++ b/src/ffa_memory.c
@@ -2483,6 +2483,18 @@ struct ffa_value ffa_memory_retrieve(struct vm_locked to_locked,
memory_to_attributes = ffa_memory_permissions_to_mode(
permissions, share_state->sender_orig_mode);
+
+ if (to_locked.vm->el0_partition) {
+ /*
+ * Get extra mapping attributes for the given VM ID.
+ * If the memory is shared by a VM executing in non secure
+ * world, attribute MM_MODE_NS had to be set while mapping
+ * that in a SP executing in secure world.
+ */
+ memory_to_attributes |= arch_mm_extra_attributes_from_vm(
+ retrieve_request->sender);
+ }
+
ret = ffa_retrieve_check_update(
to_locked, memory_region->sender, share_state->fragments,
share_state->fragment_constituent_counts,
@@ -0,0 +1,25 @@
# TC specific configuration
COMPATIBLE_MACHINE = "(tc?)"
HAFNIUM_PLATFORM = "secure_tc"
# Intermediate SHA with 2.7 baseline version
SRCREV = "dd0561820946fe23bcd57cc129140437f72102a5"
PV = "2.7+git${SRCPV}"
FILESEXTRAPATHS:prepend:tc := "${THISDIR}/files/tc:"
SRC_URI:remove = "file://0003-Fix-build-with-clang-15.patch"
SRC_URI:append = " \
file://0001-feat-emulate-cntp-timer-register-accesses-using-cnth.patch \
file://0002-feat-emulate-interrupt-controller-register-access.patch \
file://0003-feat-disable-alignment-check-for-EL0-partitions.patch \
file://0004-feat-vhe-set-STAGE1_NS-while-mapping-memory-from-NWd.patch \
file://0001-tc-increase-heap-pages.patch;patchdir=project/reference \
file://0002-feat-vhe-enable-vhe-and-disable-branch-protection-fo.patch;patchdir=project/reference \
"
do_compile() {
PATH="${S}/prebuilts/linux-x64/clang/bin:$PATH" oe_runmake -C ${S}
}
@@ -0,0 +1,6 @@
# Machine specific configurations
MACHINE_HAFNIUM_REQUIRE ?= ""
MACHINE_HAFNIUM_REQUIRE:tc = "hafnium-tc.inc"
require ${MACHINE_HAFNIUM_REQUIRE}