228 lines
5.8 KiB
C++
228 lines
5.8 KiB
C++
/*
|
|
* \brief VirtualBox SUPLib supplements
|
|
* \author Norman Feske
|
|
* \date 2013-08-20
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
|
*
|
|
* This file is distributed under the terms of the GNU General Public License
|
|
* version 2.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <base/attached_ram_dataspace.h>
|
|
#include <trace/timestamp.h>
|
|
|
|
/* Genode/Virtualbox includes */
|
|
#include "sup.h"
|
|
#include "vmm.h"
|
|
|
|
/* VirtualBox includes */
|
|
#include <iprt/ldr.h>
|
|
#include <iprt/semaphore.h>
|
|
#include <VBox/err.h>
|
|
|
|
|
|
SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)
|
|
{
|
|
return sizeof(void *) == 4 ? SUPPAGINGMODE_32_BIT : SUPPAGINGMODE_AMD64_NX;
|
|
}
|
|
|
|
|
|
int SUPR3Term(bool) { return VINF_SUCCESS; }
|
|
|
|
|
|
int SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod,
|
|
uint32_t fFlags, PRTERRINFO pErrInfo)
|
|
{
|
|
return RTLdrLoad(pszFilename, phLdrMod);
|
|
}
|
|
|
|
|
|
SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
|
|
{
|
|
Genode::log(__func__, " pvPages=", pvPages, " pages=", cPages);
|
|
return VINF_SUCCESS;
|
|
}
|
|
|
|
|
|
int SUPR3QueryMicrocodeRev(uint32_t *puMicrocodeRev)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
uint32_t SUPSemEventMultiGetResolution(PSUPDRVSESSION)
|
|
{
|
|
return 100000*10; /* called by 'vmR3HaltGlobal1Init' */
|
|
}
|
|
|
|
|
|
int SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent)
|
|
{
|
|
return RTSemEventCreate((PRTSEMEVENT)phEvent);
|
|
}
|
|
|
|
|
|
int SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
|
|
{
|
|
Assert (hEvent);
|
|
|
|
return RTSemEventDestroy((RTSEMEVENT)hEvent);
|
|
}
|
|
|
|
|
|
int SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
|
|
{
|
|
Assert (hEvent);
|
|
|
|
return RTSemEventSignal((RTSEMEVENT)hEvent);
|
|
}
|
|
|
|
|
|
int SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent,
|
|
uint32_t cMillies)
|
|
{
|
|
Assert (hEvent);
|
|
|
|
return RTSemEventWaitNoResume((RTSEMEVENT)hEvent, cMillies);
|
|
}
|
|
|
|
|
|
int SUPSemEventMultiCreate(PSUPDRVSESSION, PSUPSEMEVENTMULTI phEventMulti)
|
|
{
|
|
RTSEMEVENTMULTI sem;
|
|
|
|
/*
|
|
* Input validation.
|
|
*/
|
|
AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
|
|
|
|
/*
|
|
* Create the event semaphore object.
|
|
*/
|
|
int rc = RTSemEventMultiCreate(&sem);
|
|
|
|
static_assert(sizeof(sem) == sizeof(*phEventMulti), "oi");
|
|
*phEventMulti = reinterpret_cast<SUPSEMEVENTMULTI>(sem);
|
|
return rc;
|
|
}
|
|
|
|
|
|
int SUPSemEventMultiWaitNoResume(PSUPDRVSESSION, SUPSEMEVENTMULTI event,
|
|
uint32_t ms)
|
|
{
|
|
RTSEMEVENTMULTI const rtevent = reinterpret_cast<RTSEMEVENTMULTI>(event);
|
|
return RTSemEventMultiWait(rtevent, ms);
|
|
}
|
|
|
|
int SUPSemEventMultiSignal(PSUPDRVSESSION, SUPSEMEVENTMULTI event) {
|
|
return RTSemEventMultiSignal(reinterpret_cast<RTSEMEVENTMULTI>(event)); }
|
|
|
|
int SUPSemEventMultiReset(PSUPDRVSESSION, SUPSEMEVENTMULTI event) {
|
|
return RTSemEventMultiReset(reinterpret_cast<RTSEMEVENTMULTI>(event)); }
|
|
|
|
int SUPSemEventMultiClose(PSUPDRVSESSION, SUPSEMEVENTMULTI event) {
|
|
return RTSemEventMultiDestroy(reinterpret_cast<RTSEMEVENTMULTI>(event)); }
|
|
|
|
|
|
int SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
|
|
void *pvArg)
|
|
{
|
|
if (uOperation == VMMR0_DO_CALL_HYPERVISOR) {
|
|
Genode::log(__func__, ": VMMR0_DO_CALL_HYPERVISOR - doing nothing");
|
|
return VINF_SUCCESS;
|
|
}
|
|
if (uOperation == VMMR0_DO_VMMR0_TERM) {
|
|
Genode::log(__func__, ": VMMR0_DO_VMMR0_TERM - doing nothing");
|
|
return VINF_SUCCESS;
|
|
}
|
|
if (uOperation == VMMR0_DO_GVMM_DESTROY_VM) {
|
|
Genode::log(__func__, ": VMMR0_DO_GVMM_DESTROY_VM - doing nothing");
|
|
return VINF_SUCCESS;
|
|
}
|
|
|
|
AssertMsg(uOperation != VMMR0_DO_VMMR0_TERM &&
|
|
uOperation != VMMR0_DO_CALL_HYPERVISOR &&
|
|
uOperation != VMMR0_DO_GVMM_DESTROY_VM,
|
|
("SUPR3CallVMMR0: unhandled uOperation %d", uOperation));
|
|
return VERR_GENERAL_FAILURE;
|
|
}
|
|
|
|
|
|
void genode_VMMR0_DO_GVMM_CREATE_VM(PSUPVMMR0REQHDR pReqHdr)
|
|
{
|
|
GVMMCREATEVMREQ &req = reinterpret_cast<GVMMCREATEVMREQ &>(*pReqHdr);
|
|
|
|
size_t const cCpus = req.cCpus;
|
|
|
|
/*
|
|
* Allocate and initialize VM struct
|
|
*
|
|
* The VM struct is followed by the variable-sizedA array of VMCPU
|
|
* objects. 'RT_UOFFSETOF' is used to determine the size including
|
|
* the VMCPU array.
|
|
*
|
|
* VM struct must be page-aligned, which is checked at least in
|
|
* PDMR3CritSectGetNop().
|
|
*/
|
|
size_t const cbVM = RT_UOFFSETOF(VM, aCpus[cCpus]);
|
|
|
|
static Genode::Attached_ram_dataspace vm(genode_env().ram(),
|
|
genode_env().rm(),
|
|
cbVM);
|
|
Assert (vm.size() >= cbVM);
|
|
|
|
VM *pVM = vm.local_addr<VM>();
|
|
Genode::memset(pVM, 0, cbVM);
|
|
|
|
/*
|
|
* On Genode, VMMR0 and VMMR3 share a single address space. Hence, the
|
|
* same pVM pointer is valid as pVMR0 and pVMR3.
|
|
*/
|
|
pVM->enmVMState = VMSTATE_CREATING;
|
|
pVM->pVMR0 = (RTHCUINTPTR)pVM;
|
|
pVM->pVMRC = (RTGCUINTPTR)pVM;
|
|
pVM->pSession = req.pSession;
|
|
pVM->cbSelf = cbVM;
|
|
pVM->cCpus = cCpus;
|
|
pVM->uCpuExecutionCap = 100; /* expected by 'vmR3CreateU()' */
|
|
pVM->offVMCPU = RT_UOFFSETOF(VM, aCpus);
|
|
|
|
for (uint32_t i = 0; i < cCpus; i++) {
|
|
pVM->aCpus[i].pVMR0 = pVM->pVMR0;
|
|
pVM->aCpus[i].pVMR3 = pVM;
|
|
pVM->aCpus[i].idHostCpu = NIL_RTCPUID;
|
|
pVM->aCpus[i].hNativeThreadR0 = NIL_RTNATIVETHREAD;
|
|
}
|
|
|
|
pVM->aCpus[0].hNativeThreadR0 = RTThreadNativeSelf();
|
|
|
|
/* out parameters of the request */
|
|
req.pVMR0 = pVM->pVMR0;
|
|
req.pVMR3 = pVM;
|
|
}
|
|
|
|
|
|
void genode_VMMR0_DO_GVMM_REGISTER_VMCPU(PVMR0 pVMR0, VMCPUID idCpu)
|
|
{
|
|
PVM pVM = reinterpret_cast<PVM>(pVMR0);
|
|
pVM->aCpus[idCpu].hNativeThreadR0 = RTThreadNativeSelf();
|
|
}
|
|
|
|
|
|
HRESULT genode_check_memory_config(ComObjPtr<Machine>,
|
|
size_t const memory_vmm)
|
|
{
|
|
/* Request max available memory */
|
|
size_t const memory_available = genode_env().pd().avail_ram().value;
|
|
|
|
if (memory_vmm <= memory_available)
|
|
return S_OK;
|
|
|
|
Genode::error("Available memory too low to start the VM - available: ",
|
|
memory_available, " MB < ", memory_vmm, " MB requested");
|
|
return E_FAIL;
|
|
}
|