mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
hw: generalize virtualization memory
The initial vCPU memory was written for AMD's SVM. Make the vCPU memory provider virtualization technology agnostic. Issue #5113
This commit is contained in:
parent
e82859444e
commit
3a88d133ed
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Genode Labs GmbH
|
||||
* Copyright (C) 2022-2024 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.
|
||||
@ -23,15 +23,20 @@ namespace Genode {
|
||||
/**
|
||||
* CPU context of a virtual machine
|
||||
*/
|
||||
struct Vcpu_data;
|
||||
}
|
||||
struct Vcpu_data
|
||||
{
|
||||
void * virt_area;
|
||||
addr_t phys_addr;
|
||||
Vcpu_state *vcpu_state;
|
||||
|
||||
struct Genode::Vcpu_data
|
||||
{
|
||||
alignas(Genode::get_page_size())
|
||||
uint8_t vmcb[get_page_size()];
|
||||
Genode::addr_t vmcb_phys_addr;
|
||||
Genode::Vcpu_state * vcpu_state;
|
||||
static constexpr size_t num_pages() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
static constexpr size_t size() {
|
||||
return get_page_size() * num_pages();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__PC__VM_STATE_H_ */
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include <spec/x86_64/virtualization/svm.h>
|
||||
#include <cpu.h>
|
||||
|
||||
using Genode::addr_t;
|
||||
using Genode::uint64_t;
|
||||
|
||||
namespace Board {
|
||||
|
||||
using Vm_page_table = Hw::Page_table;
|
||||
@ -62,15 +65,18 @@ namespace Kernel {
|
||||
struct Board::Vcpu_context
|
||||
{
|
||||
Vcpu_context(unsigned id, void *vcpu_data_ptr);
|
||||
Vcpu_context(unsigned id, void *virt_area, addr_t vmcb_phys_addr);
|
||||
void initialize_svm(Kernel::Cpu &cpu, void *table);
|
||||
void read_vcpu_state(Genode::Vcpu_state &state);
|
||||
void write_vcpu_state(Genode::Vcpu_state &state);
|
||||
void read_vcpu_state(Vcpu_state &state);
|
||||
void write_vcpu_state(Vcpu_state &state);
|
||||
|
||||
Vmcb &vmcb;
|
||||
addr_t vmcb_phys_addr;
|
||||
|
||||
Vmcb &vmcb;
|
||||
Genode::Align_at<Core::Cpu::Context> regs;
|
||||
Genode::uint64_t tsc_aux_host = 0U;
|
||||
Genode::uint64_t tsc_aux_guest = 0U;
|
||||
Genode::uint64_t exitcode = EXIT_INIT;
|
||||
uint64_t tsc_aux_host = 0U;
|
||||
uint64_t tsc_aux_guest = 0U;
|
||||
uint64_t exitcode = EXIT_INIT;
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__PC__VIRTUALIZATION__BOARD_H_ */
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022-2023 Genode Labs GmbH
|
||||
* Copyright (C) 2022-2024 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.
|
||||
@ -47,7 +47,7 @@ Vm::Vm(Irq::Pool & user_irq_pool,
|
||||
_state(*data.vcpu_state),
|
||||
_context(context),
|
||||
_id(id),
|
||||
_vcpu_context(id.id, data.vmcb)
|
||||
_vcpu_context(id.id, data.virt_area, data.phys_addr)
|
||||
{
|
||||
affinity(cpu);
|
||||
}
|
||||
@ -78,9 +78,8 @@ void Vm::proceed(Cpu & cpu)
|
||||
* we can pop it later
|
||||
*/
|
||||
_vcpu_context.regs->trapno = _vcpu_context.vmcb.root_vmcb_phys;
|
||||
Hypervisor::switch_world(_vcpu_context.vmcb.vcpu_data()->vmcb_phys_addr,
|
||||
(addr_t) &_vcpu_context.regs->r8,
|
||||
_vcpu_context.regs->fpu_context());
|
||||
Hypervisor::switch_world( _vcpu_context.vmcb_phys_addr,
|
||||
(addr_t)&_vcpu_context.regs->r8, _vcpu_context.regs->fpu_context());
|
||||
/*
|
||||
* This will fall into an interrupt or otherwise jump into
|
||||
* _kernel_entry
|
||||
@ -175,9 +174,12 @@ void Vm::_sync_from_vmm()
|
||||
}
|
||||
|
||||
|
||||
Board::Vcpu_context::Vcpu_context(unsigned id, void *vcpu_data_ptr)
|
||||
Board::Vcpu_context::Vcpu_context(unsigned id,
|
||||
void *virt_area,
|
||||
addr_t vmcb_phys_addr)
|
||||
:
|
||||
vmcb(*Genode::construct_at<Vmcb>(vcpu_data_ptr, id)),
|
||||
vmcb(*Genode::construct_at<Vmcb>(virt_area, id)),
|
||||
vmcb_phys_addr(vmcb_phys_addr),
|
||||
regs(1)
|
||||
{
|
||||
regs->trapno = TRAP_VMEXIT;
|
||||
|
@ -154,11 +154,6 @@ struct alignas(Genode::get_page_size()) Board::Vmcb
|
||||
sizeof(Board::Vmcb_state_save_area) -
|
||||
Board::Vmcb_control_area::total_size];
|
||||
|
||||
Genode::Vcpu_data * vcpu_data()
|
||||
{
|
||||
return reinterpret_cast<Genode::Vcpu_data *>(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* AMD Manual Vol. 2, Table B-1: VMCB Layout, Control Area
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2023 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2024 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.
|
||||
@ -103,21 +103,40 @@ static Vmid_allocator &alloc()
|
||||
|
||||
Genode::addr_t Vm_session_component::_alloc_vcpu_data(Genode::addr_t ds_addr)
|
||||
{
|
||||
void * vcpu_data_ptr = cma()
|
||||
.alloc_aligned(sizeof(Board::Vcpu_data), 12)
|
||||
.convert<void *>(
|
||||
[&](void *ptr) { return ptr; },
|
||||
[&](Range_allocator::Alloc_error) -> void * {
|
||||
/* XXX handle individual error conditions */
|
||||
error("failed to allocate kernel object");
|
||||
throw Insufficient_ram_quota();
|
||||
}
|
||||
);
|
||||
/*
|
||||
* XXX these allocations currently leak memory on VM Session
|
||||
* destruction. This cannot be easily fixed because the
|
||||
* Core Mem Allocator does not implement free().
|
||||
*
|
||||
* Normally we would use constrained_md_ram_alloc to make the allocation,
|
||||
* but to get the physical address of the pages in virt_area, we need
|
||||
* to use the Core Mem Allocator.
|
||||
*/
|
||||
|
||||
Genode::Vcpu_data* vcpu_data = (Genode::Vcpu_data *) vcpu_data_ptr;
|
||||
vcpu_data->vcpu_state = (Genode::Vcpu_state *) ds_addr;
|
||||
vcpu_data->vmcb_phys_addr = (addr_t)cma().phys_addr(vcpu_data->vmcb);
|
||||
return (Genode::addr_t) vcpu_data_ptr;
|
||||
Vcpu_data * vcpu_data = (Vcpu_data *) cma()
|
||||
.try_alloc(sizeof(Board::Vcpu_data))
|
||||
.convert<void *>(
|
||||
[&](void *ptr) { return ptr; },
|
||||
[&](Range_allocator::Alloc_error) -> void * {
|
||||
/* XXX handle individual error conditions */
|
||||
error("failed to allocate kernel object");
|
||||
throw Insufficient_ram_quota();
|
||||
});
|
||||
|
||||
vcpu_data->virt_area = cma()
|
||||
.alloc_aligned(Vcpu_data::size(), 12)
|
||||
.convert<void *>(
|
||||
[&](void *ptr) { return ptr; },
|
||||
[&](Range_allocator::Alloc_error) -> void * {
|
||||
/* XXX handle individual error conditions */
|
||||
error("failed to allocate kernel object");
|
||||
throw Insufficient_ram_quota();
|
||||
});
|
||||
|
||||
vcpu_data->vcpu_state = (Vcpu_state *) ds_addr;
|
||||
vcpu_data->phys_addr = (addr_t)cma().phys_addr(vcpu_data->virt_area);
|
||||
|
||||
return (Genode::addr_t) vcpu_data;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user