hw: x86_64: clean up vCPU startup

- and store the vCPU startup state in a dedicated enum
- return the STARTUP exit from Vm::run()
- initialize the vCPU from Vm::proceed() instead of Vm::exception()

Fix genodelabs/genode#5450
This commit is contained in:
Benjamin Lamowski 2025-02-03 13:54:21 +01:00 committed by Christian Helmuth
parent faa5b9ca40
commit 759bfec3a9
6 changed files with 56 additions and 30 deletions

View File

@ -132,12 +132,7 @@ class Kernel::Vm : private Kernel::Object, public Cpu_context
** Vm_session **
****************/
void run()
{
_sync_from_vmm();
if (_scheduled != ACTIVE) Cpu_context::_activate();
_scheduled = ACTIVE;
}
void run();
void pause()
{

View File

@ -84,6 +84,14 @@ void Vm::proceed()
}
void Vm::run()
{
_sync_from_vmm();
if (_scheduled != ACTIVE) Cpu_context::_activate();
_scheduled = ACTIVE;
}
void Vm::_sync_to_vmm()
{}

View File

@ -205,6 +205,14 @@ void Kernel::Vm::proceed()
}
void Vm::run()
{
_sync_from_vmm();
if (_scheduled != ACTIVE) Cpu_context::_activate();
_scheduled = ACTIVE;
}
void Vm::_sync_to_vmm()
{}

View File

@ -212,6 +212,14 @@ void Vm::proceed()
}
void Vm::run()
{
_sync_from_vmm();
if (_scheduled != ACTIVE) Cpu_context::_activate();
_scheduled = ACTIVE;
}
void Vm::_sync_to_vmm()
{}

View File

@ -35,14 +35,12 @@ namespace Board {
enum Platform_exitcodes : uint64_t {
EXIT_NPF = 0xfc,
EXIT_INIT = 0xfd,
EXIT_STARTUP = 0xfe,
EXIT_PAUSED = 0xff,
};
enum Custom_trapnos : uint64_t {
TRAP_VMEXIT = 256,
TRAP_VMSKIP = 257,
};
};
@ -55,6 +53,12 @@ namespace Kernel {
struct Board::Vcpu_context
{
enum class Init_state {
CREATED,
INITIALIZING,
STARTED
};
Vcpu_context(unsigned id, Vcpu_data &vcpu_data);
void initialize(Kernel::Cpu &cpu, addr_t table_phys_addr);
void read_vcpu_state(Vcpu_state &state);
@ -66,7 +70,10 @@ struct Board::Vcpu_context
uint64_t tsc_aux_host = 0U;
uint64_t tsc_aux_guest = 0U;
uint64_t exit_reason = EXIT_INIT;
uint64_t exit_reason = EXIT_PAUSED;
Init_state init_state { Init_state::CREATED };
static Virt_interface &detect_virtualization(Vcpu_data &vcpu_data,
unsigned id)

View File

@ -54,16 +54,31 @@ Vm::~Vm()
}
void Vm::run()
{
if (_vcpu_context.init_state == Board::Vcpu_context::Init_state::CREATED) {
_vcpu_context.exit_reason = Board::EXIT_STARTUP;
_vcpu_context.init_state = Board::Vcpu_context::Init_state::INITIALIZING;
_context.submit(1);
return;
}
_sync_from_vmm();
if (_scheduled != ACTIVE) Cpu_context::_activate();
_scheduled = ACTIVE;
}
void Vm::proceed()
{
using namespace Board;
_cpu().switch_to(*_vcpu_context.regs);
if (_vcpu_context.exit_reason == EXIT_INIT) {
_vcpu_context.regs->trapno = TRAP_VMSKIP;
Hypervisor::restore_state_for_entry((addr_t)&_vcpu_context.regs->r8,
_vcpu_context.regs->fpu_context());
/* jumps to _kernel_entry */
if (_vcpu_context.init_state == Board::Vcpu_context::Init_state::INITIALIZING) {
_vcpu_context.initialize(_cpu(),
reinterpret_cast<addr_t>(_id.table));
_vcpu_context.tsc_aux_host = _cpu().id();
}
Cpu::Ia32_tsc_aux::write(
@ -125,18 +140,6 @@ void Vm::exception()
case Cpu_state::INTERRUPTS_START ... Cpu_state::INTERRUPTS_END:
_interrupt(_user_irq_pool);
break;
case TRAP_VMSKIP:
/* vCPU is running for the first time */
_vcpu_context.initialize(_cpu(),
reinterpret_cast<addr_t>(_id.table));
_vcpu_context.tsc_aux_host = _cpu().id();
/*
* We set the artificial startup exit code, stop the
* vCPU thread and ask the VMM to handle it.
*/
_vcpu_context.exit_reason = EXIT_STARTUP;
pause = true;
break;
default:
error("VM: triggered unknown exception ",
_vcpu_context.regs->trapno,
@ -169,13 +172,10 @@ void Vm::_sync_to_vmm()
void Vm::_sync_from_vmm()
{
/* first run() will skip through to issue startup exit */
if (_vcpu_context.exit_reason == Board::EXIT_INIT)
return;
_vcpu_context.read_vcpu_state(_state);
}
Board::Vcpu_context::Vcpu_context(unsigned id, Vcpu_data &vcpu_data)
:
regs(1),