mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-23 07:03:08 +00:00
hv: Support cleanly exiting the hypervisor from an exception
Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
d35fa5e0fc
commit
a3440f2b48
6 changed files with 62 additions and 20 deletions
|
@ -54,20 +54,23 @@ class HV:
|
||||||
for attr in dir(self):
|
for attr in dir(self):
|
||||||
locals[attr] = getattr(self, attr)
|
locals[attr] = getattr(self, attr)
|
||||||
|
|
||||||
shell.run_shell(locals, "Entering debug shell", "Returning from exception")
|
ret = shell.run_shell(locals, "Entering debug shell", "Returning from exception")
|
||||||
|
|
||||||
|
if ret is None:
|
||||||
|
ret = EXC_RET.HANDLED
|
||||||
|
|
||||||
self.iface.writemem(info, ExcInfo.build(self.ctx))
|
self.iface.writemem(info, ExcInfo.build(self.ctx))
|
||||||
self.p.exit(EXC_RET.HANDLED)
|
self.p.exit(ret)
|
||||||
|
|
||||||
def skip(self):
|
def skip(self):
|
||||||
self.ctx.elr += 4
|
self.ctx.elr += 4
|
||||||
raise shell.ExitConsole()
|
raise shell.ExitConsole(EXC_RET.HANDLED)
|
||||||
|
|
||||||
def cont(self):
|
def cont(self):
|
||||||
raise shell.ExitConsole()
|
raise shell.ExitConsole(EXC_RET.HANDLED)
|
||||||
|
|
||||||
def exit(self):
|
def exit(self):
|
||||||
sys.exit(0)
|
raise shell.ExitConsole(EXC_RET.EXIT_GUEST)
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.adt = load_adt(self.u.get_adt())
|
self.adt = load_adt(self.u.get_adt())
|
||||||
|
|
|
@ -90,6 +90,7 @@ class EXC(IntEnum):
|
||||||
class EXC_RET(IntEnum):
|
class EXC_RET(IntEnum):
|
||||||
UNHANDLED = 1
|
UNHANDLED = 1
|
||||||
HANDLED = 2
|
HANDLED = 2
|
||||||
|
EXIT_GUEST = 3
|
||||||
|
|
||||||
ExcInfo = Struct(
|
ExcInfo = Struct(
|
||||||
"spsr" / RegAdapter(SPSR),
|
"spsr" / RegAdapter(SPSR),
|
||||||
|
@ -802,7 +803,6 @@ class M1N1Proxy:
|
||||||
def hv_map(self, from_, to, size, incr):
|
def hv_map(self, from_, to, size, incr):
|
||||||
return self.request(self.P_HV_MAP, from_, to, size, incr)
|
return self.request(self.P_HV_MAP, from_, to, size, incr)
|
||||||
def hv_start(self, entry, *args):
|
def hv_start(self, entry, *args):
|
||||||
# does not return
|
|
||||||
return self.request(self.P_HV_START, entry, *args)
|
return self.request(self.P_HV_START, entry, *args)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
4
src/hv.c
4
src/hv.c
|
@ -4,7 +4,7 @@
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "cpu_regs.h"
|
#include "cpu_regs.h"
|
||||||
|
|
||||||
void hv_enter_guest(u64 x0, u64 x1, u64 x2, u64 x3, void *entry) __attribute__((noreturn));
|
void hv_enter_guest(u64 x0, u64 x1, u64 x2, u64 x3, void *entry);
|
||||||
|
|
||||||
extern char _hv_vectors_start[0];
|
extern char _hv_vectors_start[0];
|
||||||
|
|
||||||
|
@ -38,4 +38,6 @@ void hv_start(void *entry, u64 regs[4])
|
||||||
msr(VBAR_EL1, _hv_vectors_start);
|
msr(VBAR_EL1, _hv_vectors_start);
|
||||||
|
|
||||||
hv_enter_guest(regs[0], regs[1], regs[2], regs[3], entry);
|
hv_enter_guest(regs[0], regs[1], regs[2], regs[3], entry);
|
||||||
|
|
||||||
|
printf("Exiting hypervisor.\n");
|
||||||
}
|
}
|
||||||
|
|
31
src/hv_asm.S
31
src/hv_asm.S
|
@ -84,6 +84,17 @@ _v_hv_serr:
|
||||||
.globl hv_enter_guest
|
.globl hv_enter_guest
|
||||||
.type hv_enter_guest, @function
|
.type hv_enter_guest, @function
|
||||||
hv_enter_guest:
|
hv_enter_guest:
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
stp x27, x28, [sp, #-16]!
|
||||||
|
stp x25, x26, [sp, #-16]!
|
||||||
|
stp x23, x24, [sp, #-16]!
|
||||||
|
stp x21, x22, [sp, #-16]!
|
||||||
|
stp x19, x20, [sp, #-16]!
|
||||||
|
str x18, [sp, #-16]!
|
||||||
|
|
||||||
|
mov x5, sp
|
||||||
|
msr tpidr_el2, x5
|
||||||
|
|
||||||
mrs x5, daif
|
mrs x5, daif
|
||||||
msr daifclr, 3
|
msr daifclr, 3
|
||||||
mov x6, #5
|
mov x6, #5
|
||||||
|
@ -91,8 +102,24 @@ hv_enter_guest:
|
||||||
msr spsr_el2, x5
|
msr spsr_el2, x5
|
||||||
|
|
||||||
msr elr_el2, x4
|
msr elr_el2, x4
|
||||||
msr spsel, #0
|
|
||||||
mov x5, #0
|
mov x5, #0
|
||||||
mov sp, x5
|
msr sp_el0, x5
|
||||||
|
msr sp_el1, x5
|
||||||
|
|
||||||
eret
|
eret
|
||||||
|
|
||||||
|
.globl hv_exit_guest
|
||||||
|
.type hv_exit_guest, @function
|
||||||
|
hv_exit_guest:
|
||||||
|
mrs x5, tpidr_el2
|
||||||
|
mov sp, x5
|
||||||
|
|
||||||
|
ldr x18, [sp], #16
|
||||||
|
ldp x19, x20, [sp], #16
|
||||||
|
ldp x21, x22, [sp], #16
|
||||||
|
ldp x23, x24, [sp], #16
|
||||||
|
ldp x25, x26, [sp], #16
|
||||||
|
ldp x27, x28, [sp], #16
|
||||||
|
ldp x29, x30, [sp], #16
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
15
src/hv_exc.c
15
src/hv_exc.c
|
@ -7,6 +7,8 @@
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "uartproxy.h"
|
#include "uartproxy.h"
|
||||||
|
|
||||||
|
void hv_exit_guest(void) __attribute__((noreturn));
|
||||||
|
|
||||||
static void hv_exc_proxy(u64 *regs, uartproxy_exc_code_t type)
|
static void hv_exc_proxy(u64 *regs, uartproxy_exc_code_t type)
|
||||||
{
|
{
|
||||||
struct uartproxy_exc_info exc_info = {
|
struct uartproxy_exc_info exc_info = {
|
||||||
|
@ -27,18 +29,25 @@ static void hv_exc_proxy(u64 *regs, uartproxy_exc_code_t type)
|
||||||
|
|
||||||
int ret = uartproxy_run(&start);
|
int ret = uartproxy_run(&start);
|
||||||
|
|
||||||
if (ret == EXC_RET_HANDLED) {
|
switch (ret) {
|
||||||
|
case EXC_RET_HANDLED:
|
||||||
memcpy(regs, exc_info.regs, sizeof(exc_info.regs));
|
memcpy(regs, exc_info.regs, sizeof(exc_info.regs));
|
||||||
msr(SPSR_EL2, exc_info.spsr);
|
msr(SPSR_EL2, exc_info.spsr);
|
||||||
msr(ELR_EL2, exc_info.elr);
|
msr(ELR_EL2, exc_info.elr);
|
||||||
msr(SP_EL0, exc_info.sp[0]);
|
msr(SP_EL0, exc_info.sp[0]);
|
||||||
msr(SP_EL1, exc_info.sp[1]);
|
msr(SP_EL1, exc_info.sp[1]);
|
||||||
return;
|
return;
|
||||||
}
|
case EXC_EXIT_GUEST:
|
||||||
|
hv_exit_guest();
|
||||||
|
default:
|
||||||
printf("Guest exception not handled, rebooting.\n");
|
printf("Guest exception not handled, rebooting.\n");
|
||||||
print_regs(regs, 0);
|
print_regs(regs, 0);
|
||||||
|
for (int i = 0; i < 300; i++) {
|
||||||
|
iodev_console_kick();
|
||||||
|
udelay(1000);
|
||||||
|
}
|
||||||
reboot();
|
reboot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hv_exc_sync(u64 *regs)
|
void hv_exc_sync(u64 *regs)
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef enum _uartproxy_exc_code_t {
|
||||||
typedef enum _uartproxy_exc_ret_t {
|
typedef enum _uartproxy_exc_ret_t {
|
||||||
EXC_RET_UNHANDLED = 1,
|
EXC_RET_UNHANDLED = 1,
|
||||||
EXC_RET_HANDLED = 2,
|
EXC_RET_HANDLED = 2,
|
||||||
|
EXC_EXIT_GUEST = 3,
|
||||||
} uartproxy_exc_ret_t;
|
} uartproxy_exc_ret_t;
|
||||||
|
|
||||||
struct uartproxy_exc_info {
|
struct uartproxy_exc_info {
|
||||||
|
|
Loading…
Reference in a new issue