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/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 39bf58c..e72d69e 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -32,6 +32,7 @@
#include "debug_el1.h"
#include "msr.h"
+#include "perfmon.h"
#include "psci.h"
#include "psci_handler.h"
#include "smc.h"
@@ -631,16 +632,26 @@
CHECK(ec == 0x18);
/*
- * Handle accesses to debug registers.
+ * Handle accesses to debug and performance monitor registers.
* Abort when encountering unhandled register accesses.
*/
- if (is_debug_el1_register_access(esr) &&
- debug_el1_process_access(vcpu, vm_id, esr)) {
- /* Instruction was fulfilled. Skip it and run the next one. */
- vcpu->regs.pc += GET_NEXT_PC_INC(esr);
- return NULL;
+ if (debug_el1_is_register_access(esr)) {
+ if (!debug_el1_process_access(vcpu, vm_id, esr)) {
+ goto fail;
+ }
+ } else if (perfmon_is_register_access(esr)) {
+ if (!perfmon_process_access(vcpu, vm_id, esr)) {
+ goto fail;
+ }
+ } else {
+ goto fail;
}
+ /* Instruction was fulfilled. Skip it and run the next one. */
+ vcpu->regs.pc += GET_NEXT_PC_INC(esr);
+ return NULL;
+
+fail:
direction_str = ISS_IS_READ(esr) ? "read" : "write";
dlog("Unhandled system register %s: op0=%d, op1=%d, crn=%d, "