diff --git a/proxyclient/hv.py b/proxyclient/hv.py index 5662c28c..380f66f9 100644 --- a/proxyclient/hv.py +++ b/proxyclient/hv.py @@ -31,6 +31,7 @@ EvtMMIOTrace = Struct( class HV_EVENT(IntEnum): HOOK_VM = 1 + VTIMER = 2 VMProxyHookData = Struct( "flags" / RegAdapter(MMIOTraceFlags), @@ -92,7 +93,7 @@ class HV: self.vbar_el1 = None self.want_vbar = None self.vectors = [None] - self.step = False + self._stepping = False self.sym_offset = 0 self.symbols = [] self.sysreg = {} @@ -344,6 +345,9 @@ class HV: code = HV_EVENT(code) if code == HV_EVENT.HOOK_VM: handled = self.handle_vm_hook(ctx) + elif code == HV_EVENT.VTIMER: + print("Step") + handled = True except Exception as e: print(f"Python exception while handling guest exception:") traceback.print_exc() @@ -355,6 +359,9 @@ class HV: self.u.print_exception(code, ctx) + if self._stepping or not handled: + self._stepping = False + locals = { "hv": self, "iface": self.iface, @@ -376,7 +383,7 @@ class HV: if new_info != info_data: self.iface.writemem(info, new_info) - if ret == EXC_RET.HANDLED and self.step: + if ret == EXC_RET.HANDLED and self._stepping: ret = EXC_RET.STEP self.p.exit(ret) @@ -387,6 +394,10 @@ class HV: def cont(self): raise shell.ExitConsole(EXC_RET.HANDLED) + def step(self): + self._stepping = True + raise shell.ExitConsole(EXC_RET.STEP) + def exit(self): raise shell.ExitConsole(EXC_RET.EXIT_GUEST) @@ -490,7 +501,9 @@ class HV: self.iface.set_handler(START.EXCEPTION_LOWER, EXC.IRQ, self.handle_exception) self.iface.set_handler(START.EXCEPTION_LOWER, EXC.FIQ, self.handle_exception) self.iface.set_handler(START.EXCEPTION_LOWER, EXC.SERROR, self.handle_exception) + self.iface.set_handler(START.EXCEPTION, EXC.FIQ, self.handle_exception) self.iface.set_handler(START.HV, HV_EVENT.HOOK_VM, self.handle_exception) + self.iface.set_handler(START.HV, HV_EVENT.VTIMER, self.handle_exception) self.iface.set_event_handler(EVENT.MMIOTRACE, self.handle_mmiotrace) self.map_hw(0x2_00000000, 0x2_00000000, 0x5_00000000) diff --git a/src/hv.c b/src/hv.c index b9c26b89..355bcb19 100644 --- a/src/hv.c +++ b/src/hv.c @@ -5,10 +5,14 @@ #include "cpu_regs.h" #include "utils.h" +#define HV_TICK_RATE 1000 + void hv_enter_guest(u64 x0, u64 x1, u64 x2, u64 x3, void *entry); extern char _hv_vectors_start[0]; +u64 hv_tick_interval; + void hv_init(void) { // Enable physical timer for EL1 @@ -28,6 +32,9 @@ void hv_init(void) // No guest vectors initially msr(VBAR_EL12, 0); + // Compute tick interval + hv_tick_interval = mrs(CNTFRQ_EL0) / HV_TICK_RATE; + sysop("dsb ishst"); sysop("tlbi alle1is"); sysop("dsb ish"); @@ -38,7 +45,19 @@ void hv_start(void *entry, u64 regs[4]) { msr(VBAR_EL1, _hv_vectors_start); + hv_arm_tick(); hv_enter_guest(regs[0], regs[1], regs[2], regs[3], entry); printf("Exiting hypervisor.\n"); } + +void hv_arm_tick(void) +{ + msr(CNTP_TVAL_EL0, hv_tick_interval); + msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE); +} + +void hv_tick(void) +{ + // printf("HV tick!\n"); +} diff --git a/src/hv.h b/src/hv.h index 27855deb..f127dc2a 100644 --- a/src/hv.h +++ b/src/hv.h @@ -29,6 +29,7 @@ struct hv_vm_proxy_hook_data { typedef enum _hv_entry_type { HV_HOOK_VM = 1, + HV_VTIMER, } hv_entry_type; /* VM */ @@ -53,5 +54,7 @@ void hv_exc_proxy(u64 *regs, uartproxy_boot_reason_t reason, uartproxy_exc_code_ /* HV main */ void hv_init(void); void hv_start(void *entry, u64 regs[4]); +void hv_arm_tick(void); +void hv_tick(void); #endif diff --git a/src/hv_exc.c b/src/hv_exc.c index ad3dbc63..683a205f 100644 --- a/src/hv_exc.c +++ b/src/hv_exc.c @@ -82,7 +82,30 @@ void hv_exc_irq(u64 *regs) void hv_exc_fiq(u64 *regs) { - hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_FIQ, NULL); + if (mrs(CNTP_CTL_EL0) == (CNTx_CTL_ISTATUS | CNTx_CTL_ENABLE)) { + msr(CNTP_CTL_EL0, CNTx_CTL_ISTATUS | CNTx_CTL_IMASK | CNTx_CTL_ENABLE); + hv_tick(); + hv_arm_tick(); + } + + if (mrs(CNTV_CTL_EL0) == (CNTx_CTL_ISTATUS | CNTx_CTL_ENABLE)) { + msr(CNTV_CTL_EL0, CNTx_CTL_ISTATUS | CNTx_CTL_IMASK | CNTx_CTL_ENABLE); + hv_exc_proxy(regs, START_HV, HV_VTIMER, NULL); + } + + u64 reg = mrs(SYS_IMP_APL_PMCR0); + if ((reg & (PMCR0_IMODE_MASK | PMCR0_IACT)) == (PMCR0_IMODE_FIQ | PMCR0_IACT)) { + printf("[FIQ] PMC IRQ, masking"); + reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK); + hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_FIQ, NULL); + } + + reg = mrs(SYS_IMP_APL_UPMCR0); + if ((reg & UPMCR0_IMODE_MASK) == UPMCR0_IMODE_FIQ && (mrs(SYS_IMP_APL_UPMSR) & UPMSR_IACT)) { + printf("[FIQ] UPMC IRQ, masking"); + reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_IMODE_MASK); + hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_FIQ, NULL); + } } void hv_exc_serr(u64 *regs)