mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-26 08:20:18 +00:00
hv_exc, hv.py: Add support for interrupting guest with ^C
Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
1ce8d8b706
commit
75f206e65c
3 changed files with 42 additions and 3 deletions
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import sys, traceback, struct, array, bisect, os
|
import sys, traceback, struct, array, bisect, os, signal
|
||||||
|
|
||||||
from construct import *
|
from construct import *
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ EvtMMIOTrace = Struct(
|
||||||
class HV_EVENT(IntEnum):
|
class HV_EVENT(IntEnum):
|
||||||
HOOK_VM = 1
|
HOOK_VM = 1
|
||||||
VTIMER = 2
|
VTIMER = 2
|
||||||
|
USER_INTERRUPT = 3
|
||||||
|
|
||||||
VMProxyHookData = Struct(
|
VMProxyHookData = Struct(
|
||||||
"flags" / RegAdapter(MMIOTraceFlags),
|
"flags" / RegAdapter(MMIOTraceFlags),
|
||||||
|
@ -98,6 +99,8 @@ class HV:
|
||||||
self.symbols = []
|
self.symbols = []
|
||||||
self.sysreg = {}
|
self.sysreg = {}
|
||||||
self.novm = False
|
self.novm = False
|
||||||
|
self._in_handler = False
|
||||||
|
self._sigint_pending = False
|
||||||
self.vm_hooks = []
|
self.vm_hooks = []
|
||||||
|
|
||||||
def unmap(self, ipa, size):
|
def unmap(self, ipa, size):
|
||||||
|
@ -328,6 +331,8 @@ class HV:
|
||||||
return self.handle_hvc(ctx)
|
return self.handle_hvc(ctx)
|
||||||
|
|
||||||
def handle_exception(self, reason, code, info):
|
def handle_exception(self, reason, code, info):
|
||||||
|
self._in_handler = True
|
||||||
|
|
||||||
info_data = self.iface.readmem(info, ExcInfo.sizeof())
|
info_data = self.iface.readmem(info, ExcInfo.sizeof())
|
||||||
self.ctx = ctx = ExcInfo.parse(info_data)
|
self.ctx = ctx = ExcInfo.parse(info_data)
|
||||||
|
|
||||||
|
@ -348,18 +353,23 @@ class HV:
|
||||||
elif code == HV_EVENT.VTIMER:
|
elif code == HV_EVENT.VTIMER:
|
||||||
print("Step")
|
print("Step")
|
||||||
handled = True
|
handled = True
|
||||||
|
elif code == HV_EVENT.USER_INTERRUPT:
|
||||||
|
handled = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Python exception while handling guest exception:")
|
print(f"Python exception while handling guest exception:")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
if handled:
|
if handled:
|
||||||
ret = EXC_RET.HANDLED
|
ret = EXC_RET.HANDLED
|
||||||
|
if self._sigint_pending:
|
||||||
|
print("User interrupt")
|
||||||
else:
|
else:
|
||||||
print(f"Guest exception: {reason.name}/{code.name}")
|
print(f"Guest exception: {reason.name}/{code.name}")
|
||||||
|
|
||||||
self.u.print_exception(code, ctx)
|
self.u.print_exception(code, ctx)
|
||||||
|
|
||||||
if self._stepping or not handled:
|
if self._sigint_pending or self._stepping or not handled:
|
||||||
|
|
||||||
|
self._sigint_pending = False
|
||||||
self._stepping = False
|
self._stepping = False
|
||||||
|
|
||||||
locals = {
|
locals = {
|
||||||
|
@ -374,7 +384,9 @@ class HV:
|
||||||
if callable(a):
|
if callable(a):
|
||||||
locals[attr] = getattr(self, attr)
|
locals[attr] = getattr(self, attr)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
ret = shell.run_shell(locals, "Entering debug shell", "Returning from exception")
|
ret = shell.run_shell(locals, "Entering debug shell", "Returning from exception")
|
||||||
|
signal.signal(signal.SIGINT, self._handle_sigint)
|
||||||
|
|
||||||
if ret is None:
|
if ret is None:
|
||||||
ret = EXC_RET.EXIT_GUEST
|
ret = EXC_RET.EXIT_GUEST
|
||||||
|
@ -387,6 +399,10 @@ class HV:
|
||||||
ret = EXC_RET.STEP
|
ret = EXC_RET.STEP
|
||||||
self.p.exit(ret)
|
self.p.exit(ret)
|
||||||
|
|
||||||
|
self._in_handler = False
|
||||||
|
if self._sigint_pending:
|
||||||
|
self._handle_sigint()
|
||||||
|
|
||||||
def skip(self):
|
def skip(self):
|
||||||
self.ctx.elr += 4
|
self.ctx.elr += 4
|
||||||
raise shell.ExitConsole(EXC_RET.HANDLED)
|
raise shell.ExitConsole(EXC_RET.HANDLED)
|
||||||
|
@ -502,6 +518,7 @@ class HV:
|
||||||
self.iface.set_handler(START.EXCEPTION_LOWER, EXC.FIQ, 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_LOWER, EXC.SERROR, self.handle_exception)
|
||||||
self.iface.set_handler(START.EXCEPTION, EXC.FIQ, self.handle_exception)
|
self.iface.set_handler(START.EXCEPTION, EXC.FIQ, self.handle_exception)
|
||||||
|
self.iface.set_handler(START.HV, HV_EVENT.USER_INTERRUPT, self.handle_exception)
|
||||||
self.iface.set_handler(START.HV, HV_EVENT.HOOK_VM, 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_handler(START.HV, HV_EVENT.VTIMER, self.handle_exception)
|
||||||
self.iface.set_event_handler(EVENT.MMIOTRACE, self.handle_mmiotrace)
|
self.iface.set_event_handler(EVENT.MMIOTRACE, self.handle_mmiotrace)
|
||||||
|
@ -690,6 +707,15 @@ class HV:
|
||||||
|
|
||||||
self.iface.writemem(guest_base + self.bootargs_off, BootArgs.build(self.tba))
|
self.iface.writemem(guest_base + self.bootargs_off, BootArgs.build(self.tba))
|
||||||
|
|
||||||
|
def _handle_sigint(self, signal=None, stack=None):
|
||||||
|
self._sigint_pending = True
|
||||||
|
|
||||||
|
if self._in_handler:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Kick the proxy to break out of the hypervisor
|
||||||
|
self.iface.dev.write(b"!")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
print(f"Disabling other iodevs...")
|
print(f"Disabling other iodevs...")
|
||||||
for iodev in IODEV:
|
for iodev in IODEV:
|
||||||
|
@ -709,6 +735,7 @@ class HV:
|
||||||
print(f"Jumping to entrypoint at 0x{self.entry:x}")
|
print(f"Jumping to entrypoint at 0x{self.entry:x}")
|
||||||
|
|
||||||
self.iface.dev.timeout = None
|
self.iface.dev.timeout = None
|
||||||
|
signal.signal(signal.SIGINT, self._handle_sigint)
|
||||||
|
|
||||||
# Does not return
|
# Does not return
|
||||||
self.p.hv_start(self.entry, self.guest_base + self.bootargs_off)
|
self.p.hv_start(self.entry, self.guest_base + self.bootargs_off)
|
||||||
|
|
1
src/hv.h
1
src/hv.h
|
@ -30,6 +30,7 @@ struct hv_vm_proxy_hook_data {
|
||||||
typedef enum _hv_entry_type {
|
typedef enum _hv_entry_type {
|
||||||
HV_HOOK_VM = 1,
|
HV_HOOK_VM = 1,
|
||||||
HV_VTIMER,
|
HV_VTIMER,
|
||||||
|
HV_USER_INTERRUPT,
|
||||||
} hv_entry_type;
|
} hv_entry_type;
|
||||||
|
|
||||||
/* VM */
|
/* VM */
|
||||||
|
|
11
src/hv_exc.c
11
src/hv_exc.c
|
@ -57,6 +57,12 @@ void hv_exc_proxy(u64 *regs, uartproxy_boot_reason_t reason, uartproxy_exc_code_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hv_exc_exit(u64 *regs)
|
||||||
|
{
|
||||||
|
if (iodev_can_read(uartproxy_iodev))
|
||||||
|
hv_exc_proxy(regs, START_HV, HV_USER_INTERRUPT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void hv_exc_sync(u64 *regs)
|
void hv_exc_sync(u64 *regs)
|
||||||
{
|
{
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
@ -73,11 +79,14 @@ void hv_exc_sync(u64 *regs)
|
||||||
msr(ELR_EL2, mrs(ELR_EL2) + 4);
|
msr(ELR_EL2, mrs(ELR_EL2) + 4);
|
||||||
else
|
else
|
||||||
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_SYNC, NULL);
|
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_SYNC, NULL);
|
||||||
|
|
||||||
|
hv_exc_exit(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hv_exc_irq(u64 *regs)
|
void hv_exc_irq(u64 *regs)
|
||||||
{
|
{
|
||||||
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_IRQ, NULL);
|
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_IRQ, NULL);
|
||||||
|
hv_exc_exit(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hv_exc_fiq(u64 *regs)
|
void hv_exc_fiq(u64 *regs)
|
||||||
|
@ -106,9 +115,11 @@ void hv_exc_fiq(u64 *regs)
|
||||||
reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_IMODE_MASK);
|
reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_IMODE_MASK);
|
||||||
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_FIQ, NULL);
|
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_FIQ, NULL);
|
||||||
}
|
}
|
||||||
|
hv_exc_exit(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hv_exc_serr(u64 *regs)
|
void hv_exc_serr(u64 *regs)
|
||||||
{
|
{
|
||||||
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_SERROR, NULL);
|
hv_exc_proxy(regs, START_EXCEPTION_LOWER, EXC_SERROR, NULL);
|
||||||
|
hv_exc_exit(regs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue