Support for accessing performance monitoring registers

For now, the primary VM can access all performance monitoring registers, whereas
secondary VMs cannot.  Registers that enable counting or performance-related
interrupts are saved and switched, therefore, the primary VM cannot count events
or set interrupts for secondary VMs.

This code allows us in the future to add performance monitor support to
secondary VMs, and to have fine-grained control over which register accesses are
allowed, either by the primary or secondary, as well as change the behavior for
such accesses.

Bug: 132394973
Change-Id: I89c9f6658d30b8bca3c13ae99c3354f957fd0bb3
diff --git a/src/arch/aarch64/hypervisor/exceptions.S b/src/arch/aarch64/hypervisor/exceptions.S
index 8cca831..e8e391b 100644
--- a/src/arch/aarch64/hypervisor/exceptions.S
+++ b/src/arch/aarch64/hypervisor/exceptions.S
@@ -280,7 +280,15 @@
 	stp x4, x5, [x28], #16
 
 	mrs x6, mdscr_el1
-	str x6, [x28], #16
+	mrs x7, pmccfiltr_el0
+	stp x6, x7, [x28], #16
+
+	mrs x8, pmcr_el0
+	mrs x9, pmcntenset_el0
+	stp x8, x9, [x28], #16
+
+	mrs x10, pmintenset_el1
+	str x10, [x28], #16
 
 	/* Save GIC registers. */
 #if GIC_VERSION == 3 || GIC_VERSION == 4
@@ -438,8 +446,27 @@
 	msr vttbr_el2, x4
 	msr mdcr_el2, x5
 
-	ldr x6, [x28], #16
+	ldp x6, x7, [x28], #16
 	msr mdscr_el1, x6
+	msr pmccfiltr_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
+
+	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
 
 	/* Restore GIC registers. */
 #if GIC_VERSION == 3 || GIC_VERSION == 4