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