mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-26 08:20:18 +00:00
hv: Implement a periodic hypervisor ptimer and use vtimer for stepping
Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
76c283deba
commit
2e014f58fa
4 changed files with 61 additions and 3 deletions
|
@ -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)
|
||||
|
|
19
src/hv.c
19
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");
|
||||
}
|
||||
|
|
3
src/hv.h
3
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
|
||||
|
|
25
src/hv_exc.c
25
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)
|
||||
|
|
Loading…
Reference in a new issue