diff --git a/repos/base-nova/src/lib/base/vm_session.cc b/repos/base-nova/src/lib/base/vm_session.cc index fc1a4da3f..30daf44ca 100644 --- a/repos/base-nova/src/lib/base/vm_session.cc +++ b/repos/base-nova/src/lib/base/vm_session.cc @@ -473,14 +473,14 @@ struct Vcpu { if (exit_reason != VM_EXIT_RECALL || !previous_blocked) _read_nova_state(utcb, state, exit_reason); - /* consume potential multiple sem ups */ - Nova::sm_ctrl(vcpu->_sm_sel(), Nova::SEMAPHORE_UP); - Nova::sm_ctrl(vcpu->_sm_sel(), Nova::SEMAPHORE_DOWNZERO); - if (exit_reason == VM_EXIT_RECALL) { if (previous_blocked) state.exit_reason = exit_reason; + /* consume potential multiple sem ups */ + Nova::sm_ctrl(vcpu->_sm_sel(), Nova::SEMAPHORE_UP); + Nova::sm_ctrl(vcpu->_sm_sel(), Nova::SEMAPHORE_DOWNZERO); + if (vcpu->_remote == PAUSE) { vcpu->_remote = NONE; } else { @@ -550,8 +550,13 @@ struct Vcpu { if (_dispatching == current) { /* current thread is already dispatching */ - _block = true; - return; + if (_block) + /* issue pause exit next time - fall through */ + _block = false; + else { + _block = true; + return; + } } if ((_ep_handler == current) && _block) { diff --git a/repos/ports/ports/virtualbox5.hash b/repos/ports/ports/virtualbox5.hash index 13bfd34ec..dd486cd0f 100644 --- a/repos/ports/ports/virtualbox5.hash +++ b/repos/ports/ports/virtualbox5.hash @@ -1 +1 @@ -0ccf5764631d03e73d2a952391c96fe457f6f5ee +5de6eead003606684659956308561f9dffcdffba diff --git a/repos/ports/src/virtualbox5/generic/sup_vmm.cc b/repos/ports/src/virtualbox5/generic/sup_vmm.cc index 06d83505f..8074d83a5 100644 --- a/repos/ports/src/virtualbox5/generic/sup_vmm.cc +++ b/repos/ports/src/virtualbox5/generic/sup_vmm.cc @@ -823,13 +823,19 @@ static int _map_memory(Genode::Vm_connection &vm_session, } catch (Genode::Vm_session::Region_conflict) { /* XXX PGMUnmapMemoryGenode on vm_session does not flush caps */ vm_session.detach(GCPhys, mapping_size); - if (retry) { - Genode::error("region conflict - ", Genode::Hex(GCPhys), - " ", Genode::Hex(mapping_size), " vmm_local=", - Genode::Hex(vmm_local), " ", region->cap, - " region=", Genode::Hex(region->vmm_local), - "+", Genode::Hex(region->size)); + Genode::log("region conflict - ", Genode::Hex(GCPhys), + " ", Genode::Hex(mapping_size), " vmm_local=", + Genode::Hex(vmm_local), " ", region->cap, + " region=", Genode::Hex(region->vmm_local), + "+", Genode::Hex(region->size)); + + size_t detach_size = mapping_size; + while (detach_size) { + size_t const size = 4096; + vm_session.detach(GCPhys + (mapping_size - detach_size), size); + detach_size -= detach_size > size ? size : detach_size; + } return VERR_PGM_DYNMAP_FAILED; } @@ -863,8 +869,6 @@ class Pgm_guard int Vcpu_handler::map_memory(Genode::Vm_connection &vm_session, RTGCPHYS const GCPhys, RTGCUINT vbox_fault_reason) { - Pgm_guard guard(*_vm); - _ept_fault_addr_type = PGMPAGETYPE_INVALID; PPGMRAMRANGE const pRam = pgmPhysGetRangeAtOrAbove(_vm, GCPhys); @@ -891,6 +895,7 @@ int Vcpu_handler::map_memory(Genode::Vm_connection &vm_session, && !PGM_PAGE_IS_SPECIAL_ALIAS_MMIO(pPage) && PGM_A20_IS_ENABLED(_vcpu)) { + Pgm_guard guard(*_vm); pgmPhysPageMakeWritable(_vm, pPage, GCPhys); } diff --git a/repos/ports/src/virtualbox5/libc.cc b/repos/ports/src/virtualbox5/libc.cc index f49ef596a..47689b119 100644 --- a/repos/ports/src/virtualbox5/libc.cc +++ b/repos/ports/src/virtualbox5/libc.cc @@ -296,3 +296,10 @@ extern "C" long pathconf(char const *path, int name) errno = EINVAL; return -1; } + +extern "C" int siginterrupt(int, int) +{ + Genode::Thread * thread = Genode::Thread::myself(); + Genode::warning(__func__, " called, caller=", thread ? thread->name() : ""); + return 0; +} diff --git a/repos/ports/src/virtualbox5/patches/register.patch b/repos/ports/src/virtualbox5/patches/register.patch new file mode 100644 index 000000000..04479ac33 --- /dev/null +++ b/repos/ports/src/virtualbox5/patches/register.patch @@ -0,0 +1,159 @@ +--- a/src/app/virtualbox/src/VBox/VMM/VMMAll/PGMAllGst.h ++++ b/src/app/virtualbox/src/VBox/VMM/VMMAll/PGMAllGst.h +@@ -101,9 +101,9 @@ + if (RT_FAILURE(rc)) + return PGM_GST_NAME(WalkReturnBadPhysAddr)(pVCpu, pWalk, 4, rc); + +- PX86PML4 register pPml4 = pWalk->pPml4; +- X86PML4E register Pml4e; +- PX86PML4E register pPml4e; ++ PX86PML4 pPml4 = pWalk->pPml4; ++ X86PML4E Pml4e; ++ PX86PML4E pPml4e; + + pWalk->pPml4e = pPml4e = &pPml4->a[(GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK]; + pWalk->Pml4e.u = Pml4e.u = pPml4e->u; +@@ -127,9 +127,9 @@ + } + { + # if PGM_GST_TYPE == PGM_TYPE_AMD64 || PGM_GST_TYPE == PGM_TYPE_PAE +- PX86PDPT register pPdpt = pWalk->pPdpt; +- PX86PDPE register pPdpe; +- X86PDPE register Pdpe; ++ PX86PDPT pPdpt = pWalk->pPdpt; ++ PX86PDPE pPdpe; ++ X86PDPE Pdpe; + + pWalk->pPdpe = pPdpe = &pPdpt->a[(GCPtr >> GST_PDPT_SHIFT) & GST_PDPT_MASK]; + pWalk->Pdpe.u = Pdpe.u = pPdpe->u; +@@ -151,8 +151,8 @@ + # endif + } + { +- PGSTPD register pPd = pWalk->pPd; +- PGSTPDE register pPde; ++ PGSTPD pPd = pWalk->pPd; ++ PGSTPDE pPde; + GSTPDE Pde; + + pWalk->pPde = pPde = &pPd->a[(GCPtr >> GST_PD_SHIFT) & GST_PD_MASK]; +@@ -201,9 +201,9 @@ + return PGM_GST_NAME(WalkReturnBadPhysAddr)(pVCpu, pWalk, 1, rc); + } + { +- PGSTPT register pPt = pWalk->pPt; +- PGSTPTE register pPte; +- GSTPTE register Pte; ++ PGSTPT pPt = pWalk->pPt; ++ PGSTPTE pPte; ++ GSTPTE Pte; + + pWalk->pPte = pPte = &pPt->a[(GCPtr >> GST_PT_SHIFT) & GST_PT_MASK]; + pWalk->Pte.u = Pte.u = pPte->u; +--- a/src/app/virtualbox/include/iprt/log.h ++++ b/src/app/virtualbox/include/iprt/log.h +@@ -607,7 +607,7 @@ + # define _LogIt(a_fFlags, a_iGroup, ...) \ + do \ + { \ +- register PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \ ++ PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \ + if (RT_LIKELY(!LogIt_pLogger)) \ + { /* likely */ } \ + else \ +@@ -621,7 +621,7 @@ + # define LogIt(a_fFlags, a_iGroup, fmtargs) \ + do \ + { \ +- register PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \ ++ PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(a_fFlags, a_iGroup)); \ + if (RT_LIKELY(!LogIt_pLogger)) \ + { /* likely */ } \ + else \ +@@ -632,7 +632,7 @@ + # define LogItAlways(a_fFlags, a_iGroup, fmtargs) \ + do \ + { \ +- register PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)); \ ++ PRTLOGGER LogIt_pLogger = RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)); \ + if (LogIt_pLogger) \ + LogIt_pLogger->pfnLogger fmtargs; \ + } while (0) +--- a/src/app/virtualbox/src/VBox/Devices/Network/DevPCNet.cpp ++++ b/src/app/virtualbox/src/VBox/Devices/Network/DevPCNet.cpp +@@ -1244,8 +1244,8 @@ + */ + static void pcnetUpdateIrq(PPCNETSTATE pThis) + { +- register int iISR = 0; +- register uint16_t csr0 = pThis->aCSR[0]; ++ int iISR = 0; ++ uint16_t csr0 = pThis->aCSR[0]; + + csr0 &= ~0x0080; /* clear INTR */ + +--- a/src/app/virtualbox/src/VBox/Runtime/common/table/avl_Base.cpp.h ++++ b/src/app/virtualbox/src/VBox/Runtime/common/table/avl_Base.cpp.h +@@ -266,7 +266,7 @@ + } + else + { +- register unsigned char uchHeight = (unsigned char)(KMAX(uchLeftHeight, uchRightHeight) + 1); ++ unsigned char uchHeight = (unsigned char)(KMAX(uchLeftHeight, uchRightHeight) + 1); + if (uchHeight == pNode->uchHeight) + break; + pNode->uchHeight = uchHeight; +@@ -300,10 +300,10 @@ + { + KAVLSTACK AVLStack; + PPKAVLNODECORE ppCurNode = ppTree; +- register PKAVLNODECORE pCurNode; +- register KAVLKEY Key = pNode->Key; NOREF(Key); ++ PKAVLNODECORE pCurNode; ++ KAVLKEY Key = pNode->Key; NOREF(Key); + #ifdef KAVL_RANGE +- register KAVLKEY KeyLast = pNode->KeyLast; NOREF(KeyLast); ++ KAVLKEY KeyLast = pNode->KeyLast; NOREF(KeyLast); + #endif + + AVLStack.cEntries = 0; +@@ -400,7 +400,7 @@ + { + KAVLSTACK AVLStack; + PPKAVLNODECORE ppDeleteNode = ppTree; +- register PKAVLNODECORE pDeleteNode; ++ PKAVLNODECORE pDeleteNode; + + AVLStack.cEntries = 0; + +@@ -427,7 +427,7 @@ + /* find the rightmost node in the left tree. */ + const unsigned iStackEntry = AVLStack.cEntries; + PPKAVLNODECORE ppLeftLeast = &pDeleteNode->pLeft; +- register PKAVLNODECORE pLeftLeast = KAVL_GET_POINTER(ppLeftLeast); ++ PKAVLNODECORE pLeftLeast = KAVL_GET_POINTER(ppLeftLeast); + + while (pLeftLeast->pRight != KAVL_NULL) + { +--- a/src/app/virtualbox/src/VBox/Runtime/common/string/utf-16.cpp ++++ b/src/app/virtualbox/src/VBox/Runtime/common/string/utf-16.cpp +@@ -193,7 +193,7 @@ + RT_EXPORT_SYMBOL(RTUtf16Len); + + +-RTDECL(int) RTUtf16Cmp(register PCRTUTF16 pwsz1, register PCRTUTF16 pwsz2) ++RTDECL(int) RTUtf16Cmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2) + { + if (pwsz1 == pwsz2) + return 0; +@@ -204,8 +204,8 @@ + + for (;;) + { +- register RTUTF16 wcs = *pwsz1; +- register int iDiff = wcs - *pwsz2; ++ RTUTF16 wcs = *pwsz1; ++ int iDiff = wcs - *pwsz2; + if (iDiff || !wcs) + return iDiff; + pwsz1++; diff --git a/repos/ports/src/virtualbox5/patches/series b/repos/ports/src/virtualbox5/patches/series index 3ec7c43b2..c86455b0f 100644 --- a/repos/ports/src/virtualbox5/patches/series +++ b/repos/ports/src/virtualbox5/patches/series @@ -33,3 +33,5 @@ tm_4s.patch rem_tss.patch mem_leak.patch rem_mem.patch +vga.patch +register.patch diff --git a/repos/ports/src/virtualbox5/patches/vga.patch b/repos/ports/src/virtualbox5/patches/vga.patch new file mode 100644 index 000000000..a066abd91 --- /dev/null +++ b/repos/ports/src/virtualbox5/patches/vga.patch @@ -0,0 +1,26 @@ +--- a/src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp ++++ b/src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp +@@ -2249,12 +2249,23 @@ + + const uint64_t u64ScreenSize = (uint64_t)screen.u32LineSize * screen.u32Height; + ++ if (!( screen.u32StartOffset <= pView->u32ViewSize ++ && u64ScreenSize <= pView->u32MaxScreenSize ++ && screen.u32StartOffset <= pView->u32ViewSize - (uint32_t)u64ScreenSize)) ++ { ++ RTLogPrintf("%s - assertion failed - u32StartOffset=%#x u32ViewSize=%#x u64ScreenSize=%#RX64 u32MaxScreenSize=%#x", ++ __func__, screen.u32StartOffset, pView->u32ViewSize, u64ScreenSize, pView->u32MaxScreenSize); ++#if 0 + ASSERT_GUEST_LOGREL_MSG_RETURN( screen.u32StartOffset <= pView->u32ViewSize + && u64ScreenSize <= pView->u32MaxScreenSize + && screen.u32StartOffset <= pView->u32ViewSize - (uint32_t)u64ScreenSize, + ("u32StartOffset=%#x u32ViewSize=%#x u64ScreenSize=%#RX64 u32MaxScreenSize=%#x\n", + screen.u32StartOffset, pView->u32ViewSize, u64ScreenSize, pView->u32MaxScreenSize), + VERR_INVALID_PARAMETER); ++#endif ++ return VERR_INVALID_PARAMETER; ++ } ++ + RT_UNTRUSTED_VALIDATED_FENCE(); + + /* diff --git a/repos/ports/src/virtualbox5/thread.cc b/repos/ports/src/virtualbox5/thread.cc index 176e23faa..67819b7e8 100644 --- a/repos/ports/src/virtualbox5/thread.cc +++ b/repos/ports/src/virtualbox5/thread.cc @@ -12,6 +12,7 @@ */ /* Genode */ +#include #include #include #include @@ -31,12 +32,25 @@ /* vbox */ #include +static bool use_priorities() +{ + Genode::Attached_rom_dataspace const platform(genode_env(), "platform_info"); + Genode::Xml_node const kernel = platform.xml().sub_node("kernel"); + return kernel.attribute_value("name", Genode::String<16>("unknown")) == "nova"; +} + static long prio_class(RTTHREADTYPE const type) { unsigned const VIRTUAL_GENODE_VBOX_LEVELS = 16; static_assert (RTTHREADTYPE_END < VIRTUAL_GENODE_VBOX_LEVELS, "prio levels exceeds VIRTUAL_GENODE_VBOX_LEVELS"); + /* evaluate once */ + static bool const priorities = use_priorities(); + + if (!priorities) + return Genode::Cpu_session::DEFAULT_PRIORITY; + return (VIRTUAL_GENODE_VBOX_LEVELS - type) * Genode::Cpu_session::PRIORITY_LIMIT / VIRTUAL_GENODE_VBOX_LEVELS; } @@ -124,6 +138,10 @@ extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr, log("Upgrading memory for creation of " "thread '", Cstring(rtthread->szName), "'"); cpu_connection(rtthread->enmType)->upgrade_ram(4096); + } catch (Genode::Signal_receiver::Signal_not_pending) { + error("signal not pending ?"); + } catch (Out_of_caps) { + error("out of caps ..."); } catch (...) { break; } } diff --git a/repos/ports/src/virtualbox5/vcpu.h b/repos/ports/src/virtualbox5/vcpu.h index 636f2c62f..8c7a4f3f1 100644 --- a/repos/ports/src/virtualbox5/vcpu.h +++ b/repos/ports/src/virtualbox5/vcpu.h @@ -17,8 +17,6 @@ /* Genode includes */ #include -#include -#include #include #include #include @@ -45,13 +43,8 @@ /* Genode libc pthread binding */ #include "thread.h" -/* LibC includes */ -#include - #include -static bool debug_map_memory = false; - /* * VirtualBox stores segment attributes in Intel format using a 32-bit * value. Genode represents the attributes in packed format using a 16-bit @@ -68,31 +61,13 @@ static inline Genode::uint32_t sel_ar_conv_from_genode(Genode::uint16_t v) return (v & 0xff) | (((uint32_t )v << 4) & 0x1f000); } -namespace Vcpu_sync -{ - struct Session : Genode::Session - { - GENODE_RPC(Rpc_resume, void, resume); - GENODE_RPC(Rpc_request_pause, void, request_pause); - GENODE_RPC_INTERFACE(Rpc_resume, Rpc_request_pause); - }; - - struct Client : Genode::Rpc_client - { - Client(Genode::Capability cap) : Rpc_client(cap) { } - - void resume() { call(); } - void request_pause() { call(); } - }; -}; - -class Vcpu_handler : public Genode::List::Element, - public Genode::Rpc_object +class Vcpu_handler : public Genode::List::Element { protected: Genode::Entrypoint _ep; - Genode::Lock _lock; + Genode::Lock _lock_emt; + Genode::Semaphore _sem_handler; Genode::Vm_state *_state { nullptr }; /* halt / wakeup handling with timeout support */ @@ -106,9 +81,8 @@ class Vcpu_handler : public Genode::List::Element, bool npt_ept_unmap { false }; /* state machine between EMT and EP thread of a vCPU */ - enum State { RUNNING, PAUSED, IRQ_WIN, NPT_EPT } _vm_state { PAUSED }; - - Vcpu_sync::Client _ep_emt; + enum { RUNNING, PAUSED, IRQ_WIN, NPT_EPT } _vm_state { PAUSED }; + enum { PAUSE_EXIT, RUN } _next_state { RUN }; private: @@ -171,10 +145,17 @@ class Vcpu_handler : public Genode::List::Element, Genode::memcpy(fpu, pCtx->pXStateR3, sizeof(X86FXSTATE)); }); - _ep_emt.resume(); + Assert(_vm_state == IRQ_WIN || _vm_state == PAUSED || _vm_state == NPT_EPT); + Assert(_next_state == PAUSE_EXIT || _next_state == RUN); + + /* wake up vcpu ep handler */ + _sem_handler.up(); /* wait for next exit */ - _lock.lock(); + _lock_emt.lock(); + + /* next time run - recall() may change this */ + _next_state = RUN; /* write FPU state of vCPU to pCtx */ _state->fpu.value([&] (uint8_t *fpu, size_t const size) { @@ -192,7 +173,7 @@ class Vcpu_handler : public Genode::List::Element, if (npt_ept_unmap) { Genode::error("NPT/EPT unmap not supported - stop"); while (true) { - _lock.lock(); + _lock_emt.lock(); } } @@ -223,10 +204,10 @@ class Vcpu_handler : public Genode::List::Element, _vm_state = PAUSED; - _lock.unlock(); + _lock_emt.unlock(); } - void _recall_handler() + bool _recall_handler() { if (_vm_state != RUNNING) Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason)); @@ -252,15 +233,14 @@ class Vcpu_handler : public Genode::List::Element, /* got recall during irq injection and the guest is ready for * delivery of IRQ - just continue */ - run_vm(); - return; + return /* no-wait */ false; } /* are we forced to go back to emulation mode ? */ if (!continue_hw_accelerated()) { /* go back to emulation mode */ _default_handler(); - return; + return /* wait */ true; } /* check whether we have to request irq injection window */ @@ -268,12 +248,11 @@ class Vcpu_handler : public Genode::List::Element, *_state = Genode::Vm_state {}; /* reset */ _state->inj_info.value(_state->inj_info.value()); _irq_win = true; - run_vm(); - return; + return /* no-wait */ false; } _default_handler(); - return; + return /* wait */ true; } inline bool vbox_to_state(VM *pVM, PVMCPU pVCpu) @@ -500,7 +479,7 @@ class Vcpu_handler : public Genode::List::Element, _vm_exits ++; _vm_state = IRQ_WIN; - _lock.unlock(); + _lock_emt.unlock(); } void _npt_ept() @@ -512,7 +491,7 @@ class Vcpu_handler : public Genode::List::Element, _vm_exits ++; _vm_state = NPT_EPT; - _lock.unlock(); + _lock_emt.unlock(); } void _irq_window_pthread() @@ -672,7 +651,6 @@ class Vcpu_handler : public Genode::List::Element, virtual bool hw_save_state(Genode::Vm_state *, VM *, PVMCPU) = 0; virtual int vm_exit_requires_instruction_emulation(PCPUMCTX) = 0; - virtual void run_vm() = 0; virtual void pause_vm() = 0; virtual int attach_memory_to_vm(RTGCPHYS const, RTGCUINT vbox_fault_reason) = 0; @@ -696,35 +674,9 @@ class Vcpu_handler : public Genode::List::Element, : _ep(env, stack_size, Genode::String<12>("EP-EMT-", cpu_id).string(), location), - _ep_emt(_ep.rpc_ep().manage(this)), _cpu_id(cpu_id) { } - void resume() - { - PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(_vcpu); - - Assert(_vm_state == IRQ_WIN || _vm_state == PAUSED || _vm_state == NPT_EPT); - - _vm_state = RUNNING; - run_vm(); - } - - void request_pause() - { - _recall_req ++; - - if (_irq_win) { - _recall_skip ++; - return; - } - - if (_vm_state != RUNNING) - return; - - pause_vm(); - } - unsigned int cpu_id() { return _cpu_id; } @@ -738,7 +690,19 @@ class Vcpu_handler : public Genode::List::Element, if (_vm != vm || _vcpu != &vm->aCpus[_cpu_id]) Genode::error("wrong CPU !?"); - _ep_emt.request_pause(); + _recall_req ++; + + if (_irq_win) { + _recall_skip ++; + return; + } + + asm volatile ("":::"memory"); + + if (_vm_state != PAUSED) + pause_vm(); + + _next_state = PAUSE_EXIT; #if 0 if (_recall_req % 1000 == 0) { diff --git a/repos/ports/src/virtualbox5/vcpu_svm.h b/repos/ports/src/virtualbox5/vcpu_svm.h index 3a9e1ff5e..4d5f66c83 100644 --- a/repos/ports/src/virtualbox5/vcpu_svm.h +++ b/repos/ports/src/virtualbox5/vcpu_svm.h @@ -1,11 +1,11 @@ /* - * \brief Genode/Nova specific VirtualBox SUPLib supplements + * \brief Genode specific VirtualBox SUPLib supplements * \author Alexander Boettcher * \date 2013-11-18 */ /* - * Copyright (C) 2013-2017 Genode Labs GmbH + * Copyright (C) 2013-2019 Genode Labs GmbH * * This file is distributed under the terms of the GNU General Public License * version 2. @@ -76,14 +76,12 @@ class Vcpu_handler_svm : public Vcpu_handler next_utcb.ctrl[1] = 0; } - void _svm_recall() { Vcpu_handler::_recall_handler(); } - void _handle_vm_exception() { unsigned const exit = _state->exit_reason; -// Genode::warning(__func__, " ", Genode::Hex(exit), " _irq_win=", _irq_win); + bool recall_wait = true; + switch (exit) { - case RECALL: _svm_recall(); break; case SVM_EXIT_IOIO: _svm_ioio(); break; case SVM_EXIT_VINTR: _svm_vintr(); break; // case SVM_EXIT_RDTSC: _svm_default(); break; @@ -91,17 +89,36 @@ class Vcpu_handler_svm : public Vcpu_handler case SVM_NPT: _svm_npt(); break; case SVM_EXIT_HLT: _svm_default(); break; case SVM_EXIT_CPUID: _svm_default(); break; + case RECALL: + recall_wait = Vcpu_handler::_recall_handler(); + break; case VCPU_STARTUP: _svm_startup(); - _lock.unlock(); + _lock_emt.unlock(); /* pause - no resume */ - return; + break; default: Genode::error(__func__, " unknown exit - stop - ", Genode::Hex(exit)); _vm_state = PAUSED; return; } + + if (exit == RECALL && !recall_wait) { + _vm_state = RUNNING; + run_vm(); + return; + } + + /* wait until EMT thread wake's us up */ + _sem_handler.down(); + + /* resume vCPU */ + _vm_state = RUNNING; + if (_next_state == RUN) + run_vm(); + else + pause_vm(); /* cause pause exit */ } void run_vm() { _vm_session.run(_vcpu); } @@ -154,13 +171,12 @@ class Vcpu_handler_svm : public Vcpu_handler _state = _state_ds.local_addr(); /* sync with initial startup exception */ - _lock.lock(); + _lock_emt.lock(); _vm_session.run(_vcpu); /* sync with initial startup exception */ - _lock.lock(); -// _lock.unlock(); + _lock_emt.lock(); } bool hw_save_state(Genode::Vm_state *state, VM * pVM, PVMCPU pVCpu) { diff --git a/repos/ports/src/virtualbox5/vcpu_vmx.h b/repos/ports/src/virtualbox5/vcpu_vmx.h index 030f98750..fe686f04b 100644 --- a/repos/ports/src/virtualbox5/vcpu_vmx.h +++ b/repos/ports/src/virtualbox5/vcpu_vmx.h @@ -1,12 +1,12 @@ /* - * \brief Genode/Nova specific VirtualBox SUPLib supplements + * \brief Genode specific VirtualBox SUPLib supplements * \author Alexander Boettcher * \author Norman Feske * \author Christian Helmuth */ /* - * Copyright (C) 2013-2017 Genode Labs GmbH + * Copyright (C) 2013-2019 Genode Labs GmbH * * This file is distributed under the terms of the GNU General Public License * version 2. @@ -106,8 +106,6 @@ class Vcpu_handler_vmx : public Vcpu_handler void _vmx_irqwin() { _irq_window(); } - void _vmx_recall() { Vcpu_handler::_recall_handler(); } - __attribute__((noreturn)) void _vmx_invalid() { unsigned const dubious = _state->inj_info.value() | @@ -124,19 +122,12 @@ class Vcpu_handler_vmx : public Vcpu_handler exit(-1); } - /* - * This VM exit is in part handled by the NOVA kernel (writing the CR - * register) and in part by VirtualBox (updating the PDPTE registers, - * which requires access to the guest physical memory). - * Intel manual sections 4.4.1 of Vol. 3A and 26.3.2.4 of Vol. 3C - * indicate the conditions when the PDPTE registers need to get - * updated. - */ void _vmx_mov_crx() { _default_handler(); return; } void _handle_vm_exception() { unsigned const exit = _state->exit_reason; + bool recall_wait = true; switch (exit) { case VMX_EXIT_TRIPLE_FAULT: _vmx_triple(); break; @@ -157,20 +148,39 @@ class Vcpu_handler_vmx : public Vcpu_handler case VMX_EXIT_WBINVD: _vmx_default(); break; case VMX_EXIT_MOV_CRX: _vmx_mov_crx(); break; case VMX_EXIT_MOV_DRX: _vmx_default(); break; + case VMX_EXIT_XSETBV: _vmx_default(); break; case VMX_EXIT_TPR_BELOW_THRESHOLD: _vmx_default(); break; case VMX_EXIT_EPT_VIOLATION: _vmx_ept(); break; - case RECALL: _vmx_recall(); break; + case RECALL: + recall_wait = Vcpu_handler::_recall_handler(); + break; case VCPU_STARTUP: _vmx_startup(); - _lock.unlock(); + _lock_emt.unlock(); /* pause - no resume */ - return; + break; default: Genode::error(__func__, " unknown exit - stop - ", Genode::Hex(exit)); _vm_state = PAUSED; return; } + + if (exit == RECALL && !recall_wait) { + _vm_state = RUNNING; + run_vm(); + return; + } + + /* wait until EMT thread wake's us up */ + _sem_handler.down(); + + /* resume vCPU */ + _vm_state = RUNNING; + if (_next_state == RUN) + run_vm(); + else + pause_vm(); /* cause pause exit */ } void run_vm() { _vm_session.run(_vcpu); } @@ -204,6 +214,7 @@ class Vcpu_handler_vmx : public Vcpu_handler case VMX_EXIT_MOV_DRX: case VMX_EXIT_TPR_BELOW_THRESHOLD: case VMX_EXIT_EPT_VIOLATION: + case VMX_EXIT_XSETBV: case VCPU_STARTUP: case RECALL: /* todo - touch all members */ @@ -235,13 +246,12 @@ class Vcpu_handler_vmx : public Vcpu_handler _state = _state_ds.local_addr(); /* sync with initial startup exception */ - _lock.lock(); + _lock_emt.lock(); _vm_session.run(_vcpu); /* sync with initial startup exception */ - _lock.lock(); -// _lock.unlock(); + _lock_emt.lock(); } bool hw_save_state(Genode::Vm_state *state, VM * pVM, PVMCPU pVCpu) {