diff options
author | Todd Clayton <Todd.Clayton@Sun.COM> | 2009-10-24 11:04:55 -0700 |
---|---|---|
committer | Todd Clayton <Todd.Clayton@Sun.COM> | 2009-10-24 11:04:55 -0700 |
commit | 530f2c280d739b194cfbb75f25352b75bb99b4b2 (patch) | |
tree | 00097103202108aead1536c3d0fe39685516b93f /usr/src | |
parent | fcc214c383d20beb968b623b83d851672e174702 (diff) | |
download | illumos-gate-530f2c280d739b194cfbb75f25352b75bb99b4b2.tar.gz |
6818123 booting sn1 branded zone in 64-bit dom0 causes xvm panic
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/i86pc/ml/syscall_asm_amd64.s | 47 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/sys/machprivregs.h | 12 |
2 files changed, 48 insertions, 11 deletions
diff --git a/usr/src/uts/i86pc/ml/syscall_asm_amd64.s b/usr/src/uts/i86pc/ml/syscall_asm_amd64.s index c8ed8ecaaf..d8aa1396c9 100644 --- a/usr/src/uts/i86pc/ml/syscall_asm_amd64.s +++ b/usr/src/uts/i86pc/ml/syscall_asm_amd64.s @@ -366,12 +366,11 @@ __no_rupdate_msg: * [1] They used to, and we relied on it, but this was broken in 3.1.1. * Sigh. */ - #if defined(__xpv) -#define XPV_SYSCALL_PROD \ - XPV_TRAP_POP; \ - movq (%rsp), %rcx; \ - movq 0x10(%rsp), %r11 +#define XPV_SYSCALL_PROD \ + movq 0x10(%rsp), %rcx; \ + movq 0x20(%rsp), %r11; \ + movq 0x28(%rsp), %rsp #else #define XPV_SYSCALL_PROD /* nothing */ #endif @@ -409,12 +408,7 @@ noprod_sys_syscall: ASSERT_UPCALL_MASK_IS_SET movq %r15, %gs:CPU_RTMP_R15 -#if defined(__xpv) - movq 0x18(%rsp), %r15 /* save user stack */ - movq %r15, %gs:CPU_RTMP_RSP -#else movq %rsp, %gs:CPU_RTMP_RSP -#endif /* __xpv */ movq %gs:CPU_THREAD, %r15 movq T_STACK(%r15), %rsp @@ -589,9 +583,42 @@ _syscall_invoke: * in sn1_brand_syscall_callback for an example. */ ASSERT_UPCALL_MASK_IS_SET +#if defined(__xpv) + SYSRETQ + ALTENTRY(nopop_sys_syscall_swapgs_sysretq) + + /* + * We can only get here after executing a brand syscall + * interposition callback handler and simply need to + * "sysretq" back to userland. On the hypervisor this + * involves the iret hypercall which requires us to construct + * just enough of the stack needed for the hypercall. + * (rip, cs, rflags, rsp, ss). + */ + movq %rsp, %gs:CPU_RTMP_RSP /* save user's rsp */ + movq %gs:CPU_THREAD, %r11 + movq T_STACK(%r11), %rsp + + movq %rcx, REGOFF_RIP(%rsp) + movl $UCS_SEL, REGOFF_CS(%rsp) + movq %gs:CPU_RTMP_RSP, %r11 + movq %r11, REGOFF_RSP(%rsp) + pushfq + popq %r11 /* hypercall enables ints */ + movq %r11, REGOFF_RFL(%rsp) + movl $UDS_SEL, REGOFF_SS(%rsp) + addq $REGOFF_RIP, %rsp + /* + * XXPV: see comment in SYSRETQ definition for future optimization + * we could take. + */ + ASSERT_UPCALL_MASK_IS_SET + SYSRETQ +#else ALTENTRY(nopop_sys_syscall_swapgs_sysretq) SWAPGS /* user gsbase */ SYSRETQ +#endif /*NOTREACHED*/ SET_SIZE(nopop_sys_syscall_swapgs_sysretq) diff --git a/usr/src/uts/i86xpv/sys/machprivregs.h b/usr/src/uts/i86xpv/sys/machprivregs.h index 35df0b99e9..64780f0c4e 100644 --- a/usr/src/uts/i86xpv/sys/machprivregs.h +++ b/usr/src/uts/i86xpv/sys/machprivregs.h @@ -372,7 +372,17 @@ extern "C" { ud2 /* die nastily if we return! */ #define IRET HYPERVISOR_IRET(0) -#define SYSRETQ HYPERVISOR_IRET(VGCF_IN_KERNEL) + +/* + * XXPV: Normally we would expect to use sysret to return from kernel to + * user mode when using the syscall instruction. The iret hypercall + * does support both iret and sysret semantics. For us to use sysret + * style would require that we use the hypervisor's private descriptors + * that obey syscall instruction's imposed segment selector ordering. + * With iret we can use whatever %cs value we choose. We should fix + * this to use sysret one day. + */ +#define SYSRETQ HYPERVISOR_IRET(0) #define SYSRETL ud2 /* 32-bit syscall/sysret not supported */ #define SWAPGS /* empty - handled in hypervisor */ |