diff --git a/repos/base-hw/src/core/spec/x86_64/virtualization/hypervisor.h b/repos/base-hw/src/core/spec/x86_64/virtualization/hypervisor.h
deleted file mode 100644
index 86c3935257..0000000000
--- a/repos/base-hw/src/core/spec/x86_64/virtualization/hypervisor.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * \brief Interface between kernel and hypervisor
- * \author Benjamin Lamowski
- * \date 2022-10-14
- */
-
-/*
- * Copyright (C) 2022 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU Affero General Public License version 3.
- */
-
-#ifndef _SPEC__PC__VIRTUALIZATION_HYPERVISOR_H_
-#define _SPEC__PC__VIRTUALIZATION_HYPERVISOR_H_
-
-#include
-#include
-
-namespace Hypervisor {
-
- using Call_arg = Genode::umword_t;
- using Call_ret = Genode::umword_t;
-
-
- inline void restore_state_for_entry(Call_arg regs, Call_arg fpu_context)
- {
- asm volatile(
- "fxrstor (%[fpu_context]);"
- "mov %[regs], %%rsp;"
- "popq %%r8;"
- "popq %%r9;"
- "popq %%r10;"
- "popq %%r11;"
- "popq %%r12;"
- "popq %%r13;"
- "popq %%r14;"
- "popq %%r15;"
- "popq %%rax;"
- "popq %%rbx;"
- "popq %%rcx;"
- "popq %%rdx;"
- "popq %%rdi;"
- "popq %%rsi;"
- "popq %%rbp;"
- "sti;" /* maybe enter the kernel to handle an external
- interrupt that occured ... */
- "nop;"
- "cli;" /* ... otherwise, just disable interrupts again */
- "jmp _kernel_entry;"
- :
- : [regs] "r"(regs), [fpu_context] "r"(fpu_context)
-
- : "memory");
- };
-}
-
-#endif /* _SPEC__PC__VIRTUALIZATION_HYPERVISOR_H_ */
diff --git a/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/svm.cc b/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/svm.cc
index 9246d870d2..51ae02d399 100644
--- a/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/svm.cc
+++ b/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/svm.cc
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -496,7 +497,7 @@ void Vmcb::switch_world(Core::Cpu::Context ®s, addr_t stack_start)
that occured ... */
"nop;"
"cli;" /* ... otherwise, just disable interrupts again */
- "subq $568, %%rsp;" /* keep room for fpu and general-purpose registers */
+ "subq %[stack_offset], %%rsp;" /* keep room for fpu and general-purpose registers */
"pushq %[trap_vmexit];" /* make the stack point to trapno, the right place
to jump to _kernel_entry. We push 256 because
this is outside of the valid range for interrupts
@@ -504,11 +505,12 @@ void Vmcb::switch_world(Core::Cpu::Context ®s, addr_t stack_start)
"jmp _kernel_entry;" /* jump to _kernel_entry to save the
GPRs without breaking any */
:
- : [regs] "r" (®s.r8),
- [fpu_context] "r" (®s.fpu_context()),
- [guest_state] "r" (vcpu_data.phys_addr + get_page_size()),
- [host_state] "r" (root_vmcb_phys),
- [stack] "r" (stack_start),
- [trap_vmexit] "i"(TRAP_VMEXIT)
+ : [regs] "r" (®s.r8),
+ [fpu_context] "r" (®s.fpu_context()),
+ [guest_state] "r" (vcpu_data.phys_addr + get_page_size()),
+ [host_state] "r" (root_vmcb_phys),
+ [stack] "r" (stack_start),
+ [stack_offset] "i" (Hw::Mm::KERNEL_STACK_ERRCODE_OFFSET),
+ [trap_vmexit] "i"(TRAP_VMEXIT)
: "rax", "memory");
}
diff --git a/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vm.cc
index 5a6cc3bbc7..9d67040677 100644
--- a/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vm.cc
+++ b/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vm.cc
@@ -24,7 +24,6 @@
#include
#include
-#include
#include
#include
@@ -77,6 +76,13 @@ void Vm::proceed()
_vcpu_context.initialize(_cpu(),
reinterpret_cast(_id.table));
_vcpu_context.tsc_aux_host = _cpu().id();
+ _vcpu_context.init_state = Board::Vcpu_context::Init_state::STARTED;
+
+ /*
+ * Sync the initial state from the VMM that was skipped due to
+ * the vCPU being uninitialized.
+ */
+ _sync_from_vmm();
}
Cpu::Ia32_tsc_aux::write(
@@ -161,6 +167,15 @@ void Vm::exception(Genode::Cpu_state &state)
void Vm::_sync_to_vmm()
{
+ /*
+ * If the vCPU isn't initialized, sync instructions such as vmread may fail.
+ * Just sync the startup exit and skip the rest of the synchronization.
+ */
+ if (_vcpu_context.init_state != Board::Vcpu_context::Init_state::STARTED) {
+ _state.exit_reason = (unsigned) Board::EXIT_STARTUP;
+ return;
+ }
+
_vcpu_context.write_vcpu_state(_state);
/*
@@ -173,6 +188,13 @@ void Vm::_sync_to_vmm()
void Vm::_sync_from_vmm()
{
+ /*
+ * Syncing the state to an unitialized vCPU may fail.
+ * The inial state from the VMM will be synced after vCPU initialization.
+ */
+ if (_vcpu_context.init_state != Board::Vcpu_context::Init_state::STARTED)
+ return;
+
_vcpu_context.read_vcpu_state(_state);
}
diff --git a/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vmx.cc b/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vmx.cc
index 6ee5bd3150..d7ac07f098 100644
--- a/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vmx.cc
+++ b/repos/base-hw/src/core/spec/x86_64/virtualization/kernel/vmx.cc
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -363,10 +364,11 @@ void Vmcs::initialize(Kernel::Cpu &cpu, Genode::addr_t page_table_phys)
write(E_HOST_IA32_SYSENTER_EIP, reinterpret_cast(&kernel_entry_push_trap));
/*
- * Set the RSP to trapno, so that _kernel_entry will save the registers
- * into the right fields.
+ * Set the RSP to a stack offset such that kernel_entry_push_trap pushes
+ * the `TRAP_VMEXIT` value to the right place for consumption by the
+ * subsequent jump to _kernel_entry.
*/
- write(E_HOST_RSP, cpu.stack_start() - 568);
+ write(E_HOST_RSP, cpu.stack_start() - Hw::Mm::KERNEL_STACK_ERRCODE_OFFSET);
write(E_HOST_RIP, reinterpret_cast(&kernel_entry_push_trap));
}
diff --git a/repos/base-hw/src/lib/hw/spec/64bit/memory_consts.s b/repos/base-hw/src/lib/hw/spec/64bit/memory_consts.s
index f4dc117e2f..e1d6240ba6 100644
--- a/repos/base-hw/src/lib/hw/spec/64bit/memory_consts.s
+++ b/repos/base-hw/src/lib/hw/spec/64bit/memory_consts.s
@@ -16,8 +16,9 @@
#namespace Hw {
# namespace Mm {
-HW_MM_KERNEL_START = 0xffffffc000000000
-HW_MM_KERNEL_STACK_SIZE = 0x10000
+HW_MM_KERNEL_START = 0xffffffc000000000
+HW_MM_KERNEL_STACK_SIZE = 0x10000
+HW_MM_KERNEL_STACK_ERRCODE_OFFSET = 568
HW_MM_CPU_LOCAL_MEMORY_AREA_START = 0xffffffe070000000
HW_MM_CPU_LOCAL_MEMORY_AREA_SIZE = 0x10000000