vm_session: adjustments to work with seoul vmm
for foc, nova, sel4 Issue #3111
This commit is contained in:
parent
8950de5a89
commit
cc64c43758
|
@ -1 +1 @@
|
||||||
1367e8214fa7c02682a97bbb3b375b0d792f4fed
|
9db0c4985349d47251e91e4e61145526668278fc
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
LICENSE := GPLv2
|
LICENSE := GPLv2
|
||||||
VERSION := git
|
VERSION := git
|
||||||
DOWNLOADS := foc.git
|
DOWNLOADS := foc.git
|
||||||
URL(foc) := https://github.com/cproc/foc.git
|
URL(foc) := https://github.com/alex-ab/foc.git
|
||||||
REV(foc) := b74e427801f045578c401a140a8e66404bb3ff19
|
REV(foc) := a8411389dffc3c55dc5809d2e849b3afac94ee5d
|
||||||
DIR(foc) := src/kernel/foc
|
DIR(foc) := src/kernel/foc
|
||||||
|
|
|
@ -63,11 +63,8 @@ class Genode::Vm_session_component
|
||||||
|
|
||||||
Rpc_entrypoint &_ep;
|
Rpc_entrypoint &_ep;
|
||||||
Con_ram_allocator _constrained_md_ram_alloc;
|
Con_ram_allocator _constrained_md_ram_alloc;
|
||||||
Sliced_heap _sliced_heap;
|
Sliced_heap _heap;
|
||||||
Slab _slab { max(sizeof(Vcpu), sizeof(Rm_region)),
|
Avl_region _map { &_heap };
|
||||||
4096 - Sliced_heap::meta_data_size(),
|
|
||||||
nullptr, &_sliced_heap };
|
|
||||||
Avl_region _map { &_slab };
|
|
||||||
List<Vcpu> _vcpus { };
|
List<Vcpu> _vcpus { };
|
||||||
Cap_mapping _task_vcpu { true };
|
Cap_mapping _task_vcpu { true };
|
||||||
unsigned _id_alloc { 0 };
|
unsigned _id_alloc { 0 };
|
||||||
|
|
|
@ -40,7 +40,7 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ep,
|
||||||
Cap_quota_guard(resources.cap_quota),
|
Cap_quota_guard(resources.cap_quota),
|
||||||
_ep(ep),
|
_ep(ep),
|
||||||
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
||||||
_sliced_heap(_constrained_md_ram_alloc, local_rm)
|
_heap(_constrained_md_ram_alloc, local_rm)
|
||||||
{
|
{
|
||||||
_cap_quota_guard().withdraw(Cap_quota{1});
|
_cap_quota_guard().withdraw(Cap_quota{1});
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ Vm_session_component::~Vm_session_component()
|
||||||
{
|
{
|
||||||
for (;Vcpu * vcpu = _vcpus.first();) {
|
for (;Vcpu * vcpu = _vcpus.first();) {
|
||||||
_vcpus.remove(vcpu);
|
_vcpus.remove(vcpu);
|
||||||
destroy(_slab, vcpu);
|
destroy(_heap, vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detach all regions */
|
/* detach all regions */
|
||||||
|
@ -118,7 +118,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||||
/* allocate vCPU object */
|
/* allocate vCPU object */
|
||||||
Vcpu * vcpu = nullptr;
|
Vcpu * vcpu = nullptr;
|
||||||
try {
|
try {
|
||||||
vcpu = new (_slab) Vcpu(_constrained_md_ram_alloc,
|
vcpu = new (_heap) Vcpu(_constrained_md_ram_alloc,
|
||||||
_cap_quota_guard(),
|
_cap_quota_guard(),
|
||||||
Vcpu_id {_id_alloc});
|
Vcpu_id {_id_alloc});
|
||||||
|
|
||||||
|
@ -134,12 +134,12 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||||
});
|
});
|
||||||
} catch (int) {
|
} catch (int) {
|
||||||
if (vcpu)
|
if (vcpu)
|
||||||
destroy(_slab, vcpu);
|
destroy(_heap, vcpu);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if (vcpu)
|
if (vcpu)
|
||||||
destroy(_slab, vcpu);
|
destroy(_heap, vcpu);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ static uint32_t svm_features()
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool svm_np() { return svm_features() & (1U << 0); }
|
static bool svm_np() { return svm_features() & (1U << 0); }
|
||||||
static bool svm_instr_decode_support() { return svm_features() & (1U << 7); }
|
|
||||||
|
|
||||||
struct Vcpu;
|
struct Vcpu;
|
||||||
|
|
||||||
|
@ -137,6 +136,7 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
INTR_INFO = 0x4016,
|
INTR_INFO = 0x4016,
|
||||||
INTR_ERROR = 0x4018,
|
INTR_ERROR = 0x4018,
|
||||||
|
ENTRY_INST_LEN = 0x401a,
|
||||||
|
|
||||||
IDT_INFO = 0x4408,
|
IDT_INFO = 0x4408,
|
||||||
IDT_ERROR = 0x440a,
|
IDT_ERROR = 0x440a,
|
||||||
|
@ -154,39 +154,44 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
enum Vmcb
|
enum Vmcb
|
||||||
{
|
{
|
||||||
CTRL0_INTR = 1u << 0,
|
CTRL0_VINTR = 1u << 4,
|
||||||
CTRL0_NMI = 1u << 1,
|
|
||||||
CTRL0_INIT = 1u << 3,
|
|
||||||
CTRL0_INVD = 1u << 22,
|
|
||||||
CTRL0_HLT = 1u << 24,
|
|
||||||
CTRL0_IO = 1u << 27,
|
CTRL0_IO = 1u << 27,
|
||||||
CTRL0_MSR = 1u << 28,
|
CTRL0_MSR = 1u << 28,
|
||||||
CTRL0_SHUTDOWN = 1u << 31,
|
|
||||||
|
|
||||||
AMD_EXIT_INVALID = 0xfd
|
AMD_SVM_ENABLE = 1 << 12,
|
||||||
|
|
||||||
|
AMD_EXIT_INVALID = 0xfd,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CR0_PE = 0, /* 1U << 0 - not needed in case of UG */
|
CR0_PE = 0, /* 1U << 0 - not needed in case of UG */
|
||||||
CR0_CP = 1U << 1,
|
CR0_CP = 1U << 1,
|
||||||
|
CR0_TS = 1u << 3,
|
||||||
CR0_NE = 1U << 5,
|
CR0_NE = 1U << 5,
|
||||||
CR0_NM = 1U << 29,
|
CR0_NM = 1U << 29,
|
||||||
CR0_CD = 1U << 30,
|
CR0_CD = 1U << 30,
|
||||||
CR0_PG = 0 /* 1U << 31 - not needed in case of UG */
|
CR0_PG = 0 /* 1U << 31 - not needed in case of UG */
|
||||||
};
|
};
|
||||||
|
|
||||||
addr_t const vmcb_ctrl0 = CTRL0_INTR | CTRL0_NMI | CTRL0_INIT |
|
addr_t const _cr0_mask { CR0_CP | CR0_NM | CR0_NE | CR0_CD };
|
||||||
CTRL0_INVD | CTRL0_HLT | CTRL0_IO |
|
addr_t const vmcb_ctrl0 { CTRL0_IO | CTRL0_MSR };
|
||||||
CTRL0_MSR | CTRL0_SHUTDOWN;
|
addr_t const vmcb_ctrl1 { 0 };
|
||||||
|
|
||||||
|
addr_t vmcb_cr0_shadow { 0 };
|
||||||
|
addr_t vmcb_cr4_shadow { 0 };
|
||||||
|
addr_t const vmcb_cr0_mask { _cr0_mask | CR0_TS };
|
||||||
|
addr_t const vmcb_cr0_set { 0 };
|
||||||
|
addr_t const vmcb_cr4_mask { 0 };
|
||||||
|
addr_t const vmcb_cr4_set { 0 };
|
||||||
|
|
||||||
enum { EXIT_ON_HLT = 1U << 7 };
|
enum { EXIT_ON_HLT = 1U << 7 };
|
||||||
addr_t const _vmcs_ctrl0 = EXIT_ON_HLT;
|
addr_t const _vmcs_ctrl0 { EXIT_ON_HLT };
|
||||||
|
|
||||||
addr_t const vmcs_cr0_mask = CR0_PE | CR0_CP | CR0_NM | CR0_NE | CR0_CD | CR0_PG;
|
addr_t const vmcs_cr0_mask { _cr0_mask | CR0_PE | CR0_PG };
|
||||||
addr_t const vmcs_cr0_set = 0;
|
addr_t const vmcs_cr0_set { 0 };
|
||||||
|
|
||||||
addr_t const vmcs_cr4_mask = CR4_VMX;
|
addr_t const vmcs_cr4_mask { CR4_VMX };
|
||||||
addr_t const vmcs_cr4_set = CR4_VMX;
|
addr_t const vmcs_cr4_set { CR4_VMX };
|
||||||
|
|
||||||
Signal_context_capability _signal;
|
Signal_context_capability _signal;
|
||||||
Semaphore _wake_up { 0 };
|
Semaphore _wake_up { 0 };
|
||||||
|
@ -211,7 +216,7 @@ struct Vcpu : Genode::Thread
|
||||||
PAUSE = 1,
|
PAUSE = 1,
|
||||||
RUN = 2,
|
RUN = 2,
|
||||||
TERMINATE = 3,
|
TERMINATE = 3,
|
||||||
} _remote { PAUSE };
|
} _remote { NONE };
|
||||||
Lock _remote_lock { Lock::UNLOCKED };
|
Lock _remote_lock { Lock::UNLOCKED };
|
||||||
|
|
||||||
void entry() override
|
void entry() override
|
||||||
|
@ -265,7 +270,6 @@ struct Vcpu : Genode::Thread
|
||||||
* Fiasoc.OC peculiarities
|
* Fiasoc.OC peculiarities
|
||||||
*/
|
*/
|
||||||
if (_vm_type == Virt::SVM) {
|
if (_vm_type == Virt::SVM) {
|
||||||
enum { AMD_SVM_ENABLE = 1 << 12 };
|
|
||||||
state.efer.value(state.efer.value() | AMD_SVM_ENABLE);
|
state.efer.value(state.efer.value() | AMD_SVM_ENABLE);
|
||||||
}
|
}
|
||||||
if (_vm_type == Virt::SVM) {
|
if (_vm_type == Virt::SVM) {
|
||||||
|
@ -274,12 +278,9 @@ struct Vcpu : Genode::Thread
|
||||||
if (!vmcb->control_area.np_enable)
|
if (!vmcb->control_area.np_enable)
|
||||||
vmcb->control_area.intercept_exceptions |= 1 << 14;
|
vmcb->control_area.intercept_exceptions |= 1 << 14;
|
||||||
|
|
||||||
/* XXX - further stuff needed .. */
|
vmcb->control_area.intercept_instruction0 = vmcb_ctrl0;
|
||||||
if (!svm_instr_decode_support()) {
|
vmcb->control_area.intercept_rd_crX = 0x0001; /* cr0 */
|
||||||
vmcb->control_area.intercept_instruction0 = vmcb_ctrl0;
|
vmcb->control_area.intercept_wr_crX = 0x0001; /* cr0 */
|
||||||
vmcb->control_area.intercept_rd_crX = 0x0001; /* cr0 */
|
|
||||||
vmcb->control_area.intercept_wr_crX = 0x0001; /* cr0 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_vm_type == Virt::VMX) {
|
if (_vm_type == Virt::VMX) {
|
||||||
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR0_MASK, vmcs_cr0_mask);
|
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR0_MASK, vmcs_cr0_mask);
|
||||||
|
@ -295,6 +296,13 @@ struct Vcpu : Genode::Thread
|
||||||
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::ENTRY_CTRL, ENTRY_LOAD_EFER);
|
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::ENTRY_CTRL, ENTRY_LOAD_EFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_vm_type == Virt::SVM)
|
||||||
|
_write_amd_state(state, vmcb, vcpu);
|
||||||
|
if (_vm_type == Virt::VMX)
|
||||||
|
_write_intel_state(state, vmcs, vcpu);
|
||||||
|
|
||||||
|
vcpu->saved_state = L4_VCPU_F_USER_MODE | L4_VCPU_F_FPU_ENABLED;
|
||||||
|
|
||||||
State local_state { NONE };
|
State local_state { NONE };
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -303,6 +311,15 @@ struct Vcpu : Genode::Thread
|
||||||
Lock::Guard guard(_remote_lock);
|
Lock::Guard guard(_remote_lock);
|
||||||
local_state = _remote;
|
local_state = _remote;
|
||||||
_remote = NONE;
|
_remote = NONE;
|
||||||
|
|
||||||
|
if (local_state == PAUSE) {
|
||||||
|
while (vcpu->sticky_flags) {
|
||||||
|
/* consume spurious notifications */
|
||||||
|
Fiasco::l4_cap_idx_t tid = native_thread().kcap;
|
||||||
|
Fiasco::l4_cap_idx_t irq = tid + Fiasco::TASK_VCPU_IRQ_CAP;
|
||||||
|
l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_state == NONE) {
|
if (local_state == NONE) {
|
||||||
|
@ -316,11 +333,6 @@ struct Vcpu : Genode::Thread
|
||||||
if (_vm_type == Virt::VMX)
|
if (_vm_type == Virt::VMX)
|
||||||
_write_intel_state(state, vmcs, vcpu);
|
_write_intel_state(state, vmcs, vcpu);
|
||||||
|
|
||||||
/* consume spurious notifications */
|
|
||||||
Fiasco::l4_cap_idx_t tid = native_thread().kcap;
|
|
||||||
Fiasco::l4_cap_idx_t irq = tid + Fiasco::TASK_VCPU_IRQ_CAP;
|
|
||||||
l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
|
|
||||||
|
|
||||||
state.exit_reason = VMEXIT_PAUSED;
|
state.exit_reason = VMEXIT_PAUSED;
|
||||||
|
|
||||||
if (_vm_type == Virt::SVM)
|
if (_vm_type == Virt::SVM)
|
||||||
|
@ -350,8 +362,6 @@ struct Vcpu : Genode::Thread
|
||||||
if (_vm_type == Virt::VMX)
|
if (_vm_type == Virt::VMX)
|
||||||
_write_intel_state(state, vmcs, vcpu);
|
_write_intel_state(state, vmcs, vcpu);
|
||||||
|
|
||||||
vcpu->saved_state = L4_VCPU_F_USER_MODE | L4_VCPU_F_FPU_ENABLED;
|
|
||||||
|
|
||||||
/* tell Fiasco.OC to run the vCPU */
|
/* tell Fiasco.OC to run the vCPU */
|
||||||
l4_msgtag_t tag = l4_thread_vcpu_resume_start();
|
l4_msgtag_t tag = l4_thread_vcpu_resume_start();
|
||||||
tag = l4_thread_vcpu_resume_commit(L4_INVALID_CAP, tag);
|
tag = l4_thread_vcpu_resume_commit(L4_INVALID_CAP, tag);
|
||||||
|
@ -377,9 +387,11 @@ struct Vcpu : Genode::Thread
|
||||||
}
|
}
|
||||||
|
|
||||||
/* consume notification */
|
/* consume notification */
|
||||||
Fiasco::l4_cap_idx_t tid = native_thread().kcap;
|
while (vcpu->sticky_flags) {
|
||||||
Fiasco::l4_cap_idx_t irq = tid + Fiasco::TASK_VCPU_IRQ_CAP;
|
Fiasco::l4_cap_idx_t tid = native_thread().kcap;
|
||||||
l4_irq_receive(irq, L4_IPC_NEVER);
|
Fiasco::l4_cap_idx_t irq = tid + Fiasco::TASK_VCPU_IRQ_CAP;
|
||||||
|
l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.exit_reason = reason & 0xff;
|
state.exit_reason = reason & 0xff;
|
||||||
|
@ -400,9 +412,11 @@ struct Vcpu : Genode::Thread
|
||||||
}
|
}
|
||||||
|
|
||||||
/* consume notification */
|
/* consume notification */
|
||||||
Fiasco::l4_cap_idx_t tid = native_thread().kcap;
|
while (vcpu->sticky_flags) {
|
||||||
Fiasco::l4_cap_idx_t irq = tid + Fiasco::TASK_VCPU_IRQ_CAP;
|
Fiasco::l4_cap_idx_t tid = native_thread().kcap;
|
||||||
l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
|
Fiasco::l4_cap_idx_t irq = tid + Fiasco::TASK_VCPU_IRQ_CAP;
|
||||||
|
l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.exit_reason = reason & 0xff;
|
state.exit_reason = reason & 0xff;
|
||||||
|
@ -468,12 +482,8 @@ struct Vcpu : Genode::Thread
|
||||||
addr_t const cr0 = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR0);
|
addr_t const cr0 = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR0);
|
||||||
addr_t const cr0_shadow = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR0_SHADOW);
|
addr_t const cr0_shadow = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR0_SHADOW);
|
||||||
state.cr0.value((cr0 & ~vmcs_cr0_mask) | (cr0_shadow & vmcs_cr0_mask));
|
state.cr0.value((cr0 & ~vmcs_cr0_mask) | (cr0_shadow & vmcs_cr0_mask));
|
||||||
if (state.cr0.value() != cr0_shadow) {
|
if (state.cr0.value() != cr0_shadow)
|
||||||
Genode::error("reset cr0_shadow to cr0 ", Genode::Hex(cr0),
|
|
||||||
" ", Genode::Hex(cr0_shadow), "->",
|
|
||||||
Genode::Hex(state.cr0.value()));
|
|
||||||
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR0_SHADOW, state.cr0.value());
|
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR0_SHADOW, state.cr0.value());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned const cr2 = Fiasco::l4_vm_vmx_get_cr2_index(vmcs);
|
unsigned const cr2 = Fiasco::l4_vm_vmx_get_cr2_index(vmcs);
|
||||||
|
@ -484,19 +494,11 @@ struct Vcpu : Genode::Thread
|
||||||
addr_t const cr4 = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR4);
|
addr_t const cr4 = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR4);
|
||||||
addr_t const cr4_shadow = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR4_SHADOW);
|
addr_t const cr4_shadow = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR4_SHADOW);
|
||||||
state.cr4.value((cr4 & ~vmcs_cr4_mask) | (cr4_shadow & vmcs_cr4_mask));
|
state.cr4.value((cr4 & ~vmcs_cr4_mask) | (cr4_shadow & vmcs_cr4_mask));
|
||||||
if (state.cr4.value() != cr4_shadow) {
|
if (state.cr4.value() != cr4_shadow)
|
||||||
Genode::error("reset cr0_shadow to cr4 ", Genode::Hex(cr4),
|
|
||||||
" ", Genode::Hex(cr4_shadow), "->",
|
|
||||||
Genode::Hex(state.cr4.value()));
|
|
||||||
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR4_SHADOW,
|
Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR4_SHADOW,
|
||||||
state.cr4.value());
|
state.cr4.value());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
state.cs.value(Segment{utcb.cs.sel, utcb.cs.ar, utcb.cs.limit,
|
|
||||||
utcb.cs.base});
|
|
||||||
*/
|
|
||||||
using Fiasco::l4_vm_vmx_read;
|
using Fiasco::l4_vm_vmx_read;
|
||||||
using Fiasco::l4_vm_vmx_read_16;
|
using Fiasco::l4_vm_vmx_read_16;
|
||||||
using Fiasco::l4_vm_vmx_read_32;
|
using Fiasco::l4_vm_vmx_read_32;
|
||||||
|
@ -636,7 +638,7 @@ struct Vcpu : Genode::Thread
|
||||||
state.sp.value(vmcb->state_save_area.rsp);
|
state.sp.value(vmcb->state_save_area.rsp);
|
||||||
|
|
||||||
state.ip.value(vmcb->state_save_area.rip);
|
state.ip.value(vmcb->state_save_area.rip);
|
||||||
state.ip_len.value(state.ip_len.value()); /* unsupported on AMD */
|
state.ip_len.value(0); /* unsupported on AMD */
|
||||||
|
|
||||||
state.dr7.value(vmcb->state_save_area.dr7);
|
state.dr7.value(vmcb->state_save_area.dr7);
|
||||||
|
|
||||||
|
@ -651,10 +653,20 @@ struct Vcpu : Genode::Thread
|
||||||
state.r15.value(vcpu->r.r15);
|
state.r15.value(vcpu->r.r15);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
state.cr0.value(vmcb->state_save_area.cr0);
|
{
|
||||||
|
addr_t const cr0 = vmcb->state_save_area.cr0;
|
||||||
|
state.cr0.value((cr0 & ~vmcb_cr0_mask) | (vmcb_cr0_shadow & vmcb_cr0_mask));
|
||||||
|
if (state.cr0.value() != vmcb_cr0_shadow)
|
||||||
|
vmcb_cr0_shadow = state.cr0.value();
|
||||||
|
}
|
||||||
state.cr2.value(vmcb->state_save_area.cr2);
|
state.cr2.value(vmcb->state_save_area.cr2);
|
||||||
state.cr3.value(vmcb->state_save_area.cr3);
|
state.cr3.value(vmcb->state_save_area.cr3);
|
||||||
state.cr4.value(vmcb->state_save_area.cr4);
|
{
|
||||||
|
addr_t const cr4 = vmcb->state_save_area.cr4;
|
||||||
|
state.cr4.value((cr4 & ~vmcb_cr4_mask) | (vmcb_cr4_shadow & vmcb_cr4_mask));
|
||||||
|
if (state.cr4.value() != vmcb_cr4_shadow)
|
||||||
|
vmcb_cr4_shadow = state.cr4.value();
|
||||||
|
}
|
||||||
|
|
||||||
typedef Genode::Vm_state::Segment Segment;
|
typedef Genode::Vm_state::Segment Segment;
|
||||||
|
|
||||||
|
@ -733,9 +745,7 @@ struct Vcpu : Genode::Thread
|
||||||
state.tsc.value(Trace::timestamp());
|
state.tsc.value(Trace::timestamp());
|
||||||
state.tsc_offset.value(_tsc_offset);
|
state.tsc_offset.value(_tsc_offset);
|
||||||
|
|
||||||
if (state.efer.valid()) {
|
state.efer.value(vmcb->state_save_area.efer);
|
||||||
Genode::error("efer not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.pdpte_0.valid() || state.pdpte_1.valid() ||
|
if (state.pdpte_0.valid() || state.pdpte_1.valid() ||
|
||||||
state.pdpte_2.valid() || state.pdpte_3.valid()) {
|
state.pdpte_2.valid() || state.pdpte_3.valid()) {
|
||||||
|
@ -760,12 +770,14 @@ struct Vcpu : Genode::Thread
|
||||||
using Fiasco::l4_vm_vmx_write;
|
using Fiasco::l4_vm_vmx_write;
|
||||||
|
|
||||||
if (state.ax.valid() || state.cx.valid() || state.dx.valid() ||
|
if (state.ax.valid() || state.cx.valid() || state.dx.valid() ||
|
||||||
state.bx.valid() || state.bp.valid() || state.di.valid() ||
|
state.bx.valid()) {
|
||||||
state.si.valid()) {
|
|
||||||
vcpu->r.ax = state.ax.value();
|
vcpu->r.ax = state.ax.value();
|
||||||
vcpu->r.cx = state.cx.value();
|
vcpu->r.cx = state.cx.value();
|
||||||
vcpu->r.dx = state.dx.value();
|
vcpu->r.dx = state.dx.value();
|
||||||
vcpu->r.bx = state.bx.value();
|
vcpu->r.bx = state.bx.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.bp.valid() || state.di.valid() || state.si.valid()) {
|
||||||
vcpu->r.bp = state.bp.value();
|
vcpu->r.bp = state.bp.value();
|
||||||
vcpu->r.di = state.di.value();
|
vcpu->r.di = state.di.value();
|
||||||
vcpu->r.si = state.si.value();
|
vcpu->r.si = state.si.value();
|
||||||
|
@ -825,9 +837,10 @@ struct Vcpu : Genode::Thread
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::CR4_SHADOW, state.cr4.value());
|
l4_vm_vmx_write(vmcs, Vmcs::CR4_SHADOW, state.cr4.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (state.inj_info.valid() || state.inj_error.valid()) {
|
if (state.inj_info.valid() || state.inj_error.valid()) {
|
||||||
addr_t ctrl_0 = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CTRL_0);
|
addr_t ctrl_0 = state.ctrl_primary.valid() ?
|
||||||
|
state.ctrl_primary.value() :
|
||||||
|
Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CTRL_0);
|
||||||
|
|
||||||
if (state.inj_info.value() & 0x2000)
|
if (state.inj_info.value() & 0x2000)
|
||||||
Genode::warning("unimplemented ", state.inj_info.value() & 0x1000, " ", state.inj_info.value() & 0x2000, " ", Genode::Hex(ctrl_0), " ", Genode::Hex(state.ctrl_secondary.value()));
|
Genode::warning("unimplemented ", state.inj_info.value() & 0x1000, " ", state.inj_info.value() & 0x2000, " ", Genode::Hex(ctrl_0), " ", Genode::Hex(state.ctrl_secondary.value()));
|
||||||
|
@ -844,7 +857,6 @@ struct Vcpu : Genode::Thread
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::INTR_ERROR,
|
l4_vm_vmx_write(vmcs, Vmcs::INTR_ERROR,
|
||||||
state.inj_error.value());
|
state.inj_error.value());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (state.flags.valid())
|
if (state.flags.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::FLAGS, state.flags.value());
|
l4_vm_vmx_write(vmcs, Vmcs::FLAGS, state.flags.value());
|
||||||
|
@ -855,24 +867,27 @@ struct Vcpu : Genode::Thread
|
||||||
if (state.ip.valid())
|
if (state.ip.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::IP, state.ip.value());
|
l4_vm_vmx_write(vmcs, Vmcs::IP, state.ip.value());
|
||||||
|
|
||||||
|
if (state.ip_len.valid())
|
||||||
|
l4_vm_vmx_write(vmcs, Vmcs::ENTRY_INST_LEN, state.ip_len.value());
|
||||||
|
|
||||||
if (state.efer.valid())
|
if (state.efer.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::EFER, state.efer.value());
|
l4_vm_vmx_write(vmcs, Vmcs::EFER, state.efer.value());
|
||||||
|
|
||||||
if (state.ctrl_primary.valid())
|
if (state.ctrl_primary.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::CTRL_0,
|
l4_vm_vmx_write(vmcs, Vmcs::CTRL_0,
|
||||||
_vmcs_ctrl0 | state.ctrl_primary.value());
|
_vmcs_ctrl0 | state.ctrl_primary.value());
|
||||||
|
|
||||||
if (state.ctrl_secondary.valid())
|
if (state.ctrl_secondary.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::CTRL_1,
|
l4_vm_vmx_write(vmcs, Vmcs::CTRL_1,
|
||||||
state.ctrl_secondary.value());
|
state.ctrl_secondary.value());
|
||||||
|
|
||||||
if (state.intr_state.valid())
|
if (state.intr_state.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::STATE_INTR,
|
l4_vm_vmx_write(vmcs, Vmcs::STATE_INTR,
|
||||||
state.intr_state.value());
|
state.intr_state.value());
|
||||||
|
|
||||||
if (state.actv_state.valid())
|
if (state.actv_state.valid())
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::STATE_ACTV,
|
l4_vm_vmx_write(vmcs, Vmcs::STATE_ACTV,
|
||||||
state.actv_state.valid());
|
state.actv_state.value());
|
||||||
|
|
||||||
if (state.cs.valid()) {
|
if (state.cs.valid()) {
|
||||||
l4_vm_vmx_write(vmcs, Vmcs::CS_SEL, state.cs.value().sel);
|
l4_vm_vmx_write(vmcs, Vmcs::CS_SEL, state.cs.value().sel);
|
||||||
|
@ -964,13 +979,16 @@ struct Vcpu : Genode::Thread
|
||||||
Fiasco::l4_vcpu_state_t *vcpu)
|
Fiasco::l4_vcpu_state_t *vcpu)
|
||||||
{
|
{
|
||||||
if (state.ax.valid() || state.cx.valid() || state.dx.valid() ||
|
if (state.ax.valid() || state.cx.valid() || state.dx.valid() ||
|
||||||
state.bx.valid() || state.bp.valid() || state.di.valid() ||
|
state.bx.valid()) {
|
||||||
state.si.valid()) {
|
|
||||||
vmcb->state_save_area.rax = state.ax.value();
|
vmcb->state_save_area.rax = state.ax.value();
|
||||||
vcpu->r.ax = state.ax.value();
|
vcpu->r.ax = state.ax.value();
|
||||||
vcpu->r.cx = state.cx.value();
|
vcpu->r.cx = state.cx.value();
|
||||||
vcpu->r.dx = state.dx.value();
|
vcpu->r.dx = state.dx.value();
|
||||||
vcpu->r.bx = state.bx.value();
|
vcpu->r.bx = state.bx.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.bp.valid() || state.di.valid() || state.si.valid()) {
|
||||||
vcpu->r.bp = state.bp.value();
|
vcpu->r.bp = state.bp.value();
|
||||||
vcpu->r.di = state.di.value();
|
vcpu->r.di = state.di.value();
|
||||||
vcpu->r.si = state.si.value();
|
vcpu->r.si = state.si.value();
|
||||||
|
@ -1007,7 +1025,8 @@ struct Vcpu : Genode::Thread
|
||||||
vmcb->state_save_area.dr7 = state.dr7.value();
|
vmcb->state_save_area.dr7 = state.dr7.value();
|
||||||
|
|
||||||
if (state.cr0.valid()) {
|
if (state.cr0.valid()) {
|
||||||
vmcb->state_save_area.cr0 = state.cr0.value();
|
vmcb->state_save_area.cr0 = vmcb_cr0_set | (~vmcb_cr0_mask & state.cr0.value());
|
||||||
|
vmcb_cr0_shadow = state.cr0.value();
|
||||||
#if 0
|
#if 0
|
||||||
vmcb->state_save_area.xcr0 = state.cr0();
|
vmcb->state_save_area.xcr0 = state.cr0();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1019,13 +1038,36 @@ struct Vcpu : Genode::Thread
|
||||||
if (state.cr3.valid())
|
if (state.cr3.valid())
|
||||||
vmcb->state_save_area.cr3 = state.cr3.value();
|
vmcb->state_save_area.cr3 = state.cr3.value();
|
||||||
|
|
||||||
if (state.cr4.valid())
|
if (state.cr4.valid()) {
|
||||||
vmcb->state_save_area.cr4 = state.cr4.value();
|
vmcb->state_save_area.cr4 = vmcb_cr4_set | (~vmcb_cr4_mask & state.cr4.value());
|
||||||
|
vmcb_cr4_shadow = state.cr4.value();
|
||||||
|
}
|
||||||
|
|
||||||
if (state.inj_info.valid())
|
if (state.ctrl_primary.valid())
|
||||||
Genode::error(__LINE__, " not implemented ");
|
vmcb->control_area.intercept_instruction0 = vmcb_ctrl0 |
|
||||||
if (state.inj_error.valid())
|
state.ctrl_primary.value();
|
||||||
Genode::error(__LINE__, " not implemented ");
|
|
||||||
|
if (state.ctrl_secondary.valid())
|
||||||
|
vmcb->control_area.intercept_instruction1 = vmcb_ctrl1 |
|
||||||
|
state.ctrl_secondary.value();
|
||||||
|
|
||||||
|
if (state.inj_info.valid()) {
|
||||||
|
if (state.inj_info.value() & 0x1000) {
|
||||||
|
vmcb->control_area.interrupt_ctl |= (1ul << 8 | 1ul << 20);
|
||||||
|
vmcb->control_area.intercept_instruction0 |= Vmcb::CTRL0_VINTR;
|
||||||
|
} else {
|
||||||
|
vmcb->control_area.interrupt_ctl &= ~(1ul << 8 | 1ul << 20);
|
||||||
|
vmcb->control_area.intercept_instruction0 &= ~Vmcb::CTRL0_VINTR;
|
||||||
|
}
|
||||||
|
vmcb->control_area.eventinj = 0;
|
||||||
|
vmcb->control_area.eventinj |= ~0x3000U & state.inj_info.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.inj_error.valid()) {
|
||||||
|
vmcb->control_area.eventinj &= ((1ULL << 32) - 1);
|
||||||
|
uint64_t value = (0ULL + state.inj_error.value()) << 32;
|
||||||
|
vmcb->control_area.eventinj |= value;
|
||||||
|
}
|
||||||
|
|
||||||
if (state.flags.valid())
|
if (state.flags.valid())
|
||||||
vmcb->state_save_area.rflags = state.flags.value();
|
vmcb->state_save_area.rflags = state.flags.value();
|
||||||
|
@ -1037,14 +1079,7 @@ struct Vcpu : Genode::Thread
|
||||||
vmcb->state_save_area.rip = state.ip.value();
|
vmcb->state_save_area.rip = state.ip.value();
|
||||||
|
|
||||||
if (state.efer.valid())
|
if (state.efer.valid())
|
||||||
vmcb->state_save_area.efer = state.efer.value();
|
vmcb->state_save_area.efer = state.efer.value() | AMD_SVM_ENABLE;
|
||||||
|
|
||||||
if (state.ctrl_primary.valid())
|
|
||||||
vmcb->control_area.intercept_instruction0 = vmcb_ctrl0 |
|
|
||||||
state.ctrl_primary.value();
|
|
||||||
|
|
||||||
if (state.ctrl_secondary.valid())
|
|
||||||
vmcb->control_area.intercept_instruction1 = state.ctrl_secondary.value();
|
|
||||||
|
|
||||||
if (state.intr_state.valid())
|
if (state.intr_state.valid())
|
||||||
vmcb->control_area.interrupt_shadow = state.intr_state.value();
|
vmcb->control_area.interrupt_shadow = state.intr_state.value();
|
||||||
|
@ -1162,7 +1197,7 @@ struct Vcpu : Genode::Thread
|
||||||
void resume() {
|
void resume() {
|
||||||
Lock::Guard guard(_remote_lock);
|
Lock::Guard guard(_remote_lock);
|
||||||
|
|
||||||
if (_remote == RUN)
|
if (_remote == RUN || _remote == PAUSE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_remote = RUN;
|
_remote = RUN;
|
||||||
|
|
|
@ -74,11 +74,8 @@ class Genode::Vm_session_component
|
||||||
|
|
||||||
Rpc_entrypoint &_ep;
|
Rpc_entrypoint &_ep;
|
||||||
Con_ram_allocator _constrained_md_ram_alloc;
|
Con_ram_allocator _constrained_md_ram_alloc;
|
||||||
Sliced_heap _sliced_heap;
|
Sliced_heap _heap;
|
||||||
Slab _slab { max(sizeof(Vcpu), sizeof(Rm_region)),
|
Avl_region _map { &_heap };
|
||||||
4096 - Sliced_heap::meta_data_size(),
|
|
||||||
nullptr, &_sliced_heap };
|
|
||||||
Avl_region _map { &_slab };
|
|
||||||
addr_t _pd_sel { 0 };
|
addr_t _pd_sel { 0 };
|
||||||
unsigned _id_alloc { 0 };
|
unsigned _id_alloc { 0 };
|
||||||
unsigned _priority;
|
unsigned _priority;
|
||||||
|
|
|
@ -151,7 +151,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* allocate vCPU object */
|
/* allocate vCPU object */
|
||||||
Vcpu &vcpu = *new (_slab) Vcpu(_constrained_md_ram_alloc,
|
Vcpu &vcpu = *new (_heap) Vcpu(_constrained_md_ram_alloc,
|
||||||
_cap_quota_guard(),
|
_cap_quota_guard(),
|
||||||
Vcpu_id {_id_alloc});
|
Vcpu_id {_id_alloc});
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||||
|
|
||||||
if (res != Nova::NOVA_OK) {
|
if (res != Nova::NOVA_OK) {
|
||||||
error("create_sm = ", res);
|
error("create_sm = ", res);
|
||||||
destroy(_slab, &vcpu);
|
destroy(_heap, &vcpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||||
|
|
||||||
if (res != Nova::NOVA_OK) {
|
if (res != Nova::NOVA_OK) {
|
||||||
error("create_ec = ", res);
|
error("create_ec = ", res);
|
||||||
destroy(_slab, &vcpu);
|
destroy(_heap, &vcpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||||
if (res != Nova::NOVA_OK)
|
if (res != Nova::NOVA_OK)
|
||||||
{
|
{
|
||||||
error("map sm ", res, " ", _id_alloc);
|
error("map sm ", res, " ", _id_alloc);
|
||||||
destroy(_slab, &vcpu);
|
destroy(_heap, &vcpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,8 +283,8 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ep,
|
||||||
Cap_quota_guard(resources.cap_quota),
|
Cap_quota_guard(resources.cap_quota),
|
||||||
_ep(ep),
|
_ep(ep),
|
||||||
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
||||||
_sliced_heap(_constrained_md_ram_alloc, local_rm),
|
_heap(_constrained_md_ram_alloc, local_rm),
|
||||||
_priority(scale_priority(priority, "VM sesssion"))
|
_priority(scale_priority(priority, "VM session"))
|
||||||
{
|
{
|
||||||
_cap_quota_guard().withdraw(Cap_quota{1});
|
_cap_quota_guard().withdraw(Cap_quota{1});
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ Vm_session_component::~Vm_session_component()
|
||||||
{
|
{
|
||||||
for (;Vcpu * vcpu = _vcpus.first();) {
|
for (;Vcpu * vcpu = _vcpus.first();) {
|
||||||
_vcpus.remove(vcpu);
|
_vcpus.remove(vcpu);
|
||||||
destroy(_slab, vcpu);
|
destroy(_heap, vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detach all regions */
|
/* detach all regions */
|
||||||
|
|
|
@ -227,6 +227,7 @@ struct Vcpu {
|
||||||
if (state.ip.valid()) {
|
if (state.ip.valid()) {
|
||||||
utcb.mtd |= Nova::Mtd::EIP;
|
utcb.mtd |= Nova::Mtd::EIP;
|
||||||
utcb.ip = state.ip.value();
|
utcb.ip = state.ip.value();
|
||||||
|
utcb.instr_len = state.ip_len.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.dr7.valid()) {
|
if (state.dr7.valid()) {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
--- src/kernel/sel4/src/arch/x86/object/vcpu.c
|
||||||
|
+++ src/kernel/sel4/src/arch/x86/object/vcpu.c
|
||||||
|
@@ -760,6 +774,8 @@ decodeWriteVMCS(cap_t cap, word_t length, word_t* buffer)
|
||||||
|
case VMX_GUEST_CR3:
|
||||||
|
case VMX_CONTROL_EXCEPTION_BITMAP:
|
||||||
|
case VMX_CONTROL_ENTRY_INTERRUPTION_INFO:
|
||||||
|
+ case VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE:
|
||||||
|
+ case VMX_CONTROL_ENTRY_INSTRUCTION_LENGTH:
|
||||||
|
break;
|
||||||
|
case VMX_CONTROL_PIN_EXECUTION_CONTROLS:
|
||||||
|
value = applyFixedBits(value, pin_control_high, pin_control_low);
|
||||||
|
@@ -909,6 +925,7 @@ decodeReadVMCS(cap_t cap, word_t length, word_t* buffer)
|
||||||
|
case VMX_GUEST_CR0:
|
||||||
|
case VMX_GUEST_CR3:
|
||||||
|
case VMX_GUEST_CR4:
|
||||||
|
+ case VMX_CONTROL_ENTRY_EXCEPTION_ERROR_CODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
userError("VCPU ReadVMCS: Invalid field %lx.", (long)field);
|
|
@ -1 +1 @@
|
||||||
8518d37c4b819daba60648ca23a739ccf1f55460
|
34b8f0e01692d1d2ba2f02c98bafe321fc09de22
|
||||||
|
|
|
@ -57,14 +57,13 @@ class Genode::Vm_session_component
|
||||||
|
|
||||||
Rpc_entrypoint &_ep;
|
Rpc_entrypoint &_ep;
|
||||||
Constrained_ram_allocator _constrained_md_ram_alloc;
|
Constrained_ram_allocator _constrained_md_ram_alloc;
|
||||||
Sliced_heap _sliced_heap;
|
|
||||||
Heap _heap;
|
Heap _heap;
|
||||||
Avl_region _map { &_heap };
|
Avl_region _map { &_heap };
|
||||||
List<Vcpu> _vcpus { };
|
List<Vcpu> _vcpus { };
|
||||||
unsigned _id_alloc { 0 };
|
unsigned _id_alloc { 0 };
|
||||||
unsigned _pd_id { 0 };
|
unsigned _pd_id { 0 };
|
||||||
Cap_sel _vm_page_table;
|
Cap_sel _vm_page_table;
|
||||||
Page_table_registry _page_table_registry { _sliced_heap };
|
Page_table_registry _page_table_registry { _heap };
|
||||||
Vm_space _vm_space;
|
Vm_space _vm_space;
|
||||||
struct {
|
struct {
|
||||||
addr_t _phys;
|
addr_t _phys;
|
||||||
|
|
|
@ -127,10 +127,15 @@ class Genode::Vm_space
|
||||||
|
|
||||||
Leaf_cnode _vm_cnodes[NUM_LEAF_CNODES];
|
Leaf_cnode _vm_cnodes[NUM_LEAF_CNODES];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocator for the selectors within '_vm_cnodes'
|
* Allocator for the selectors within '_vm_cnodes'
|
||||||
*/
|
*/
|
||||||
using Selector_allocator = Bit_allocator<1UL << NUM_VM_SEL_LOG2>;
|
using Selector_allocator = Bit_allocator<1UL << NUM_VM_SEL_LOG2>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
Selector_allocator _sel_alloc { };
|
Selector_allocator _sel_alloc { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,7 +193,7 @@ class Genode::Vm_space
|
||||||
* wasting of resources (idx selectors, creating kernel
|
* wasting of resources (idx selectors, creating kernel
|
||||||
* capabilities, causing kernel warning ...).
|
* capabilities, causing kernel warning ...).
|
||||||
*/
|
*/
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
/* allocate page-table-entry selector */
|
/* allocate page-table-entry selector */
|
||||||
addr_t pte_idx;
|
addr_t pte_idx;
|
||||||
|
@ -277,6 +282,15 @@ class Genode::Vm_space
|
||||||
return Cap_sel(idx);
|
return Cap_sel(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _unmap_and_free(Cap_sel const idx, addr_t const paddr)
|
||||||
|
{
|
||||||
|
_leaf_cnode(idx.value()).remove(idx);
|
||||||
|
|
||||||
|
_sel_alloc.free(idx.value());
|
||||||
|
|
||||||
|
Untyped_memory::free_page(_phys_alloc, paddr);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,12 +362,7 @@ class Genode::Vm_space
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, [&] (Cap_sel const &idx, addr_t const paddr) {
|
}, [&] (Cap_sel const &idx, addr_t const paddr) {
|
||||||
|
_unmap_and_free(idx, paddr);
|
||||||
_leaf_cnode(idx.value()).remove(idx);
|
|
||||||
|
|
||||||
_sel_alloc.free(idx.value());
|
|
||||||
|
|
||||||
Untyped_memory::free_page(_phys_alloc, paddr);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (unsigned i = 0; i < NUM_LEAF_CNODES; i++) {
|
for (unsigned i = 0; i < NUM_LEAF_CNODES; i++) {
|
||||||
|
|
|
@ -77,7 +77,12 @@ void Genode::Vm_space::unsynchronized_alloc_page_tables(addr_t const start,
|
||||||
|
|
||||||
/* 1 MB range - page table */
|
/* 1 MB range - page table */
|
||||||
Cap_sel const pt = _alloc_and_map<Page_table_kobj>(virt, map_page_table, phys);
|
Cap_sel const pt = _alloc_and_map<Page_table_kobj>(virt, map_page_table, phys);
|
||||||
_page_table_registry.insert_page_table(virt, pt, phys,
|
try {
|
||||||
PAGE_TABLE_LOG2_SIZE);
|
_page_table_registry.insert_page_table(virt, pt, phys,
|
||||||
|
PAGE_TABLE_LOG2_SIZE);
|
||||||
|
} catch (...) {
|
||||||
|
_unmap_and_free(pt, phys);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,6 @@ try
|
||||||
Cap_quota_guard(resources.cap_quota),
|
Cap_quota_guard(resources.cap_quota),
|
||||||
_ep(ep),
|
_ep(ep),
|
||||||
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
||||||
_sliced_heap(_constrained_md_ram_alloc, local_rm),
|
|
||||||
_heap(_constrained_md_ram_alloc, local_rm),
|
_heap(_constrained_md_ram_alloc, local_rm),
|
||||||
_pd_id(Platform_pd::pd_id_alloc().alloc()),
|
_pd_id(Platform_pd::pd_id_alloc().alloc()),
|
||||||
_vm_page_table(platform_specific().core_sel_alloc().alloc()),
|
_vm_page_table(platform_specific().core_sel_alloc().alloc()),
|
||||||
|
@ -249,34 +248,53 @@ void Vm_session_component::_attach_vm_memory(Dataspace_component &dsc,
|
||||||
|
|
||||||
Flexpage page = flex.page();
|
Flexpage page = flex.page();
|
||||||
while (page.valid()) {
|
while (page.valid()) {
|
||||||
try {
|
|
||||||
_vm_space.alloc_guest_page_tables(page.hotspot, 1 << page.log2_order);
|
|
||||||
} catch (...) {
|
|
||||||
// Alloc_page_table_failed
|
|
||||||
Genode::error("alloc_guest_page_table exception");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum { NO_FLUSH = false, FLUSH = true };
|
enum { NO_FLUSH = false, FLUSH = true };
|
||||||
try {
|
try {
|
||||||
|
_vm_space.alloc_guest_page_tables(page.hotspot, 1 << page.log2_order);
|
||||||
_vm_space.map_guest(page.addr, page.hotspot,
|
_vm_space.map_guest(page.addr, page.hotspot,
|
||||||
(1 << page.log2_order) / 4096,
|
(1 << page.log2_order) / 4096,
|
||||||
dsc.cacheability(),
|
dsc.cacheability(),
|
||||||
dsc.writable() && attribute.writeable,
|
dsc.writable() && attribute.writeable,
|
||||||
attribute.executable, NO_FLUSH);
|
attribute.executable, NO_FLUSH);
|
||||||
} catch (Page_table_registry::Mapping_cache_full full) {
|
} catch (Page_table_registry::Mapping_cache_full full) {
|
||||||
if (full.reason == Page_table_registry::Mapping_cache_full::MEMORY)
|
if (full.reason == Page_table_registry::Mapping_cache_full::MEMORY) {
|
||||||
|
if (_ram_quota_guard().limit().value > 4 * 1024 * 1024)
|
||||||
|
/* we get in trouble in core if we use too much memory */
|
||||||
|
throw Vm_space::Selector_allocator::Out_of_indices();
|
||||||
throw Out_of_ram();
|
throw Out_of_ram();
|
||||||
|
}
|
||||||
if (full.reason == Page_table_registry::Mapping_cache_full::CAPS)
|
if (full.reason == Page_table_registry::Mapping_cache_full::CAPS)
|
||||||
throw Out_of_caps();
|
throw Out_of_caps();
|
||||||
return;
|
return;
|
||||||
} catch (Genode::Bit_allocator<4096u>::Out_of_indices) {
|
} catch (Vm_space::Selector_allocator::Out_of_indices) {
|
||||||
Genode::warning("run out of indices - flush all");
|
Genode::warning("run out of indices - flush all - cap=",
|
||||||
|
_cap_quota_guard().used(), "/",
|
||||||
|
_cap_quota_guard().avail(), "/",
|
||||||
|
_cap_quota_guard().limit(), " ram=",
|
||||||
|
_ram_quota_guard().used(), "/",
|
||||||
|
_ram_quota_guard().avail(), "/",
|
||||||
|
_ram_quota_guard().limit(), " guest=",
|
||||||
|
Genode::Hex(0UL - _map.avail()));
|
||||||
|
|
||||||
_vm_space.map_guest(page.addr, page.hotspot,
|
_vm_space.map_guest(page.addr, page.hotspot,
|
||||||
(1 << page.log2_order) / 4096,
|
(1 << page.log2_order) / 4096,
|
||||||
dsc.cacheability(),
|
dsc.cacheability(),
|
||||||
dsc.writable() && attribute.writeable,
|
dsc.writable() && attribute.writeable,
|
||||||
attribute.executable, FLUSH);
|
attribute.executable, FLUSH);
|
||||||
|
|
||||||
|
/* drop all attachment to limit ram usage of this session */
|
||||||
|
while (true) {
|
||||||
|
addr_t out_addr = 0;
|
||||||
|
|
||||||
|
if (!_map.any_block_addr(&out_addr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
detach(out_addr);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
// Alloc_page_table_failed
|
||||||
|
Genode::error("alloc_guest_page_table exception");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
page = flex.page();
|
page = flex.page();
|
||||||
|
|
|
@ -114,26 +114,43 @@ void Genode::Vm_space::unsynchronized_alloc_guest_page_tables(addr_t const start
|
||||||
addr_t constexpr PAGE_TABLE_AREA = 1UL << EPT_PAGE_TABLE_LOG2_SIZE;
|
addr_t constexpr PAGE_TABLE_AREA = 1UL << EPT_PAGE_TABLE_LOG2_SIZE;
|
||||||
addr_t virt = start & ~(PAGE_TABLE_AREA - 1);
|
addr_t virt = start & ~(PAGE_TABLE_AREA - 1);
|
||||||
for (; size != 0; size -= min(size, PAGE_TABLE_AREA), virt += PAGE_TABLE_AREA) {
|
for (; size != 0; size -= min(size, PAGE_TABLE_AREA), virt += PAGE_TABLE_AREA) {
|
||||||
addr_t phys = 0;
|
|
||||||
|
|
||||||
if (!_page_table_registry.page_level3_at(virt, EPT_PAGE_PDPT_LOG2_SIZE)) {
|
if (!_page_table_registry.page_level3_at(virt, EPT_PAGE_PDPT_LOG2_SIZE)) {
|
||||||
/* 512 GB range - page directory pointer table */
|
/* 512 GB range - page directory pointer table */
|
||||||
|
addr_t phys = 0;
|
||||||
Cap_sel const pd = _alloc_and_map<Ept_page_pointer_table_kobj>(virt, map_pdpt, phys);
|
Cap_sel const pd = _alloc_and_map<Ept_page_pointer_table_kobj>(virt, map_pdpt, phys);
|
||||||
_page_table_registry.insert_page_level3(virt, pd, phys, EPT_PAGE_PDPT_LOG2_SIZE);
|
try {
|
||||||
|
_page_table_registry.insert_page_level3(virt, pd, phys, EPT_PAGE_PDPT_LOG2_SIZE);
|
||||||
|
} catch (...) {
|
||||||
|
_unmap_and_free(pd, phys);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_page_table_registry.page_directory_at(virt, EPT_PAGE_DIR_LOG2_SIZE)) {
|
if (!_page_table_registry.page_directory_at(virt, EPT_PAGE_DIR_LOG2_SIZE)) {
|
||||||
/* 1 GB range - page directory */
|
/* 1 GB range - page directory */
|
||||||
|
addr_t phys = 0;
|
||||||
Cap_sel const pd = _alloc_and_map<Ept_page_directory_kobj>(virt, map_directory, phys);
|
Cap_sel const pd = _alloc_and_map<Ept_page_directory_kobj>(virt, map_directory, phys);
|
||||||
_page_table_registry.insert_page_directory(virt, pd, phys,
|
try {
|
||||||
EPT_PAGE_DIR_LOG2_SIZE);
|
_page_table_registry.insert_page_directory(virt, pd, phys,
|
||||||
|
EPT_PAGE_DIR_LOG2_SIZE);
|
||||||
|
} catch (...) {
|
||||||
|
_unmap_and_free(pd, phys);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_page_table_registry.page_table_at(virt, EPT_PAGE_TABLE_LOG2_SIZE)) {
|
if (!_page_table_registry.page_table_at(virt, EPT_PAGE_TABLE_LOG2_SIZE)) {
|
||||||
/* 2 MB range - page table */
|
/* 2 MB range - page table */
|
||||||
|
addr_t phys = 0;
|
||||||
Cap_sel const pt = _alloc_and_map<Ept_page_table_kobj>(virt, map_page_table, phys);
|
Cap_sel const pt = _alloc_and_map<Ept_page_table_kobj>(virt, map_page_table, phys);
|
||||||
_page_table_registry.insert_page_table(virt, pt, phys,
|
|
||||||
EPT_PAGE_TABLE_LOG2_SIZE);
|
try {
|
||||||
|
_page_table_registry.insert_page_table(virt, pt, phys,
|
||||||
|
EPT_PAGE_TABLE_LOG2_SIZE);
|
||||||
|
} catch (...) {
|
||||||
|
_unmap_and_free(pt, phys);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
enum { EXIT_ON_HLT = 1U << 7, EXIT_ON_RDTSC = 1U << 12 };
|
enum { EXIT_ON_HLT = 1U << 7, EXIT_ON_RDTSC = 1U << 12 };
|
||||||
|
|
||||||
addr_t const _vmcs_ctrl0 = EXIT_ON_HLT; // | EXIT_ON_RDTSC;
|
addr_t const _vmcs_ctrl0 = EXIT_ON_HLT;
|
||||||
|
|
||||||
enum { STACK_SIZE = 0x3000 };
|
enum { STACK_SIZE = 0x3000 };
|
||||||
|
|
||||||
|
@ -132,6 +132,18 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
local_state = _remote;
|
local_state = _remote;
|
||||||
_remote = NONE;
|
_remote = NONE;
|
||||||
|
|
||||||
|
if (local_state == PAUSE) {
|
||||||
|
_write_sel4_state(service, state);
|
||||||
|
|
||||||
|
seL4_Word badge = 0;
|
||||||
|
/* consume spurious notification - XXX better way ? */
|
||||||
|
seL4_SetMR(0, state.ip.value());
|
||||||
|
seL4_SetMR(1, _vmcs_ctrl0 | state.ctrl_primary.value());
|
||||||
|
seL4_SetMR(2, state.inj_info.value() & ~0x3000U);
|
||||||
|
if (seL4_VMEnter(&badge) == SEL4_VMENTER_RESULT_FAULT)
|
||||||
|
Genode::error("invalid state ahead ", badge);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_state == NONE) {
|
if (local_state == NONE) {
|
||||||
|
@ -141,16 +153,6 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
if (local_state == PAUSE) {
|
if (local_state == PAUSE) {
|
||||||
|
|
||||||
_write_sel4_state(service, state);
|
|
||||||
|
|
||||||
seL4_Word badge = 0;
|
|
||||||
/* consume spurious notification - XXX better way ? */
|
|
||||||
seL4_SetMR(0, state.ip.value());
|
|
||||||
seL4_SetMR(1, _vmcs_ctrl0 | state.ctrl_primary.value());
|
|
||||||
seL4_SetMR(2, state.inj_info.value() & ~0x3000);
|
|
||||||
if (seL4_VMEnter(&badge) == SEL4_VMENTER_RESULT_FAULT)
|
|
||||||
Genode::error("invalid state ahead ", badge);
|
|
||||||
|
|
||||||
state = Vm_state {};
|
state = Vm_state {};
|
||||||
|
|
||||||
state.ip.value(seL4_GetMR(SEL4_VMENTER_CALL_EIP_MR));
|
state.ip.value(seL4_GetMR(SEL4_VMENTER_CALL_EIP_MR));
|
||||||
|
@ -180,7 +182,7 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
seL4_SetMR(0, state.ip.value());
|
seL4_SetMR(0, state.ip.value());
|
||||||
seL4_SetMR(1, _vmcs_ctrl0 | state.ctrl_primary.value());
|
seL4_SetMR(1, _vmcs_ctrl0 | state.ctrl_primary.value());
|
||||||
seL4_SetMR(2, state.inj_info.value() & ~0x3000);
|
seL4_SetMR(2, state.inj_info.value() & ~0x3000U);
|
||||||
|
|
||||||
seL4_Word badge = 0;
|
seL4_Word badge = 0;
|
||||||
seL4_Word res = seL4_VMEnter(&badge);
|
seL4_Word res = seL4_VMEnter(&badge);
|
||||||
|
@ -255,8 +257,6 @@ struct Vcpu : Genode::Thread
|
||||||
RSP = 0x681c,
|
RSP = 0x681c,
|
||||||
RIP = 0x681e,
|
RIP = 0x681e,
|
||||||
|
|
||||||
INST_LEN = 0x440c,
|
|
||||||
|
|
||||||
EFER = 0x2806,
|
EFER = 0x2806,
|
||||||
|
|
||||||
CTRL_0 = 0x4002,
|
CTRL_0 = 0x4002,
|
||||||
|
@ -322,9 +322,11 @@ struct Vcpu : Genode::Thread
|
||||||
|
|
||||||
INTR_INFO = 0x4016,
|
INTR_INFO = 0x4016,
|
||||||
INTR_ERROR = 0x4018,
|
INTR_ERROR = 0x4018,
|
||||||
|
ENTRY_INST_LEN = 0x401a,
|
||||||
|
|
||||||
IDT_INFO = 0x4408,
|
IDT_INFO = 0x4408,
|
||||||
IDT_ERROR = 0x440a,
|
IDT_ERROR = 0x440a,
|
||||||
|
EXIT_INST_LEN = 0x440c,
|
||||||
|
|
||||||
TSC_OFF_LO = 0x2010,
|
TSC_OFF_LO = 0x2010,
|
||||||
TSC_OFF_HI = 0x2011,
|
TSC_OFF_HI = 0x2011,
|
||||||
|
@ -438,7 +440,9 @@ struct Vcpu : Genode::Thread
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.inj_info.valid()) {
|
if (state.inj_info.valid()) {
|
||||||
addr_t ctrl_0 = _read_vmcs(service, Vmcs::CTRL_0);
|
addr_t ctrl_0 = state.ctrl_primary.valid() ?
|
||||||
|
state.ctrl_primary.value() :
|
||||||
|
_read_vmcs(service, Vmcs::CTRL_0);
|
||||||
|
|
||||||
if (state.inj_info.value() & 0x2000)
|
if (state.inj_info.value() & 0x2000)
|
||||||
Genode::warning("inj_info for NMI not supported");
|
Genode::warning("inj_info for NMI not supported");
|
||||||
|
@ -451,10 +455,8 @@ struct Vcpu : Genode::Thread
|
||||||
state.ctrl_primary.value(ctrl_0);
|
state.ctrl_primary.value(ctrl_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.inj_error.valid()) {
|
if (state.inj_error.valid())
|
||||||
/* not supported by seL4 */
|
_write_vmcs(service, Vmcs::INTR_ERROR, state.inj_error.value());
|
||||||
//_write_vmcs(service, Vmcs::INTR_ERROR, state.inj_error.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.flags.valid())
|
if (state.flags.valid())
|
||||||
_write_vmcs(service, Vmcs::RFLAGS, state.flags.value());
|
_write_vmcs(service, Vmcs::RFLAGS, state.flags.value());
|
||||||
|
@ -465,6 +467,9 @@ struct Vcpu : Genode::Thread
|
||||||
if (state.ip.valid())
|
if (state.ip.valid())
|
||||||
_write_vmcs(service, Vmcs::RIP, state.ip.value());
|
_write_vmcs(service, Vmcs::RIP, state.ip.value());
|
||||||
|
|
||||||
|
if (state.ip_len.valid())
|
||||||
|
_write_vmcs(service, Vmcs::ENTRY_INST_LEN, state.ip_len.value());
|
||||||
|
|
||||||
if (state.efer.valid())
|
if (state.efer.valid())
|
||||||
_write_vmcs(service, Vmcs::EFER, state.efer.value());
|
_write_vmcs(service, Vmcs::EFER, state.efer.value());
|
||||||
|
|
||||||
|
@ -589,11 +594,12 @@ struct Vcpu : Genode::Thread
|
||||||
uint16_t _read_vmcs_16(seL4_X86_VCPU const service, enum Vmcs const field) {
|
uint16_t _read_vmcs_16(seL4_X86_VCPU const service, enum Vmcs const field) {
|
||||||
return _read_vmcsX<uint16_t>(service, field); }
|
return _read_vmcsX<uint16_t>(service, field); }
|
||||||
|
|
||||||
uint16_t _read_vmcs_32(seL4_X86_VCPU const service, enum Vmcs const field) {
|
uint32_t _read_vmcs_32(seL4_X86_VCPU const service, enum Vmcs const field) {
|
||||||
return _read_vmcsX<uint32_t>(service, field); }
|
return _read_vmcsX<uint32_t>(service, field); }
|
||||||
|
|
||||||
void _read_sel4_state_async(seL4_X86_VCPU const service, Vm_state &state)
|
void _read_sel4_state_async(seL4_X86_VCPU const service, Vm_state &state)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
state.ax.value(state.ax.value()); /* XXX ? */
|
state.ax.value(state.ax.value()); /* XXX ? */
|
||||||
state.cx.value(state.cx.value());
|
state.cx.value(state.cx.value());
|
||||||
state.dx.value(state.dx.value());
|
state.dx.value(state.dx.value());
|
||||||
|
@ -602,11 +608,12 @@ struct Vcpu : Genode::Thread
|
||||||
state.di.value(state.di.value()); /* XXX ? */
|
state.di.value(state.di.value()); /* XXX ? */
|
||||||
state.si.value(state.si.value());
|
state.si.value(state.si.value());
|
||||||
state.bp.value(state.bp.value());
|
state.bp.value(state.bp.value());
|
||||||
|
#endif
|
||||||
|
|
||||||
state.flags.value(_read_vmcs(service, Vmcs::RFLAGS));
|
state.flags.value(_read_vmcs(service, Vmcs::RFLAGS));
|
||||||
|
|
||||||
state.ip.value(_read_vmcs(service, Vmcs::RIP));
|
state.ip.value(_read_vmcs(service, Vmcs::RIP));
|
||||||
state.ip_len.value(_read_vmcs(service, Vmcs::INST_LEN));
|
state.ip_len.value(_read_vmcs(service, Vmcs::EXIT_INST_LEN));
|
||||||
|
|
||||||
state.cr3.value(_read_vmcs(service, Vmcs::CR3));
|
state.cr3.value(_read_vmcs(service, Vmcs::CR3));
|
||||||
|
|
||||||
|
@ -630,10 +637,8 @@ struct Vcpu : Genode::Thread
|
||||||
addr_t const cr0_shadow = _read_vmcs(service, Vmcs::CR0_SHADOW);
|
addr_t const cr0_shadow = _read_vmcs(service, Vmcs::CR0_SHADOW);
|
||||||
state.cr0.value((cr0 & ~cr0_mask) | (cr0_shadow & cr0_mask));
|
state.cr0.value((cr0 & ~cr0_mask) | (cr0_shadow & cr0_mask));
|
||||||
|
|
||||||
if (state.cr0.value() != cr0_shadow) {
|
if (state.cr0.value() != cr0_shadow)
|
||||||
Genode::error("reset cr0_shadow to cr0 ", Genode::Hex(cr0), " ", Genode::Hex(cr0_shadow), "->", Genode::Hex(state.cr0.value()));
|
|
||||||
_write_vmcs(service, Vmcs::CR0_SHADOW, state.cr0.value());
|
_write_vmcs(service, Vmcs::CR0_SHADOW, state.cr0.value());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cr2 not supported on seL4 */
|
/* cr2 not supported on seL4 */
|
||||||
|
@ -644,10 +649,8 @@ struct Vcpu : Genode::Thread
|
||||||
addr_t const cr4_shadow = _read_vmcs(service, Vmcs::CR4_SHADOW);
|
addr_t const cr4_shadow = _read_vmcs(service, Vmcs::CR4_SHADOW);
|
||||||
state.cr4.value((cr4 & ~cr4_mask) | (cr4_shadow & cr4_mask));
|
state.cr4.value((cr4 & ~cr4_mask) | (cr4_shadow & cr4_mask));
|
||||||
|
|
||||||
if (state.cr4.value() != cr4_shadow) {
|
if (state.cr4.value() != cr4_shadow)
|
||||||
Genode::error("reset cr4_shadow to cr4 ", Genode::Hex(cr4), " ", Genode::Hex(cr4_shadow), "->", Genode::Hex(state.cr4.value()));
|
|
||||||
_write_vmcs(service, Vmcs::CR4_SHADOW, state.cr4.value());
|
_write_vmcs(service, Vmcs::CR4_SHADOW, state.cr4.value());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Genode::Vm_state::Segment Segment;
|
typedef Genode::Vm_state::Segment Segment;
|
||||||
|
@ -711,9 +714,7 @@ struct Vcpu : Genode::Thread
|
||||||
state.exit_reason == VMEXIT_RECALL)
|
state.exit_reason == VMEXIT_RECALL)
|
||||||
{
|
{
|
||||||
state.inj_info.value(_read_vmcs(service, Vmcs::INTR_INFO));
|
state.inj_info.value(_read_vmcs(service, Vmcs::INTR_INFO));
|
||||||
/* no support by seL4 to read this value */
|
state.inj_error.value(_read_vmcs(service, Vmcs::INTR_ERROR));
|
||||||
state.inj_error.value(0);
|
|
||||||
//state.inj_error.value(_read_vmcs(service, Vmcs::INTR_ERROR));
|
|
||||||
} else {
|
} else {
|
||||||
state.inj_info.value(_read_vmcs(service, Vmcs::IDT_INFO));
|
state.inj_info.value(_read_vmcs(service, Vmcs::IDT_INFO));
|
||||||
state.inj_error.value(_read_vmcs(service, Vmcs::IDT_ERROR));
|
state.inj_error.value(_read_vmcs(service, Vmcs::IDT_ERROR));
|
||||||
|
@ -768,7 +769,7 @@ struct Vcpu : Genode::Thread
|
||||||
{
|
{
|
||||||
Lock::Guard guard(_remote_lock);
|
Lock::Guard guard(_remote_lock);
|
||||||
|
|
||||||
if (_remote == RUN)
|
if (_remote == RUN || _remote == PAUSE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_remote = RUN;
|
_remote = RUN;
|
||||||
|
|
|
@ -27,7 +27,7 @@ set use_nic_bridge 0
|
||||||
|
|
||||||
set use_usb 0
|
set use_usb 0
|
||||||
|
|
||||||
set use_framebuffer 0
|
set use_framebuffer 1
|
||||||
set use_fancy_stuff 0
|
set use_fancy_stuff 0
|
||||||
set use_top 0
|
set use_top 0
|
||||||
|
|
||||||
|
@ -68,6 +68,13 @@ append qemu_args " -m 1536 "
|
||||||
append qemu_args " -cpu phenom "
|
append qemu_args " -cpu phenom "
|
||||||
append qemu_args " -nographic "
|
append qemu_args " -nographic "
|
||||||
|
|
||||||
run_genode_until {\[init -\> seoul\] VMM: # ! PERF: kbuild [ 0-9]+ s ok} 2000
|
run_genode_until {\[init -\> seoul\] VM is starting with } 400
|
||||||
|
set serial_id [output_spawn_id]
|
||||||
|
|
||||||
|
set time_start [ clock seconds ]
|
||||||
|
run_genode_until {\[init -\> seoul\] VMM: # ! PERF: kbuild [ 0-9]+ s ok} 2000 $serial_id
|
||||||
|
set time_end [ clock seconds ]
|
||||||
|
|
||||||
|
puts "\n! PERF: runtime [expr $time_end - $time_start ] seconds ok"
|
||||||
|
|
||||||
puts "Test succeeded"
|
puts "Test succeeded"
|
||||||
|
|
|
@ -16,12 +16,11 @@ import_from_depot [depot_user]/src/[base_src] \
|
||||||
|
|
||||||
assert_spec x86
|
assert_spec x86
|
||||||
|
|
||||||
set rdtsc_exit "no"
|
set map_small "no"
|
||||||
set map_small "no"
|
set vmm_vcpu_same_cpu "no"
|
||||||
|
|
||||||
if {[have_spec sel4]} {
|
if {[have_spec sel4]} {
|
||||||
set map_small "yes"
|
set map_small "yes"
|
||||||
set rdtsc_exit "yes"
|
|
||||||
|
|
||||||
# seL4 has no AMD SVM support
|
# seL4 has no AMD SVM support
|
||||||
if {[have_include "power_on/qemu"]} {
|
if {[have_include "power_on/qemu"]} {
|
||||||
|
@ -31,7 +30,9 @@ if {[have_spec sel4]} {
|
||||||
}
|
}
|
||||||
|
|
||||||
if {[have_spec foc]} {
|
if {[have_spec foc]} {
|
||||||
set rdtsc_exit yes
|
# The performance is considerable bad when
|
||||||
|
# vmm and vcpu is not on same physical CPU
|
||||||
|
set vmm_vcpu_same_cpu "yes"
|
||||||
|
|
||||||
# Qemu SVM has no EPT support
|
# Qemu SVM has no EPT support
|
||||||
if {[have_include "power_on/qemu"]} {
|
if {[have_include "power_on/qemu"]} {
|
||||||
|
@ -71,7 +72,7 @@ build $build_components
|
||||||
|
|
||||||
# write Seoul config file
|
# write Seoul config file
|
||||||
set vm_cfg_fd [open "bin/vm_seoul.cfg" w]
|
set vm_cfg_fd [open "bin/vm_seoul.cfg" w]
|
||||||
puts $vm_cfg_fd "<config map_small=\"$map_small\" exit_on_rdtsc=\"$rdtsc_exit\">"
|
puts $vm_cfg_fd "<config map_small=\"$map_small\" vmm_vcpu_same_cpu=\"$vmm_vcpu_same_cpu\">"
|
||||||
puts $vm_cfg_fd { <machine>
|
puts $vm_cfg_fd { <machine>
|
||||||
<mem start="0x0" end="0x9a000"/>
|
<mem start="0x0" end="0x9a000"/>
|
||||||
<mem start="0x100000" end="0xfffff000"/>
|
<mem start="0x100000" end="0xfffff000"/>
|
||||||
|
|
|
@ -764,6 +764,7 @@ class Machine : public StaticReceiver<Machine>
|
||||||
|
|
||||||
bool _map_small { false };
|
bool _map_small { false };
|
||||||
bool _rdtsc_exit { false };
|
bool _rdtsc_exit { false };
|
||||||
|
bool _same_cpu { false };
|
||||||
Seoul::Network *_nic { nullptr };
|
Seoul::Network *_nic { nullptr };
|
||||||
Rtc::Session *_rtc { nullptr };
|
Rtc::Session *_rtc { nullptr };
|
||||||
|
|
||||||
|
@ -865,8 +866,6 @@ class Machine : public StaticReceiver<Machine>
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging::printf("create vcpu %u\n", _vcpus_up);
|
|
||||||
|
|
||||||
/* detect virtualization extension */
|
/* detect virtualization extension */
|
||||||
Attached_rom_dataspace const info(_env, "platform_info");
|
Attached_rom_dataspace const info(_env, "platform_info");
|
||||||
Genode::Xml_node const features = info.xml().sub_node("hardware").sub_node("features");
|
Genode::Xml_node const features = info.xml().sub_node("hardware").sub_node("features");
|
||||||
|
@ -881,11 +880,15 @@ class Machine : public StaticReceiver<Machine>
|
||||||
|
|
||||||
using Genode::Entrypoint;
|
using Genode::Entrypoint;
|
||||||
using Genode::String;
|
using Genode::String;
|
||||||
|
using Genode::Affinity;
|
||||||
|
|
||||||
|
Affinity::Space space = _env.cpu().affinity_space();
|
||||||
|
Affinity::Location location(space.location_of_index(_vcpus_up + (_same_cpu ? 0 : 1)));
|
||||||
|
|
||||||
String<16> * ep_name = new String<16>("vCPU EP ", _vcpus_up);
|
String<16> * ep_name = new String<16>("vCPU EP ", _vcpus_up);
|
||||||
Entrypoint * ep = new Entrypoint(_env, STACK_SIZE,
|
Entrypoint * ep = new Entrypoint(_env, STACK_SIZE,
|
||||||
ep_name->string(),
|
ep_name->string(),
|
||||||
_env.cpu().affinity_space().location_of_index(_vcpus_up + 1));
|
location);
|
||||||
|
|
||||||
Vcpu * vcpu = new Vcpu(*ep, _vm_con, _heap, _env,
|
Vcpu * vcpu = new Vcpu(*ep, _vm_con, _heap, _env,
|
||||||
_motherboard_lock, msg.vcpu,
|
_motherboard_lock, msg.vcpu,
|
||||||
|
@ -896,6 +899,9 @@ class Machine : public StaticReceiver<Machine>
|
||||||
_vcpus[_vcpus_up] = vcpu;
|
_vcpus[_vcpus_up] = vcpu;
|
||||||
msg.value = _vcpus_up;
|
msg.value = _vcpus_up;
|
||||||
|
|
||||||
|
Logging::printf("create vcpu %u affinity %u:%u\n",
|
||||||
|
_vcpus_up, location.xpos(), location.ypos());
|
||||||
|
|
||||||
_vcpus_up ++;
|
_vcpus_up ++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1140,7 +1146,7 @@ class Machine : public StaticReceiver<Machine>
|
||||||
Boot_module_provider &boot_modules,
|
Boot_module_provider &boot_modules,
|
||||||
Seoul::Guest_memory &guest_memory,
|
Seoul::Guest_memory &guest_memory,
|
||||||
size_t const fb_size,
|
size_t const fb_size,
|
||||||
bool map_small, bool rdtsc_exit)
|
bool map_small, bool rdtsc_exit, bool vmm_vcpu_same_cpu)
|
||||||
:
|
:
|
||||||
_env(env), _heap(heap), _vm_con(vm_con),
|
_env(env), _heap(heap), _vm_con(vm_con),
|
||||||
_clock(Attached_rom_dataspace(env, "platform_info").xml().sub_node("hardware").sub_node("tsc").attribute_value("freq_khz", 0ULL) * 1000ULL),
|
_clock(Attached_rom_dataspace(env, "platform_info").xml().sub_node("hardware").sub_node("tsc").attribute_value("freq_khz", 0ULL) * 1000ULL),
|
||||||
|
@ -1151,7 +1157,8 @@ class Machine : public StaticReceiver<Machine>
|
||||||
_guest_memory(guest_memory),
|
_guest_memory(guest_memory),
|
||||||
_boot_modules(boot_modules),
|
_boot_modules(boot_modules),
|
||||||
_map_small(map_small),
|
_map_small(map_small),
|
||||||
_rdtsc_exit(rdtsc_exit)
|
_rdtsc_exit(rdtsc_exit),
|
||||||
|
_same_cpu(vmm_vcpu_same_cpu)
|
||||||
{
|
{
|
||||||
_timeouts()->init();
|
_timeouts()->init();
|
||||||
|
|
||||||
|
@ -1309,9 +1316,10 @@ void Component::construct(Genode::Env &env)
|
||||||
static Genode::Heap heap(env.ram(), env.rm());
|
static Genode::Heap heap(env.ram(), env.rm());
|
||||||
static Genode::Vm_connection vm_con(env, "Seoul vCPUs", Genode::Cpu_session::PRIORITY_LIMIT / 16);
|
static Genode::Vm_connection vm_con(env, "Seoul vCPUs", Genode::Cpu_session::PRIORITY_LIMIT / 16);
|
||||||
|
|
||||||
Genode::addr_t vm_size = 0;
|
Genode::addr_t vm_size = 0;
|
||||||
bool map_small = false;
|
bool map_small = false;
|
||||||
bool rdtsc_exit = false;
|
bool rdtsc_exit = false;
|
||||||
|
bool vmm_vcpu_same_cpu = false;
|
||||||
|
|
||||||
static Attached_rom_dataspace config(env, "config");
|
static Attached_rom_dataspace config(env, "config");
|
||||||
|
|
||||||
|
@ -1329,6 +1337,7 @@ void Component::construct(Genode::Env &env)
|
||||||
try {
|
try {
|
||||||
map_small = config.xml().attribute_value("map_small", false);
|
map_small = config.xml().attribute_value("map_small", false);
|
||||||
rdtsc_exit = config.xml().attribute_value("exit_on_rdtsc", false);
|
rdtsc_exit = config.xml().attribute_value("exit_on_rdtsc", false);
|
||||||
|
vmm_vcpu_same_cpu = config.xml().attribute_value("vmm_vcpu_same_cpu", false);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
||||||
Genode::log(" using ", map_small ? "small": "large",
|
Genode::log(" using ", map_small ? "small": "large",
|
||||||
|
@ -1401,7 +1410,7 @@ void Component::construct(Genode::Env &env)
|
||||||
|
|
||||||
/* create the PC machine based on the configuration given */
|
/* create the PC machine based on the configuration given */
|
||||||
static Machine machine(env, heap, vm_con, boot_modules, guest_memory,
|
static Machine machine(env, heap, vm_con, boot_modules, guest_memory,
|
||||||
fb_size, map_small, rdtsc_exit);
|
fb_size, map_small, rdtsc_exit, vmm_vcpu_same_cpu);
|
||||||
|
|
||||||
/* create console thread */
|
/* create console thread */
|
||||||
static Seoul::Console vcon(env, heap, machine.motherboard(),
|
static Seoul::Console vcon(env, heap, machine.motherboard(),
|
||||||
|
|
Loading…
Reference in New Issue