diff --git a/repos/base-foc/ports/foc.hash b/repos/base-foc/ports/foc.hash index aa4d84839..271498149 100644 --- a/repos/base-foc/ports/foc.hash +++ b/repos/base-foc/ports/foc.hash @@ -1 +1 @@ -1367e8214fa7c02682a97bbb3b375b0d792f4fed +9db0c4985349d47251e91e4e61145526668278fc diff --git a/repos/base-foc/ports/foc.port b/repos/base-foc/ports/foc.port index 354d7846a..5066bb426 100644 --- a/repos/base-foc/ports/foc.port +++ b/repos/base-foc/ports/foc.port @@ -1,6 +1,6 @@ LICENSE := GPLv2 VERSION := git DOWNLOADS := foc.git -URL(foc) := https://github.com/cproc/foc.git -REV(foc) := b74e427801f045578c401a140a8e66404bb3ff19 +URL(foc) := https://github.com/alex-ab/foc.git +REV(foc) := a8411389dffc3c55dc5809d2e849b3afac94ee5d DIR(foc) := src/kernel/foc diff --git a/repos/base-foc/src/core/include/vm_session_component.h b/repos/base-foc/src/core/include/vm_session_component.h index 6a9f55fc4..3ab566029 100644 --- a/repos/base-foc/src/core/include/vm_session_component.h +++ b/repos/base-foc/src/core/include/vm_session_component.h @@ -63,11 +63,8 @@ class Genode::Vm_session_component Rpc_entrypoint &_ep; Con_ram_allocator _constrained_md_ram_alloc; - Sliced_heap _sliced_heap; - Slab _slab { max(sizeof(Vcpu), sizeof(Rm_region)), - 4096 - Sliced_heap::meta_data_size(), - nullptr, &_sliced_heap }; - Avl_region _map { &_slab }; + Sliced_heap _heap; + Avl_region _map { &_heap }; List _vcpus { }; Cap_mapping _task_vcpu { true }; unsigned _id_alloc { 0 }; diff --git a/repos/base-foc/src/core/vm_session_component.cc b/repos/base-foc/src/core/vm_session_component.cc index b35bf555f..c268a4553 100644 --- a/repos/base-foc/src/core/vm_session_component.cc +++ b/repos/base-foc/src/core/vm_session_component.cc @@ -40,7 +40,7 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, Cap_quota_guard(resources.cap_quota), _ep(ep), _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}); @@ -61,7 +61,7 @@ Vm_session_component::~Vm_session_component() { for (;Vcpu * vcpu = _vcpus.first();) { _vcpus.remove(vcpu); - destroy(_slab, vcpu); + destroy(_heap, vcpu); } /* detach all regions */ @@ -118,7 +118,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) /* allocate vCPU object */ Vcpu * vcpu = nullptr; try { - vcpu = new (_slab) Vcpu(_constrained_md_ram_alloc, + vcpu = new (_heap) Vcpu(_constrained_md_ram_alloc, _cap_quota_guard(), Vcpu_id {_id_alloc}); @@ -134,12 +134,12 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) }); } catch (int) { if (vcpu) - destroy(_slab, vcpu); + destroy(_heap, vcpu); return; } catch (...) { if (vcpu) - destroy(_slab, vcpu); + destroy(_heap, vcpu); throw; } diff --git a/repos/base-foc/src/lib/base/x86/vm_session.cc b/repos/base-foc/src/lib/base/x86/vm_session.cc index 09e9b6370..966965844 100644 --- a/repos/base-foc/src/lib/base/x86/vm_session.cc +++ b/repos/base-foc/src/lib/base/x86/vm_session.cc @@ -46,7 +46,6 @@ static uint32_t svm_features() } static bool svm_np() { return svm_features() & (1U << 0); } -static bool svm_instr_decode_support() { return svm_features() & (1U << 7); } struct Vcpu; @@ -137,6 +136,7 @@ struct Vcpu : Genode::Thread INTR_INFO = 0x4016, INTR_ERROR = 0x4018, + ENTRY_INST_LEN = 0x401a, IDT_INFO = 0x4408, IDT_ERROR = 0x440a, @@ -154,39 +154,44 @@ struct Vcpu : Genode::Thread enum Vmcb { - CTRL0_INTR = 1u << 0, - CTRL0_NMI = 1u << 1, - CTRL0_INIT = 1u << 3, - CTRL0_INVD = 1u << 22, - CTRL0_HLT = 1u << 24, + CTRL0_VINTR = 1u << 4, CTRL0_IO = 1u << 27, CTRL0_MSR = 1u << 28, - CTRL0_SHUTDOWN = 1u << 31, - AMD_EXIT_INVALID = 0xfd + AMD_SVM_ENABLE = 1 << 12, + + AMD_EXIT_INVALID = 0xfd, }; enum { CR0_PE = 0, /* 1U << 0 - not needed in case of UG */ CR0_CP = 1U << 1, + CR0_TS = 1u << 3, CR0_NE = 1U << 5, CR0_NM = 1U << 29, CR0_CD = 1U << 30, CR0_PG = 0 /* 1U << 31 - not needed in case of UG */ }; - addr_t const vmcb_ctrl0 = CTRL0_INTR | CTRL0_NMI | CTRL0_INIT | - CTRL0_INVD | CTRL0_HLT | CTRL0_IO | - CTRL0_MSR | CTRL0_SHUTDOWN; + addr_t const _cr0_mask { CR0_CP | CR0_NM | CR0_NE | CR0_CD }; + addr_t const vmcb_ctrl0 { CTRL0_IO | CTRL0_MSR }; + 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 }; - 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_set = 0; + addr_t const vmcs_cr0_mask { _cr0_mask | CR0_PE | CR0_PG }; + addr_t const vmcs_cr0_set { 0 }; - addr_t const vmcs_cr4_mask = CR4_VMX; - addr_t const vmcs_cr4_set = CR4_VMX; + addr_t const vmcs_cr4_mask { CR4_VMX }; + addr_t const vmcs_cr4_set { CR4_VMX }; Signal_context_capability _signal; Semaphore _wake_up { 0 }; @@ -211,7 +216,7 @@ struct Vcpu : Genode::Thread PAUSE = 1, RUN = 2, TERMINATE = 3, - } _remote { PAUSE }; + } _remote { NONE }; Lock _remote_lock { Lock::UNLOCKED }; void entry() override @@ -265,7 +270,6 @@ struct Vcpu : Genode::Thread * Fiasoc.OC peculiarities */ if (_vm_type == Virt::SVM) { - enum { AMD_SVM_ENABLE = 1 << 12 }; state.efer.value(state.efer.value() | AMD_SVM_ENABLE); } if (_vm_type == Virt::SVM) { @@ -274,12 +278,9 @@ struct Vcpu : Genode::Thread if (!vmcb->control_area.np_enable) vmcb->control_area.intercept_exceptions |= 1 << 14; - /* XXX - further stuff needed .. */ - if (!svm_instr_decode_support()) { - vmcb->control_area.intercept_instruction0 = vmcb_ctrl0; - vmcb->control_area.intercept_rd_crX = 0x0001; /* cr0 */ - vmcb->control_area.intercept_wr_crX = 0x0001; /* cr0 */ - } + vmcb->control_area.intercept_instruction0 = vmcb_ctrl0; + vmcb->control_area.intercept_rd_crX = 0x0001; /* cr0 */ + vmcb->control_area.intercept_wr_crX = 0x0001; /* cr0 */ } if (_vm_type == Virt::VMX) { 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); } + 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 }; while (true) { @@ -303,6 +311,15 @@ struct Vcpu : Genode::Thread Lock::Guard guard(_remote_lock); local_state = _remote; _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) { @@ -316,11 +333,6 @@ struct Vcpu : Genode::Thread if (_vm_type == Virt::VMX) _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; if (_vm_type == Virt::SVM) @@ -350,8 +362,6 @@ struct Vcpu : Genode::Thread if (_vm_type == Virt::VMX) _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 */ l4_msgtag_t tag = l4_thread_vcpu_resume_start(); tag = l4_thread_vcpu_resume_commit(L4_INVALID_CAP, tag); @@ -377,9 +387,11 @@ struct Vcpu : Genode::Thread } /* consume notification */ - 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_NEVER); + while (vcpu->sticky_flags) { + 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 = reason & 0xff; @@ -400,9 +412,11 @@ struct Vcpu : Genode::Thread } /* consume notification */ - 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); + while (vcpu->sticky_flags) { + 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 = 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_shadow = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR0_SHADOW); state.cr0.value((cr0 & ~vmcs_cr0_mask) | (cr0_shadow & vmcs_cr0_mask)); - 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())); + if (state.cr0.value() != cr0_shadow) Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR0_SHADOW, state.cr0.value()); - } } 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_shadow = Fiasco::l4_vm_vmx_read(vmcs, Vmcs::CR4_SHADOW); state.cr4.value((cr4 & ~vmcs_cr4_mask) | (cr4_shadow & vmcs_cr4_mask)); - 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())); + if (state.cr4.value() != cr4_shadow) Fiasco::l4_vm_vmx_write(vmcs, Vmcs::CR4_SHADOW, 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_16; using Fiasco::l4_vm_vmx_read_32; @@ -636,7 +638,7 @@ struct Vcpu : Genode::Thread state.sp.value(vmcb->state_save_area.rsp); 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); @@ -651,10 +653,20 @@ struct Vcpu : Genode::Thread state.r15.value(vcpu->r.r15); #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.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; @@ -733,9 +745,7 @@ struct Vcpu : Genode::Thread state.tsc.value(Trace::timestamp()); state.tsc_offset.value(_tsc_offset); - if (state.efer.valid()) { - Genode::error("efer not implemented"); - } + state.efer.value(vmcb->state_save_area.efer); if (state.pdpte_0.valid() || state.pdpte_1.valid() || state.pdpte_2.valid() || state.pdpte_3.valid()) { @@ -760,12 +770,14 @@ struct Vcpu : Genode::Thread using Fiasco::l4_vm_vmx_write; if (state.ax.valid() || state.cx.valid() || state.dx.valid() || - state.bx.valid() || state.bp.valid() || state.di.valid() || - state.si.valid()) { + state.bx.valid()) { vcpu->r.ax = state.ax.value(); vcpu->r.cx = state.cx.value(); vcpu->r.dx = state.dx.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.di = state.di.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()); } -#if 1 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) 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, state.inj_error.value()); } -#endif if (state.flags.valid()) l4_vm_vmx_write(vmcs, Vmcs::FLAGS, state.flags.value()); @@ -855,24 +867,27 @@ struct Vcpu : Genode::Thread if (state.ip.valid()) 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()) l4_vm_vmx_write(vmcs, Vmcs::EFER, state.efer.value()); if (state.ctrl_primary.valid()) 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()) l4_vm_vmx_write(vmcs, Vmcs::CTRL_1, - state.ctrl_secondary.value()); + state.ctrl_secondary.value()); if (state.intr_state.valid()) l4_vm_vmx_write(vmcs, Vmcs::STATE_INTR, - state.intr_state.value()); + state.intr_state.value()); if (state.actv_state.valid()) l4_vm_vmx_write(vmcs, Vmcs::STATE_ACTV, - state.actv_state.valid()); + state.actv_state.value()); if (state.cs.valid()) { 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) { if (state.ax.valid() || state.cx.valid() || state.dx.valid() || - state.bx.valid() || state.bp.valid() || state.di.valid() || - state.si.valid()) { + state.bx.valid()) { + vmcb->state_save_area.rax = state.ax.value(); vcpu->r.ax = state.ax.value(); vcpu->r.cx = state.cx.value(); vcpu->r.dx = state.dx.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.di = state.di.value(); vcpu->r.si = state.si.value(); @@ -1007,7 +1025,8 @@ struct Vcpu : Genode::Thread vmcb->state_save_area.dr7 = state.dr7.value(); 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 vmcb->state_save_area.xcr0 = state.cr0(); #endif @@ -1019,13 +1038,36 @@ struct Vcpu : Genode::Thread if (state.cr3.valid()) vmcb->state_save_area.cr3 = state.cr3.value(); - if (state.cr4.valid()) - vmcb->state_save_area.cr4 = state.cr4.value(); + if (state.cr4.valid()) { + 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()) - Genode::error(__LINE__, " not implemented "); - if (state.inj_error.valid()) - Genode::error(__LINE__, " not implemented "); + 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 = 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()) vmcb->state_save_area.rflags = state.flags.value(); @@ -1037,14 +1079,7 @@ struct Vcpu : Genode::Thread vmcb->state_save_area.rip = state.ip.value(); if (state.efer.valid()) - vmcb->state_save_area.efer = state.efer.value(); - - 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(); + vmcb->state_save_area.efer = state.efer.value() | AMD_SVM_ENABLE; if (state.intr_state.valid()) vmcb->control_area.interrupt_shadow = state.intr_state.value(); @@ -1162,7 +1197,7 @@ struct Vcpu : Genode::Thread void resume() { Lock::Guard guard(_remote_lock); - if (_remote == RUN) + if (_remote == RUN || _remote == PAUSE) return; _remote = RUN; diff --git a/repos/base-nova/src/core/include/vm_session_component.h b/repos/base-nova/src/core/include/vm_session_component.h index a6ad59ad5..37fcbbb8d 100644 --- a/repos/base-nova/src/core/include/vm_session_component.h +++ b/repos/base-nova/src/core/include/vm_session_component.h @@ -74,11 +74,8 @@ class Genode::Vm_session_component Rpc_entrypoint &_ep; Con_ram_allocator _constrained_md_ram_alloc; - Sliced_heap _sliced_heap; - Slab _slab { max(sizeof(Vcpu), sizeof(Rm_region)), - 4096 - Sliced_heap::meta_data_size(), - nullptr, &_sliced_heap }; - Avl_region _map { &_slab }; + Sliced_heap _heap; + Avl_region _map { &_heap }; addr_t _pd_sel { 0 }; unsigned _id_alloc { 0 }; unsigned _priority; diff --git a/repos/base-nova/src/core/vm_session_component.cc b/repos/base-nova/src/core/vm_session_component.cc index 5d6506206..3cf86bf2c 100644 --- a/repos/base-nova/src/core/vm_session_component.cc +++ b/repos/base-nova/src/core/vm_session_component.cc @@ -151,7 +151,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) return; /* allocate vCPU object */ - Vcpu &vcpu = *new (_slab) Vcpu(_constrained_md_ram_alloc, + Vcpu &vcpu = *new (_heap) Vcpu(_constrained_md_ram_alloc, _cap_quota_guard(), Vcpu_id {_id_alloc}); @@ -169,7 +169,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) if (res != Nova::NOVA_OK) { error("create_sm = ", res); - destroy(_slab, &vcpu); + destroy(_heap, &vcpu); return; } @@ -182,7 +182,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) if (res != Nova::NOVA_OK) { error("create_ec = ", res); - destroy(_slab, &vcpu); + destroy(_heap, &vcpu); return; } @@ -204,7 +204,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) if (res != Nova::NOVA_OK) { error("map sm ", res, " ", _id_alloc); - destroy(_slab, &vcpu); + destroy(_heap, &vcpu); return; } @@ -283,8 +283,8 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, Cap_quota_guard(resources.cap_quota), _ep(ep), _constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()), - _sliced_heap(_constrained_md_ram_alloc, local_rm), - _priority(scale_priority(priority, "VM sesssion")) + _heap(_constrained_md_ram_alloc, local_rm), + _priority(scale_priority(priority, "VM session")) { _cap_quota_guard().withdraw(Cap_quota{1}); @@ -312,7 +312,7 @@ Vm_session_component::~Vm_session_component() { for (;Vcpu * vcpu = _vcpus.first();) { _vcpus.remove(vcpu); - destroy(_slab, vcpu); + destroy(_heap, vcpu); } /* detach all regions */ diff --git a/repos/base-nova/src/lib/base/vm_session.cc b/repos/base-nova/src/lib/base/vm_session.cc index 471b88f09..273f81687 100644 --- a/repos/base-nova/src/lib/base/vm_session.cc +++ b/repos/base-nova/src/lib/base/vm_session.cc @@ -227,6 +227,7 @@ struct Vcpu { if (state.ip.valid()) { utcb.mtd |= Nova::Mtd::EIP; utcb.ip = state.ip.value(); + utcb.instr_len = state.ip_len.value(); } if (state.dr7.valid()) { diff --git a/repos/base-sel4/patches/intel_vmcs.patch b/repos/base-sel4/patches/intel_vmcs.patch new file mode 100644 index 000000000..f0806b05a --- /dev/null +++ b/repos/base-sel4/patches/intel_vmcs.patch @@ -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); diff --git a/repos/base-sel4/ports/sel4.hash b/repos/base-sel4/ports/sel4.hash index db7bb5378..94fbbf1f9 100644 --- a/repos/base-sel4/ports/sel4.hash +++ b/repos/base-sel4/ports/sel4.hash @@ -1 +1 @@ -8518d37c4b819daba60648ca23a739ccf1f55460 +34b8f0e01692d1d2ba2f02c98bafe321fc09de22 diff --git a/repos/base-sel4/src/core/include/vm_session_component.h b/repos/base-sel4/src/core/include/vm_session_component.h index faaa9a027..e1739db98 100644 --- a/repos/base-sel4/src/core/include/vm_session_component.h +++ b/repos/base-sel4/src/core/include/vm_session_component.h @@ -57,14 +57,13 @@ class Genode::Vm_session_component Rpc_entrypoint &_ep; Constrained_ram_allocator _constrained_md_ram_alloc; - Sliced_heap _sliced_heap; Heap _heap; Avl_region _map { &_heap }; List _vcpus { }; unsigned _id_alloc { 0 }; unsigned _pd_id { 0 }; Cap_sel _vm_page_table; - Page_table_registry _page_table_registry { _sliced_heap }; + Page_table_registry _page_table_registry { _heap }; Vm_space _vm_space; struct { addr_t _phys; diff --git a/repos/base-sel4/src/core/include/vm_space.h b/repos/base-sel4/src/core/include/vm_space.h index 394690e90..66ea903d1 100644 --- a/repos/base-sel4/src/core/include/vm_space.h +++ b/repos/base-sel4/src/core/include/vm_space.h @@ -127,10 +127,15 @@ class Genode::Vm_space Leaf_cnode _vm_cnodes[NUM_LEAF_CNODES]; + public: + /** * Allocator for the selectors within '_vm_cnodes' */ using Selector_allocator = Bit_allocator<1UL << NUM_VM_SEL_LOG2>; + + private: + Selector_allocator _sel_alloc { }; /** @@ -188,7 +193,7 @@ class Genode::Vm_space * wasting of resources (idx selectors, creating kernel * capabilities, causing kernel warning ...). */ - return false; + return true; } /* allocate page-table-entry selector */ addr_t pte_idx; @@ -277,6 +282,15 @@ class Genode::Vm_space 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: /** @@ -348,12 +362,7 @@ class Genode::Vm_space return true; }, [&] (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); + _unmap_and_free(idx, paddr); }); for (unsigned i = 0; i < NUM_LEAF_CNODES; i++) { diff --git a/repos/base-sel4/src/core/spec/arm/vm_space.cc b/repos/base-sel4/src/core/spec/arm/vm_space.cc index 34f2f8342..8a25313b9 100644 --- a/repos/base-sel4/src/core/spec/arm/vm_space.cc +++ b/repos/base-sel4/src/core/spec/arm/vm_space.cc @@ -77,7 +77,12 @@ void Genode::Vm_space::unsynchronized_alloc_page_tables(addr_t const start, /* 1 MB range - page table */ Cap_sel const pt = _alloc_and_map(virt, map_page_table, phys); - _page_table_registry.insert_page_table(virt, pt, phys, - PAGE_TABLE_LOG2_SIZE); + try { + _page_table_registry.insert_page_table(virt, pt, phys, + PAGE_TABLE_LOG2_SIZE); + } catch (...) { + _unmap_and_free(pt, phys); + throw; + } } } diff --git a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc index a251fb34e..5ce0836e8 100644 --- a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc +++ b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc @@ -77,7 +77,6 @@ try Cap_quota_guard(resources.cap_quota), _ep(ep), _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), _pd_id(Platform_pd::pd_id_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(); 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 }; try { + _vm_space.alloc_guest_page_tables(page.hotspot, 1 << page.log2_order); _vm_space.map_guest(page.addr, page.hotspot, (1 << page.log2_order) / 4096, dsc.cacheability(), dsc.writable() && attribute.writeable, attribute.executable, NO_FLUSH); } 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(); + } if (full.reason == Page_table_registry::Mapping_cache_full::CAPS) throw Out_of_caps(); return; - } catch (Genode::Bit_allocator<4096u>::Out_of_indices) { - Genode::warning("run out of indices - flush all"); + } catch (Vm_space::Selector_allocator::Out_of_indices) { + 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, (1 << page.log2_order) / 4096, dsc.cacheability(), dsc.writable() && attribute.writeable, 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(); diff --git a/repos/base-sel4/src/core/spec/x86/vm_space.cc b/repos/base-sel4/src/core/spec/x86/vm_space.cc index f2ba3a91f..2d75d5417 100644 --- a/repos/base-sel4/src/core/spec/x86/vm_space.cc +++ b/repos/base-sel4/src/core/spec/x86/vm_space.cc @@ -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 virt = start & ~(PAGE_TABLE_AREA - 1); 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)) { /* 512 GB range - page directory pointer table */ + addr_t phys = 0; Cap_sel const pd = _alloc_and_map(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)) { /* 1 GB range - page directory */ + addr_t phys = 0; Cap_sel const pd = _alloc_and_map(virt, map_directory, phys); - _page_table_registry.insert_page_directory(virt, pd, phys, - EPT_PAGE_DIR_LOG2_SIZE); + try { + _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)) { /* 2 MB range - page table */ + addr_t phys = 0; Cap_sel const pt = _alloc_and_map(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; + } } } } diff --git a/repos/base-sel4/src/lib/base/x86/vm_session.cc b/repos/base-sel4/src/lib/base/x86/vm_session.cc index 1b9e3f92c..333f2a5e0 100644 --- a/repos/base-sel4/src/lib/base/x86/vm_session.cc +++ b/repos/base-sel4/src/lib/base/x86/vm_session.cc @@ -54,7 +54,7 @@ struct Vcpu : Genode::Thread 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 }; @@ -132,6 +132,18 @@ struct Vcpu : Genode::Thread local_state = _remote; _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) { @@ -141,16 +153,6 @@ struct Vcpu : Genode::Thread 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.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(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 res = seL4_VMEnter(&badge); @@ -255,8 +257,6 @@ struct Vcpu : Genode::Thread RSP = 0x681c, RIP = 0x681e, - INST_LEN = 0x440c, - EFER = 0x2806, CTRL_0 = 0x4002, @@ -322,9 +322,11 @@ struct Vcpu : Genode::Thread INTR_INFO = 0x4016, INTR_ERROR = 0x4018, + ENTRY_INST_LEN = 0x401a, IDT_INFO = 0x4408, IDT_ERROR = 0x440a, + EXIT_INST_LEN = 0x440c, TSC_OFF_LO = 0x2010, TSC_OFF_HI = 0x2011, @@ -438,7 +440,9 @@ struct Vcpu : Genode::Thread } 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) Genode::warning("inj_info for NMI not supported"); @@ -451,10 +455,8 @@ struct Vcpu : Genode::Thread state.ctrl_primary.value(ctrl_0); } - if (state.inj_error.valid()) { - /* not supported by seL4 */ - //_write_vmcs(service, Vmcs::INTR_ERROR, state.inj_error.value()); - } + if (state.inj_error.valid()) + _write_vmcs(service, Vmcs::INTR_ERROR, state.inj_error.value()); if (state.flags.valid()) _write_vmcs(service, Vmcs::RFLAGS, state.flags.value()); @@ -465,6 +467,9 @@ struct Vcpu : Genode::Thread if (state.ip.valid()) _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()) _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) { return _read_vmcsX(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(service, field); } void _read_sel4_state_async(seL4_X86_VCPU const service, Vm_state &state) { +#if 0 state.ax.value(state.ax.value()); /* XXX ? */ state.cx.value(state.cx.value()); state.dx.value(state.dx.value()); @@ -602,11 +608,12 @@ struct Vcpu : Genode::Thread state.di.value(state.di.value()); /* XXX ? */ state.si.value(state.si.value()); state.bp.value(state.bp.value()); +#endif state.flags.value(_read_vmcs(service, Vmcs::RFLAGS)); 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)); @@ -630,10 +637,8 @@ struct Vcpu : Genode::Thread addr_t const cr0_shadow = _read_vmcs(service, Vmcs::CR0_SHADOW); state.cr0.value((cr0 & ~cr0_mask) | (cr0_shadow & cr0_mask)); - 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())); + if (state.cr0.value() != cr0_shadow) _write_vmcs(service, Vmcs::CR0_SHADOW, state.cr0.value()); - } } /* cr2 not supported on seL4 */ @@ -644,10 +649,8 @@ struct Vcpu : Genode::Thread addr_t const cr4_shadow = _read_vmcs(service, Vmcs::CR4_SHADOW); state.cr4.value((cr4 & ~cr4_mask) | (cr4_shadow & cr4_mask)); - 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())); + if (state.cr4.value() != cr4_shadow) _write_vmcs(service, Vmcs::CR4_SHADOW, state.cr4.value()); - } } typedef Genode::Vm_state::Segment Segment; @@ -711,9 +714,7 @@ struct Vcpu : Genode::Thread state.exit_reason == VMEXIT_RECALL) { state.inj_info.value(_read_vmcs(service, Vmcs::INTR_INFO)); - /* no support by seL4 to read this value */ - state.inj_error.value(0); - //state.inj_error.value(_read_vmcs(service, Vmcs::INTR_ERROR)); + state.inj_error.value(_read_vmcs(service, Vmcs::INTR_ERROR)); } else { state.inj_info.value(_read_vmcs(service, Vmcs::IDT_INFO)); state.inj_error.value(_read_vmcs(service, Vmcs::IDT_ERROR)); @@ -768,7 +769,7 @@ struct Vcpu : Genode::Thread { Lock::Guard guard(_remote_lock); - if (_remote == RUN) + if (_remote == RUN || _remote == PAUSE) return; _remote = RUN; diff --git a/repos/ports/run/seoul-kernelbuild.run b/repos/ports/run/seoul-kernelbuild.run index f1b9e3d18..5168d7796 100644 --- a/repos/ports/run/seoul-kernelbuild.run +++ b/repos/ports/run/seoul-kernelbuild.run @@ -27,7 +27,7 @@ set use_nic_bridge 0 set use_usb 0 -set use_framebuffer 0 +set use_framebuffer 1 set use_fancy_stuff 0 set use_top 0 @@ -68,6 +68,13 @@ append qemu_args " -m 1536 " append qemu_args " -cpu phenom " 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" diff --git a/repos/ports/run/seoul.inc b/repos/ports/run/seoul.inc index 57407108e..17e524547 100644 --- a/repos/ports/run/seoul.inc +++ b/repos/ports/run/seoul.inc @@ -16,12 +16,11 @@ import_from_depot [depot_user]/src/[base_src] \ 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]} { set map_small "yes" - set rdtsc_exit "yes" # seL4 has no AMD SVM support if {[have_include "power_on/qemu"]} { @@ -31,7 +30,9 @@ if {[have_spec sel4]} { } 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 if {[have_include "power_on/qemu"]} { @@ -71,7 +72,7 @@ build $build_components # write Seoul config file set vm_cfg_fd [open "bin/vm_seoul.cfg" w] -puts $vm_cfg_fd "" +puts $vm_cfg_fd "" puts $vm_cfg_fd { diff --git a/repos/ports/src/app/seoul/component.cc b/repos/ports/src/app/seoul/component.cc index 2f8590803..f39f20117 100644 --- a/repos/ports/src/app/seoul/component.cc +++ b/repos/ports/src/app/seoul/component.cc @@ -764,6 +764,7 @@ class Machine : public StaticReceiver bool _map_small { false }; bool _rdtsc_exit { false }; + bool _same_cpu { false }; Seoul::Network *_nic { nullptr }; Rtc::Session *_rtc { nullptr }; @@ -865,8 +866,6 @@ class Machine : public StaticReceiver return false; } - Logging::printf("create vcpu %u\n", _vcpus_up); - /* detect virtualization extension */ Attached_rom_dataspace const info(_env, "platform_info"); Genode::Xml_node const features = info.xml().sub_node("hardware").sub_node("features"); @@ -881,11 +880,15 @@ class Machine : public StaticReceiver using Genode::Entrypoint; 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); Entrypoint * ep = new Entrypoint(_env, STACK_SIZE, ep_name->string(), - _env.cpu().affinity_space().location_of_index(_vcpus_up + 1)); + location); Vcpu * vcpu = new Vcpu(*ep, _vm_con, _heap, _env, _motherboard_lock, msg.vcpu, @@ -896,6 +899,9 @@ class Machine : public StaticReceiver _vcpus[_vcpus_up] = vcpu; msg.value = _vcpus_up; + Logging::printf("create vcpu %u affinity %u:%u\n", + _vcpus_up, location.xpos(), location.ypos()); + _vcpus_up ++; return true; @@ -1140,7 +1146,7 @@ class Machine : public StaticReceiver Boot_module_provider &boot_modules, Seoul::Guest_memory &guest_memory, 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), _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 _guest_memory(guest_memory), _boot_modules(boot_modules), _map_small(map_small), - _rdtsc_exit(rdtsc_exit) + _rdtsc_exit(rdtsc_exit), + _same_cpu(vmm_vcpu_same_cpu) { _timeouts()->init(); @@ -1309,9 +1316,10 @@ void Component::construct(Genode::Env &env) static Genode::Heap heap(env.ram(), env.rm()); static Genode::Vm_connection vm_con(env, "Seoul vCPUs", Genode::Cpu_session::PRIORITY_LIMIT / 16); - Genode::addr_t vm_size = 0; - bool map_small = false; - bool rdtsc_exit = false; + Genode::addr_t vm_size = 0; + bool map_small = false; + bool rdtsc_exit = false; + bool vmm_vcpu_same_cpu = false; static Attached_rom_dataspace config(env, "config"); @@ -1329,6 +1337,7 @@ void Component::construct(Genode::Env &env) try { map_small = config.xml().attribute_value("map_small", 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 (...) { } 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 */ 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 */ static Seoul::Console vcon(env, heap, machine.motherboard(),