Trap system register accesses to trace registers

Traps system register accesses to trace registers (ETM extension), but has no
effect on accesses through the memory-mapped interface.

Trace registers expose a side-channel that should be disabled system-wide.
Blocking access from the memory-mapped interface is done by not mapping
the address space to these registers. This is to be done in a separate commit,
see bug 143871895.

Additionally, making the register CPU-wide rather than per VM because none of
its fields were being set per VM. This would reduce the overhead of context
switching between VMs.

Bug: 141600635
Change-Id: Id84436c8f39d8bd11e80453d0c6e366d46fe7c20
diff --git a/src/arch/aarch64/cpu.c b/src/arch/aarch64/cpu.c
index 5025009..ba9d27b 100644
--- a/src/arch/aarch64/cpu.c
+++ b/src/arch/aarch64/cpu.c
@@ -78,7 +78,6 @@
 {
 	uintreg_t pc = r->pc;
 	uintreg_t arg = r->r[0];
-	uintreg_t cptr;
 	uintreg_t cnthctl;
 
 	memset_s(r, sizeof(*r), 0, sizeof(*r));
@@ -86,7 +85,6 @@
 	r->pc = pc;
 	r->r[0] = arg;
 
-	cptr = 0;
 	cnthctl = 0;
 
 	if (is_primary) {
@@ -96,7 +94,6 @@
 	}
 
 	r->lazy.hcr_el2 = get_hcr_el2_value(vm_id);
-	r->lazy.cptr_el2 = cptr;
 	r->lazy.cnthctl_el2 = cnthctl;
 	r->lazy.vttbr_el2 = pa_addr(table) | ((uint64_t)vm_id << 48);
 	r->lazy.vmpidr_el2 = vcpu_id;
@@ -147,4 +144,6 @@
 	 * supports them, Hafnium ensures that they are disabled.
 	 */
 	lor_disable();
+
+	write_msr(CPTR_EL2, get_cptr_el2_value());
 }
diff --git a/src/arch/aarch64/hypervisor/exceptions.S b/src/arch/aarch64/hypervisor/exceptions.S
index b8a1fcd..2f47c00 100644
--- a/src/arch/aarch64/hypervisor/exceptions.S
+++ b/src/arch/aarch64/hypervisor/exceptions.S
@@ -271,25 +271,22 @@
 	mrs x25, hcr_el2
 	stp x24, x25, [x28], #16
 
-	mrs x26, cptr_el2
-	mrs x27, cnthctl_el2
+	mrs x26, cnthctl_el2
+	mrs x27, vttbr_el2
 	stp x26, x27, [x28], #16
 
-	mrs x4, vttbr_el2
-	mrs x5, mdcr_el2
+	mrs x4, mdcr_el2
+	mrs x5, mdscr_el1
 	stp x4, x5, [x28], #16
 
-	mrs x6, mdscr_el1
-	mrs x7, pmccfiltr_el0
+	mrs x6, pmccfiltr_el0
+	mrs x7, pmcr_el0
 	stp x6, x7, [x28], #16
 
-	mrs x8, pmcr_el0
-	mrs x9, pmcntenset_el0
+	mrs x8, pmcntenset_el0
+	mrs x9, pmintenset_el1
 	stp x8, x9, [x28], #16
 
-	mrs x10, pmintenset_el1
-	str x10, [x28], #16
-
 	/* Save GIC registers. */
 #if GIC_VERSION == 3 || GIC_VERSION == 4
 	/* Offset is too large, so start from a new base. */
@@ -439,34 +436,32 @@
 	msr hcr_el2, x25
 
 	ldp x26, x27, [x28], #16
-	msr cptr_el2, x26
-	msr cnthctl_el2, x27
+	msr cnthctl_el2, x26
+	msr vttbr_el2, x27
 
 	ldp x4, x5, [x28], #16
-	msr vttbr_el2, x4
-	msr mdcr_el2, x5
+	msr mdcr_el2, x4
+	msr mdscr_el1, x5
 
 	ldp x6, x7, [x28], #16
-	msr mdscr_el1, x6
-	msr pmccfiltr_el0, x7
+	msr pmccfiltr_el0, x6
+	msr pmcr_el0, x7
 
 	ldp x8, x9, [x28], #16
-	msr pmcr_el0, x8
 	/*
 	 * NOTE: Writing 0s to pmcntenset_el0's bits do not alter their values.
 	 * To reset them, clear the register by writing to pmcntenclr_el0.
 	 */
 	mov x27, #0xffffffff
 	msr pmcntenclr_el0, x27
-	msr pmcntenset_el0, x9
+	msr pmcntenset_el0, x8
 
-	ldr x10, [x28], #16
 	/*
 	 * NOTE: Writing 0s to pmintenset_el1's bits do not alter their values.
 	 * To reset them, clear the register by writing to pmintenclr_el1.
 	 */
 	msr pmintenclr_el1, x27
-	msr pmintenset_el1, x10
+	msr pmintenset_el1, x9
 
 	/* Restore GIC registers. */
 #if GIC_VERSION == 3 || GIC_VERSION == 4
diff --git a/src/arch/aarch64/hypervisor/sysregs.c b/src/arch/aarch64/hypervisor/sysregs.c
index 779aa66..dcdf9d6 100644
--- a/src/arch/aarch64/hypervisor/sysregs.c
+++ b/src/arch/aarch64/hypervisor/sysregs.c
@@ -110,3 +110,11 @@
 
 	return mdcr_el2_value;
 }
+
+/**
+ * Returns the value for MDCR_EL2 for the CPU.
+ */
+uintreg_t get_cptr_el2_value(void)
+{
+	return CPTR_EL2_TTA;
+}
diff --git a/src/arch/aarch64/hypervisor/sysregs.h b/src/arch/aarch64/hypervisor/sysregs.h
index f83aa95..63efa1f 100644
--- a/src/arch/aarch64/hypervisor/sysregs.h
+++ b/src/arch/aarch64/hypervisor/sysregs.h
@@ -370,6 +370,15 @@
  */
 #define HCR_EL2_VM (UINT64_C(0x1) << 0)
 
+/**
+ * Trap system register accesses to trace registers.
+ * Traps accesses to ETM registers using the register interface. Does not trap
+ * on accesses through the memory-mapped interface.
+ */
+#define CPTR_EL2_TTA (UINT64_C(0x1) << 28)
+
 uintreg_t get_hcr_el2_value(spci_vm_id_t vm_id);
 
 uintreg_t get_mdcr_el2_value(spci_vm_id_t vm_id);
+
+uintreg_t get_cptr_el2_value(void);
diff --git a/src/arch/aarch64/inc/hf/arch/types.h b/src/arch/aarch64/inc/hf/arch/types.h
index b750631..987fd7b 100644
--- a/src/arch/aarch64/inc/hf/arch/types.h
+++ b/src/arch/aarch64/inc/hf/arch/types.h
@@ -106,7 +106,6 @@
 		uintreg_t spsr_el1;
 		uintreg_t par_el1;
 		uintreg_t hcr_el2;
-		uintreg_t cptr_el2;
 		uintreg_t cnthctl_el2;
 		uintreg_t vttbr_el2;
 		uintreg_t mdcr_el2;