x86/c_traps.c: add clobbers in 32-bit VMX restore

The inline assembly blocks for vmlaunch and vmresume in the 32-bit
restore_vmx() function manually pop guest state into all general-purpose
registers.

Previously, these registers were not included in the inline assembly
clobber list. If a VM entry fails, execution falls through to the
vmlaunch_failed() C function. Because the compiler is unaware that the
registers were overwritten, it may generate code for the failure handler
that relies on destroyed state.

Signed-off-by: Bill Nguyen <bill.nguyen@unsw.edu.au>
This commit is contained in:
Bill Nguyen 2026-05-25 13:05:00 +10:00 committed by Indan Zupancic
parent 84d60b58a1
commit 7eac2ceab8

View file

@ -36,11 +36,12 @@ static void NORETURN restore_vmx(tcb_t *cur_thread, vcpu_t *vcpu)
/* Do not support breakpoints in VMs, so just disable all breakpoints */
loadAllDisabledBreakpointState(cur_thread);
#endif
word_t *guest_regs_ptr = vcpu->gp_registers;
if (vcpu->launched) {
/* attempt to do a vmresume */
asm volatile(
// Set our stack pointer to the top of the tcb so we can efficiently pop
"movl %0, %%esp\n"
"movl %[guest_regs], %%esp\n"
"popl %%eax\n"
"popl %%ebx\n"
"popl %%ecx\n"
@ -57,18 +58,17 @@ static void NORETURN restore_vmx(tcb_t *cur_thread, vcpu_t *vcpu)
"leal kernel_stack_alloc + %c1, %%esp\n"
#endif
"call vmlaunch_failed\n"
:
: "r"(&vcpu->gp_registers[VCPU_EAX]),
"i"(BIT(CONFIG_KERNEL_STACK_BITS) - sizeof(word_t))
: [guest_regs] "+a"(guest_regs_ptr)
: "i"(BIT(CONFIG_KERNEL_STACK_BITS) - sizeof(word_t))
// Clobber memory so the compiler is forced to complete all stores
// before running this assembler
: "memory"
: "ebx", "ecx", "edx", "esi", "edi", "ebp", "memory"
);
} else {
/* attempt to do a vmlaunch */
asm volatile(
// Set our stack pointer to the top of the tcb so we can efficiently pop
"movl %0, %%esp\n"
"movl %[guest_regs], %%esp\n"
"popl %%eax\n"
"popl %%ebx\n"
"popl %%ecx\n"
@ -85,12 +85,11 @@ static void NORETURN restore_vmx(tcb_t *cur_thread, vcpu_t *vcpu)
"leal kernel_stack_alloc + %c1, %%esp\n"
#endif
"call vmlaunch_failed\n"
:
: "r"(&vcpu->gp_registers[VCPU_EAX]),
"i"(BIT(CONFIG_KERNEL_STACK_BITS) - sizeof(word_t))
: [guest_regs] "+a"(guest_regs_ptr)
: "i"(BIT(CONFIG_KERNEL_STACK_BITS) - sizeof(word_t))
// Clobber memory so the compiler is forced to complete all stores
// before running this assembler
: "memory"
: "ebx", "ecx", "edx", "esi", "edi", "ebp", "memory"
);
}
UNREACHABLE();