2016-08-15 12:27:54 +02:00
|
|
|
/*
|
|
|
|
* \brief Genode/Nova specific VirtualBox SUPLib supplements
|
|
|
|
* \author Alexander Boettcher
|
|
|
|
* \author Norman Feske
|
|
|
|
* \author Christian Helmuth
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-09 16:13:21 +01:00
|
|
|
* Copyright (C) 2006-2013 Oracle Corporation
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2016-08-15 12:27:54 +02:00
|
|
|
*
|
|
|
|
* This file is distributed under the terms of the GNU General Public License
|
|
|
|
* version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
2017-02-09 16:13:21 +01:00
|
|
|
#include <util/bit_allocator.h>
|
2016-08-15 12:27:54 +02:00
|
|
|
#include <base/log.h>
|
|
|
|
#include <base/semaphore.h>
|
|
|
|
#include <util/flex_iterator.h>
|
|
|
|
#include <rom_session/connection.h>
|
|
|
|
#include <timer_session/connection.h>
|
2017-01-05 13:45:37 +01:00
|
|
|
#include <base/attached_rom_dataspace.h>
|
|
|
|
#include <base/attached_ram_dataspace.h>
|
2016-08-15 12:27:54 +02:00
|
|
|
#include <trace/timestamp.h>
|
|
|
|
|
|
|
|
#include <vmm/vcpu_thread.h>
|
|
|
|
#include <vmm/vcpu_dispatcher.h>
|
|
|
|
|
|
|
|
/* NOVA includes that come with Genode */
|
|
|
|
#include <nova/syscalls.h>
|
|
|
|
|
|
|
|
/* Genode's VirtualBox includes */
|
2017-02-09 16:13:21 +01:00
|
|
|
#include "EMInternal.h" /* enable access to em.s.* */
|
2017-01-05 13:45:37 +01:00
|
|
|
#include "vmm.h"
|
2016-08-15 12:27:54 +02:00
|
|
|
#include "vcpu.h"
|
|
|
|
#include "vcpu_svm.h"
|
|
|
|
#include "vcpu_vmx.h"
|
|
|
|
|
|
|
|
/* libc memory allocator */
|
|
|
|
#include <libc_mem_alloc.h>
|
|
|
|
|
|
|
|
#include "mm.h"
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
|
2016-09-15 14:40:37 +02:00
|
|
|
extern "C" bool PGMUnmapMemoryGenode(void *, ::size_t);
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
/*
|
|
|
|
* Tracking required to fulfill VMM allocation requests of VM memory
|
|
|
|
*/
|
|
|
|
enum {
|
|
|
|
CHUNKID_PAGE_START = 1,
|
|
|
|
CHUNKID_PAGE_END = 2,
|
|
|
|
CHUNKID_START = CHUNKID_PAGE_END + 1,
|
|
|
|
|
|
|
|
ONE_PAGE_SIZE = 4096,
|
|
|
|
PAGES_SUPERPAGE = GMM_CHUNK_SIZE / ONE_PAGE_SIZE,
|
|
|
|
HANDY_PAGES = PAGES_SUPERPAGE * (CHUNKID_PAGE_END - CHUNKID_PAGE_START + 1),
|
|
|
|
|
|
|
|
MAX_VM_MEMORY = 16ULL * 1024 * 1024 * 1024, /* 16 Gb */
|
|
|
|
MAX_CHUNK_IDS = MAX_VM_MEMORY / GMM_CHUNK_SIZE,
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Genode::Bit_allocator<HANDY_PAGES> Page_ids;
|
|
|
|
typedef Genode::Bit_allocator<MAX_CHUNK_IDS> Chunk_ids;
|
|
|
|
typedef Genode::Bit_array<PAGES_SUPERPAGE> Free_ids;
|
|
|
|
|
|
|
|
static Page_ids page_ids;
|
|
|
|
static Chunk_ids chunk_ids;
|
|
|
|
|
|
|
|
|
|
|
|
static Sub_rm_connection &vm_memory(Genode::addr_t vm_size = 0)
|
|
|
|
{
|
|
|
|
/* memory used by the VM in any order as the VMM asks for allocations */
|
|
|
|
static Sub_rm_connection vm_memory(genode_env(), vm_size);
|
|
|
|
return vm_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* VCPU handling
|
|
|
|
*/
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
static Genode::List<Vcpu_handler> &vcpu_handler_list()
|
|
|
|
{
|
|
|
|
static Genode::List<Vcpu_handler> _inst;
|
|
|
|
return _inst;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Vcpu_handler *lookup_vcpu_handler(unsigned int cpu_id)
|
|
|
|
{
|
|
|
|
for (Vcpu_handler *vcpu_handler = vcpu_handler_list().first();
|
|
|
|
vcpu_handler;
|
|
|
|
vcpu_handler = vcpu_handler->next())
|
|
|
|
if (vcpu_handler->cpu_id() == cpu_id)
|
|
|
|
return vcpu_handler;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
HRESULT genode_setup_machine(ComObjPtr<Machine> machine)
|
|
|
|
{
|
|
|
|
ULONG memory_vbox;
|
|
|
|
HRESULT rc = machine->COMGETTER(MemorySize)(&memory_vbox);
|
|
|
|
if (FAILED(rc))
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Extra memory because of:
|
|
|
|
* - first chunkid (0) can't be used (VBox don't like chunkid 0)
|
|
|
|
* - second chunkid (1..2) is reserved for handy pages allocation
|
|
|
|
* - another chunkid is used additional for handy pages but as large page
|
|
|
|
*/
|
|
|
|
vm_memory(memory_vbox * 1024 * 1024 + (CHUNKID_START + 1) * GMM_CHUNK_SIZE);
|
|
|
|
return genode_check_memory_config(machine);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
/* Genode specific function */
|
|
|
|
|
2017-01-05 13:45:37 +01:00
|
|
|
Nova::Hip &hip_rom()
|
|
|
|
{
|
|
|
|
static Genode::Attached_rom_dataspace hip_rom(genode_env(),
|
|
|
|
"hypervisor_info_page");
|
|
|
|
return *hip_rom.local_addr<Nova::Hip>();
|
|
|
|
}
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
void SUPR3QueryHWACCLonGenodeSupport(VM * pVM)
|
|
|
|
{
|
|
|
|
try {
|
2017-01-05 13:45:37 +01:00
|
|
|
pVM->hm.s.svm.fSupported = hip_rom().has_feature_svm();
|
|
|
|
pVM->hm.s.vmx.fSupported = hip_rom().has_feature_vmx();
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-01-05 13:45:37 +01:00
|
|
|
if (hip_rom().has_feature_svm() || hip_rom().has_feature_vmx()) {
|
|
|
|
Genode::log("Using ", hip_rom().has_feature_svm() ? "SVM" : "VMX",
|
|
|
|
" virtualization extension.");
|
2016-08-15 12:27:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (...) { /* if we get an exception let hardware support off */ }
|
|
|
|
|
|
|
|
Genode::warning("No virtualization hardware acceleration available");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* VirtualBox SUPLib interface */
|
|
|
|
int SUPR3QueryVTxSupported(void) { return VINF_SUCCESS; }
|
|
|
|
|
|
|
|
|
|
|
|
int SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
|
|
|
|
{
|
|
|
|
switch (uOperation) {
|
|
|
|
case SUP_VMMR0_DO_HM_RUN:
|
|
|
|
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
|
|
|
|
Assert(vcpu_handler);
|
|
|
|
return vcpu_handler->run_hw(pVMR0);
|
|
|
|
}
|
|
|
|
return VERR_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
|
2016-09-15 14:40:37 +02:00
|
|
|
int SUPR3PageAllocEx(::size_t cPages, uint32_t fFlags, void **ppvPages,
|
2016-08-15 12:27:54 +02:00
|
|
|
PRTR0PTR pR0Ptr, PSUPPAGE paPages)
|
|
|
|
{
|
|
|
|
Assert(ppvPages);
|
|
|
|
Assert(!fFlags);
|
|
|
|
|
|
|
|
Genode::log(__func__, " cPages ", cPages, " flags=", Genode::Hex(fFlags),
|
|
|
|
" r3=", ppvPages, " r0=", pR0Ptr);
|
|
|
|
|
|
|
|
using Genode::Attached_ram_dataspace;
|
2017-01-05 13:45:37 +01:00
|
|
|
Attached_ram_dataspace * ds = new Attached_ram_dataspace(genode_env().ram(),
|
|
|
|
genode_env().rm(),
|
2017-02-09 16:13:21 +01:00
|
|
|
cPages * ONE_PAGE_SIZE);
|
2016-08-15 12:27:54 +02:00
|
|
|
*ppvPages = ds->local_addr<void>();
|
2016-08-17 12:07:19 +02:00
|
|
|
if (pR0Ptr)
|
|
|
|
*pR0Ptr = reinterpret_cast<RTR0PTR>(*ppvPages);
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
Genode::log(__func__, " cPages ", cPages, " alloc=", *ppvPages, " done");
|
|
|
|
|
|
|
|
if (!paPages)
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
for (unsigned iPage = 0; iPage < cPages; iPage++)
|
|
|
|
{
|
|
|
|
paPages[iPage].uReserved = 0;
|
2017-02-09 16:13:21 +01:00
|
|
|
paPages[iPage].Phys = reinterpret_cast<RTHCPHYS>(ds->local_addr<void>()) + iPage * ONE_PAGE_SIZE;
|
2016-08-15 12:27:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
enum { MAX_TRACKING = 4 };
|
|
|
|
static struct {
|
|
|
|
Free_ids free;
|
|
|
|
unsigned freed;
|
|
|
|
unsigned chunkid;
|
|
|
|
} track_free[MAX_TRACKING];
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
static void partial_free_large_page(unsigned chunkid, unsigned page_id)
|
2016-08-15 12:27:54 +02:00
|
|
|
{
|
2017-02-09 16:13:21 +01:00
|
|
|
unsigned pos = 0;
|
|
|
|
|
|
|
|
/* lookup if already exist */
|
|
|
|
for (; pos < MAX_TRACKING; pos++)
|
|
|
|
{
|
|
|
|
if (track_free[pos].chunkid == chunkid)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if not exist find free place */
|
|
|
|
if (pos >= MAX_TRACKING) {
|
|
|
|
for (int i = 0; i < MAX_TRACKING; i++) {
|
|
|
|
if (track_free[i].chunkid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
track_free[i].chunkid = chunkid;
|
|
|
|
track_free[i].freed = 0;
|
|
|
|
pos = i;
|
|
|
|
break;
|
|
|
|
}
|
2017-01-05 13:45:37 +01:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
/* too many chunkids in use ? */
|
|
|
|
Assert (pos < MAX_TRACKING);
|
|
|
|
if (pos >= MAX_TRACKING)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
/* mark as in use */
|
|
|
|
track_free[pos].free.set(page_id, 1);
|
|
|
|
track_free[pos].freed += 1;
|
|
|
|
|
|
|
|
if (track_free[pos].freed >= 512) {
|
|
|
|
/* slow ? optimize ? XXX */
|
|
|
|
for (unsigned i = 0; i < 512; i++) {
|
|
|
|
if (!track_free[pos].free.get(i, 1))
|
|
|
|
throw 1;
|
|
|
|
track_free[pos].free.clear(i, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
track_free[pos].chunkid = 0;
|
|
|
|
track_free[pos].freed = 0;
|
|
|
|
|
|
|
|
chunk_ids.free(chunkid);
|
|
|
|
}
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error(__func__," ", __LINE__, " allocation failed ", pos, ":",
|
|
|
|
chunkid, ":", page_id);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
|
|
|
|
uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
|
|
|
|
{
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
switch (uOperation) {
|
|
|
|
|
|
|
|
case VMMR0_DO_GVMM_CREATE_VM:
|
|
|
|
genode_VMMR0_DO_GVMM_CREATE_VM(pReqHdr);
|
2017-02-09 16:13:21 +01:00
|
|
|
|
|
|
|
/* reserve lower chunk ids */
|
|
|
|
try {
|
|
|
|
for (unsigned i = 0; i < CHUNKID_START; i++) {
|
|
|
|
unsigned chunkid = chunk_ids.alloc();
|
|
|
|
AssertMsg(chunkid == i, ("chunkid %u != %u i\n", chunkid, i));
|
|
|
|
}
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error(__func__," ", __LINE__, " allocation failed");
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
case VMMR0_DO_GVMM_REGISTER_VMCPU:
|
|
|
|
genode_VMMR0_DO_GVMM_REGISTER_VMCPU(pVMR0, idCpu);
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
case VMMR0_DO_GVMM_SCHED_HALT:
|
|
|
|
{
|
2016-09-21 11:56:59 +02:00
|
|
|
const uint64_t u64NowGip = RTTimeNanoTS();
|
|
|
|
const uint64_t ns_diff = u64Arg > u64NowGip ? u64Arg - u64NowGip : 0;
|
|
|
|
|
|
|
|
if (!ns_diff)
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
uint64_t const tsc_offset = genode_cpu_hz() * ns_diff / (1000*1000*1000);
|
|
|
|
uint64_t const tsc_abs = Genode::Trace::timestamp() + tsc_offset;
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
if (ns_diff > RT_NS_1SEC)
|
|
|
|
warning(" more than 1 sec vcpu halt ", ns_diff, " ns");
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
|
|
|
|
Assert(vcpu_handler);
|
2016-09-21 11:56:59 +02:00
|
|
|
vcpu_handler->halt(tsc_abs);
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VMMR0_DO_GVMM_SCHED_WAKE_UP:
|
|
|
|
{
|
|
|
|
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
|
|
|
|
Assert(vcpu_handler);
|
2016-09-21 11:56:59 +02:00
|
|
|
|
|
|
|
/* don't wake the currently running thread again */
|
|
|
|
if (vcpu_handler->utcb() == Genode::Thread::myself()->utcb())
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
vcpu_handler->wake_up();
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* called by 'vmR3HaltGlobal1Halt' */
|
|
|
|
case VMMR0_DO_GVMM_SCHED_POLL:
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
case VMMR0_DO_VMMR0_INIT:
|
|
|
|
SUPR3QueryHWACCLonGenodeSupport(reinterpret_cast<VM *>(pVMR0));
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
case VMMR0_DO_GVMM_DESTROY_VM:
|
|
|
|
case VMMR0_DO_VMMR0_TERM:
|
|
|
|
case VMMR0_DO_HM_SETUP_VM:
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
case VMMR0_DO_HM_ENABLE:
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
|
|
|
|
case VMMR0_DO_GVMM_SCHED_POKE:
|
|
|
|
{
|
|
|
|
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
|
|
|
|
Assert(vcpu_handler);
|
|
|
|
if (vcpu_handler)
|
2017-03-10 14:37:15 +01:00
|
|
|
vcpu_handler->recall(vcpu_handler_list().first());
|
2016-08-15 12:27:54 +02:00
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_GMM_ALLOCATE_PAGES:
|
|
|
|
{
|
2017-02-09 16:13:21 +01:00
|
|
|
/*
|
|
|
|
* VMM is asking for some host virtual memory pages without
|
|
|
|
* allocating the backing store actually. The backing store allocation
|
|
|
|
* takes place via VMMR0_DO_GMM_MAP_UNMAP_CHUNK. The assignment of the
|
|
|
|
* guest addresses is known at this point.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static_assert(PGM_HANDY_PAGES * ONE_PAGE_SIZE == GMM_CHUNK_SIZE,
|
|
|
|
"Don't do that - you're going to waste tons of memory");
|
2016-08-15 12:27:54 +02:00
|
|
|
Assert(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC);
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
/* XXX VMM/VMMR0/GMMR0.cpp check there XXX */
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
PGMMALLOCATEPAGESREQ req = reinterpret_cast<PGMMALLOCATEPAGESREQ>(pReqHdr);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < req->cPages; i++) {
|
|
|
|
RTHCPHYS guest_addr = req->aPages[i].HCPhysGCPhys;
|
2017-02-09 16:13:21 +01:00
|
|
|
unsigned long page_idx = 0;
|
|
|
|
unsigned long chunk_id = 0;
|
|
|
|
|
|
|
|
try {
|
|
|
|
page_idx = page_ids.alloc();
|
|
|
|
chunk_id = CHUNKID_PAGE_START + page_idx / PAGES_SUPERPAGE;
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error(__func__," ", __LINE__, " allocation failed");
|
|
|
|
throw;
|
|
|
|
}
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
Assert (page_idx <= GMM_PAGEID_IDX_MASK);
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
req->aPages[i].idPage = (chunk_id << GMM_CHUNKID_SHIFT) | page_idx;
|
|
|
|
req->aPages[i].HCPhysGCPhys = vm_memory().local_addr((chunk_id * GMM_CHUNK_SIZE) | (page_idx * ONE_PAGE_SIZE));
|
|
|
|
Assert(vm_memory().contains(req->aPages[i].HCPhysGCPhys));
|
|
|
|
|
|
|
|
#if 0
|
2016-08-15 12:27:54 +02:00
|
|
|
Genode::log("cPages ", Genode::Hex(req->cPages), " "
|
|
|
|
"chunkID=", req->aPages[i].idPage >> GMM_CHUNKID_SHIFT, " "
|
|
|
|
"pageIDX=", req->aPages[i].idPage & GMM_PAGEID_IDX_MASK, " "
|
|
|
|
"idPage=", Genode::Hex(req->aPages[i].idPage), " "
|
|
|
|
"GCPhys=", Genode::Hex(guest_addr), " "
|
|
|
|
"HCPhys=", Genode::Hex(req->aPages[i].HCPhysGCPhys), " "
|
2017-02-09 16:13:21 +01:00
|
|
|
"(", Genode::Hex(chunk_id * GMM_CHUNK_SIZE), " "
|
|
|
|
"| ", Genode::Hex(page_idx * ONE_PAGE_SIZE), ") pageidx=", page_idx, " "
|
|
|
|
"start_vm=", vm_memory().local_addr(0));
|
|
|
|
#endif
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_GMM_MAP_UNMAP_CHUNK:
|
|
|
|
{
|
|
|
|
PGMMMAPUNMAPCHUNKREQ req = reinterpret_cast<PGMMMAPUNMAPCHUNKREQ>(pReqHdr);
|
|
|
|
|
|
|
|
Assert(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC);
|
|
|
|
Assert(req->idChunkUnmap == NIL_GMM_CHUNKID);
|
|
|
|
Assert(req->idChunkMap != NIL_GMM_CHUNKID);
|
|
|
|
|
2017-01-05 13:45:37 +01:00
|
|
|
Genode::Ram_dataspace_capability ds = genode_env().ram().alloc(GMM_CHUNK_SIZE);
|
2017-02-09 16:13:21 +01:00
|
|
|
Genode::addr_t local_addr_offset = req->idChunkMap << GMM_CHUNK_SHIFT;
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
enum { OFFSET_DS = 0, USE_LOCAL_ADDR = true };
|
2017-02-09 16:13:21 +01:00
|
|
|
Genode::addr_t to = vm_memory().attach(ds, GMM_CHUNK_SIZE, OFFSET_DS,
|
|
|
|
USE_LOCAL_ADDR, local_addr_offset);
|
|
|
|
Assert(to == vm_memory().local_addr(local_addr_offset));
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
req->pvR3 = reinterpret_cast<RTR3PTR>(to);
|
|
|
|
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_GMM_QUERY_MEM_STATS:
|
|
|
|
{
|
|
|
|
PGMMMEMSTATSREQ req = reinterpret_cast<PGMMMEMSTATSREQ>(pReqHdr);
|
|
|
|
req->cAllocPages = 0;
|
|
|
|
req->cMaxPages = 0;
|
|
|
|
req->cBalloonedPages = 0;
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES:
|
|
|
|
{
|
2017-02-09 16:13:21 +01:00
|
|
|
/*
|
|
|
|
* VMM is asking for some host virtual memory pages without
|
|
|
|
* allocating the backing store actually. The backing store allocation
|
|
|
|
* takes place via VMMR0_DO_GMM_MAP_UNMAP_CHUNK. The assignment of the
|
|
|
|
* guest addresses to these host pages is unknown at this point.
|
|
|
|
*/
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
PVM pVM = reinterpret_cast<PVM>(pVMR0);
|
|
|
|
|
|
|
|
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - start */
|
|
|
|
uint32_t iFirst = pVM->pgm.s.cHandyPages;
|
|
|
|
uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst;
|
|
|
|
uint32_t cPagesToUpdate = cPages;
|
|
|
|
uint32_t cPagesToAlloc = cPages;
|
|
|
|
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - end */
|
|
|
|
|
|
|
|
/* based on GMMR0AllocateHandyPages in VMM/VMMR0/GMMR0.cpp - start */
|
|
|
|
unsigned iPage = 0;
|
|
|
|
for (; iPage < cPagesToUpdate; iPage++)
|
|
|
|
{
|
|
|
|
AssertMsgReturn( ( pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys <= GMM_GCPHYS_LAST
|
|
|
|
&& !(pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys & PAGE_OFFSET_MASK))
|
|
|
|
|| pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == NIL_RTHCPHYS
|
|
|
|
|| pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == GMM_GCPHYS_UNSHAREABLE,
|
|
|
|
("#%#x: %RHp\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys),
|
|
|
|
VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn( pVM->pgm.s.aHandyPages[iFirst + iPage].idPage <= GMM_PAGEID_LAST
|
|
|
|
/*|| pVM->pgm.s.aHandyPages[iFirst + iPage].idPage == NIL_GMM_PAGEID*/,
|
|
|
|
("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idPage), VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn( pVM->pgm.s.aHandyPages[iFirst + iPage].idPage <= GMM_PAGEID_LAST
|
|
|
|
/*|| pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage == NIL_GMM_PAGEID*/,
|
|
|
|
("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage), VERR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; iPage < cPagesToAlloc; iPage++)
|
|
|
|
{
|
|
|
|
AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == NIL_RTHCPHYS, ("#%#x: %RHp\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys), VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].idPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idPage), VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage), VERR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
unsigned chunkid = 0;
|
|
|
|
|
|
|
|
try {
|
|
|
|
chunkid = chunk_ids.alloc();
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error(__func__," ", __LINE__, " allocation failed");
|
|
|
|
throw;
|
|
|
|
}
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
if (cPagesToAlloc != GMM_CHUNK_SIZE / ONE_PAGE_SIZE)
|
|
|
|
Vmm::log("special chunkid=", chunkid, " "
|
|
|
|
"toupdate=", cPagesToUpdate, " "
|
|
|
|
"toalloc=", cPagesToAlloc, " "
|
|
|
|
"virt=", Genode::Hex(vm_memory().local_addr(chunkid << GMM_CHUNK_SHIFT)));
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < cPagesToUpdate; i++) {
|
|
|
|
if (pVM->pgm.s.aHandyPages[iFirst + i].idPage != NIL_GMM_PAGEID)
|
|
|
|
{
|
|
|
|
pVM->pgm.s.aHandyPages[iFirst + i].idPage = NIL_GMM_PAGEID;
|
|
|
|
pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys = NIL_RTHCPHYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage != NIL_GMM_PAGEID)
|
|
|
|
AssertMsgReturn(false, ("%s %u - not implemented", __func__, __LINE__), VERR_GENERAL_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < cPagesToAlloc; i++)
|
|
|
|
{
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys == NIL_RTHCPHYS);
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[iFirst + i].idPage == NIL_GMM_PAGEID);
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage == NIL_GMM_PAGEID);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < cPagesToUpdate; i++) {
|
|
|
|
unsigned reverse = i; //cPagesToUpdate - 1 - i;
|
|
|
|
Assert (pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys == NIL_RTHCPHYS);
|
|
|
|
{
|
|
|
|
pVM->pgm.s.aHandyPages[iFirst + i].idPage = (chunkid << GMM_CHUNKID_SHIFT) | (iFirst + reverse);
|
|
|
|
pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage = NIL_GMM_PAGEID;
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys = vm_memory().local_addr((chunkid << GMM_CHUNK_SHIFT) | ((iFirst + reverse) * ONE_PAGE_SIZE));
|
2016-08-15 12:27:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* based on GMMR0AllocateHandyPages in VMM/VMMR0/GMMR0.cpp - end */
|
|
|
|
|
|
|
|
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - start */
|
|
|
|
pVM->pgm.s.cHandyPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
|
|
|
|
{
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
|
|
|
|
Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
|
|
|
|
Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
|
|
|
|
}
|
|
|
|
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - end */
|
|
|
|
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_PGM_ALLOCATE_LARGE_HANDY_PAGE:
|
|
|
|
{
|
2017-02-09 16:13:21 +01:00
|
|
|
/*
|
|
|
|
* VMM is asking for some host large virtual memory pages without
|
|
|
|
* allocating the backing store actually. The backing store allocation
|
|
|
|
* takes place via VMMR0_DO_GMM_MAP_UNMAP_CHUNK. The assignment of the
|
|
|
|
* guest addresses to these host pages is unknown at this point.
|
|
|
|
*/
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
PVM pVM = reinterpret_cast<PVM>(pVMR0);
|
|
|
|
|
|
|
|
Assert(pVM);
|
|
|
|
Assert(pVM->pgm.s.cLargeHandyPages == 0);
|
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
try {
|
|
|
|
unsigned chunkid = chunk_ids.alloc();
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
pVM->pgm.s.aLargeHandyPage[0].idPage = (chunkid << GMM_CHUNKID_SHIFT);
|
|
|
|
pVM->pgm.s.aLargeHandyPage[0].HCPhysGCPhys = vm_memory().local_addr(chunkid << GMM_CHUNK_SHIFT);
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
pVM->pgm.s.cLargeHandyPages = 1;
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error(__func__," ", __LINE__, " allocation failed");
|
|
|
|
throw;
|
|
|
|
}
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_GMM_BALLOONED_PAGES:
|
|
|
|
case VMMR0_DO_GMM_RESET_SHARED_MODULES:
|
|
|
|
case VMMR0_DO_PGM_FLUSH_HANDY_PAGES:
|
|
|
|
{
|
2017-02-09 16:13:21 +01:00
|
|
|
PVM const pVM = reinterpret_cast<PVM>(pVMR0);
|
|
|
|
PVMCPU const pVCpu = &pVM->aCpus[idCpu];
|
|
|
|
|
|
|
|
/* if not in VM shutdown - complain - bug ahead */
|
|
|
|
if (pVCpu->em.s.enmState != EMSTATE_TERMINATING)
|
|
|
|
Genode::error("unexpected call of type ", uOperation, ", "
|
|
|
|
"em state=", (int)pVCpu->em.s.enmState);
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
|
|
|
case VMMR0_DO_GMM_FREE_PAGES:
|
|
|
|
{
|
|
|
|
if (u64Arg)
|
|
|
|
return VERR_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
PVM pVM = reinterpret_cast<PVM>(pVMR0);
|
|
|
|
PGMMFREEPAGESREQ pReq = reinterpret_cast<PGMMFREEPAGESREQ>(pReqHdr);
|
|
|
|
|
|
|
|
AssertPtrReturn(pVM, VERR_INVALID_POINTER);
|
|
|
|
AssertPtrReturn(pReq, VERR_INVALID_POINTER);
|
|
|
|
AssertMsgReturn(pReq->Hdr.cbReq >= RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[0]),
|
|
|
|
("%#x < %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[0])),
|
|
|
|
VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn(pReq->Hdr.cbReq == RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[pReq->cPages]),
|
|
|
|
("%#x != %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[pReq->cPages])),
|
|
|
|
VERR_INVALID_PARAMETER);
|
|
|
|
|
|
|
|
uint32_t cPages = pReq->cPages;
|
|
|
|
PGMMFREEPAGEDESC paPages = &pReq->aPages[0];
|
|
|
|
GMMACCOUNT enmAccount = pReq->enmAccount;
|
|
|
|
|
|
|
|
AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn(enmAccount > GMMACCOUNT_INVALID && enmAccount < GMMACCOUNT_END, ("%d\n", enmAccount), VERR_INVALID_PARAMETER);
|
|
|
|
AssertMsgReturn(cPages > 0 && cPages < RT_BIT(32 - PAGE_SHIFT), ("%#x\n", cPages), VERR_INVALID_PARAMETER);
|
|
|
|
|
|
|
|
for (unsigned iPage = 0; iPage < cPages; iPage++)
|
|
|
|
AssertMsgReturn( paPages[iPage].idPage <= GMM_PAGEID_LAST
|
|
|
|
/*|| paPages[iPage].idPage == NIL_GMM_PAGEID*/,
|
|
|
|
("#%#x: %#x\n", iPage, paPages[iPage].idPage), VERR_INVALID_PARAMETER);
|
|
|
|
|
2017-04-26 15:15:29 +02:00
|
|
|
for (uint32_t last_chunk = ~0U, iPage = 0; iPage < cPages; iPage++)
|
2016-08-15 12:27:54 +02:00
|
|
|
{
|
2017-02-09 16:13:21 +01:00
|
|
|
uint32_t const idPage = paPages[iPage].idPage;
|
|
|
|
uint32_t const page_idx = idPage & GMM_PAGEID_IDX_MASK;
|
|
|
|
uint32_t const chunkid = idPage >> GMM_CHUNKID_SHIFT;
|
|
|
|
|
2017-04-26 15:15:29 +02:00
|
|
|
if (last_chunk != chunkid) {
|
|
|
|
/* revoke mapping from guest VM */
|
|
|
|
void * vmm_local = reinterpret_cast<void *>(vm_memory().local_addr(chunkid << GMM_CHUNK_SHIFT));
|
|
|
|
PGMUnmapMemoryGenode(vmm_local, GMM_CHUNK_SIZE);
|
|
|
|
|
|
|
|
last_chunk = chunkid;
|
2017-02-09 16:13:21 +01:00
|
|
|
}
|
2017-04-26 15:15:29 +02:00
|
|
|
|
2017-02-09 16:13:21 +01:00
|
|
|
if (CHUNKID_PAGE_START <= chunkid && chunkid <= CHUNKID_PAGE_END) {
|
|
|
|
try {
|
|
|
|
page_ids.free((chunkid - CHUNKID_PAGE_START) * PAGES_SUPERPAGE + page_idx);
|
|
|
|
} catch (...) {
|
|
|
|
Genode::error(__func__," ", __LINE__, " clearing failed");
|
|
|
|
throw;
|
|
|
|
}
|
2016-08-15 12:27:54 +02:00
|
|
|
}
|
2017-02-09 16:13:21 +01:00
|
|
|
|
|
|
|
partial_free_large_page(chunkid, page_idx);
|
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
paPages[iPage].idPage = NIL_GMM_PAGEID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
}
|
2017-03-10 14:37:15 +01:00
|
|
|
case VMMR0_DO_GMM_INITIAL_RESERVATION:
|
|
|
|
Genode::log("VMMR0_DO_GMM_INITIAL_RESERVATION called");
|
|
|
|
return VINF_SUCCESS;
|
|
|
|
case VMMR0_DO_GMM_UPDATE_RESERVATION:
|
|
|
|
Genode::log("VMMR0_DO_GMM_UPDATE_RESERVATION called");
|
|
|
|
return VINF_SUCCESS;
|
2016-08-15 12:27:54 +02:00
|
|
|
default:
|
|
|
|
Genode::error("SUPR3CallVMMR0Ex: unhandled uOperation ", uOperation,
|
|
|
|
" ", (int)VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES, " ",
|
|
|
|
(int)VMMR0_DO_GMM_QUERY_MEM_STATS);
|
|
|
|
return VERR_GENERAL_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Various support stuff - base-nova specific.
|
|
|
|
*/
|
|
|
|
uint64_t genode_cpu_hz()
|
|
|
|
{
|
|
|
|
static uint64_t cpu_freq = 0;
|
|
|
|
|
|
|
|
if (!cpu_freq) {
|
|
|
|
try {
|
2017-01-05 13:45:37 +01:00
|
|
|
cpu_freq = hip_rom().tsc_freq * 1000;
|
2016-08-15 12:27:54 +02:00
|
|
|
} catch (...) {
|
2017-01-05 13:45:37 +01:00
|
|
|
Genode::error("could not read out CPU frequency");
|
2016-08-15 12:27:54 +02:00
|
|
|
Genode::Lock lock;
|
|
|
|
lock.lock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cpu_freq;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void genode_update_tsc(void (*update_func)(void), unsigned long update_us)
|
|
|
|
{
|
|
|
|
using namespace Genode;
|
|
|
|
using namespace Nova;
|
|
|
|
|
|
|
|
enum { TSC_FACTOR = 1000ULL };
|
|
|
|
|
|
|
|
Genode::addr_t sem = Thread::myself()->native_thread().exc_pt_sel + Nova::SM_SEL_EC;
|
|
|
|
unsigned long tsc_khz = (genode_cpu_hz() / 1000) / TSC_FACTOR;
|
|
|
|
|
|
|
|
Trace::Timestamp us_64 = update_us;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
update_func();
|
|
|
|
|
|
|
|
Trace::Timestamp now = Trace::timestamp();
|
|
|
|
|
|
|
|
/* block until timeout fires or it gets canceled */
|
|
|
|
unsigned long long tsc_absolute = now + us_64 * tsc_khz;
|
|
|
|
Genode::uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, tsc_absolute);
|
|
|
|
if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT)
|
|
|
|
nova_die();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 14:40:37 +02:00
|
|
|
bool PGMUnmapMemoryGenode(void * vmm_local, ::size_t size)
|
2016-08-15 12:27:54 +02:00
|
|
|
{
|
|
|
|
Assert(vmm_local);
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
Flexpage_iterator fli(reinterpret_cast<addr_t>(vmm_local), size, 0, ~0UL, 0);
|
|
|
|
|
|
|
|
Flexpage revoke_page = fli.page();
|
|
|
|
while (revoke_page.valid()) {
|
|
|
|
Assert(revoke_page.log2_order >= 12);
|
|
|
|
Assert(!(((1UL << revoke_page.log2_order) - 1) & revoke_page.addr));
|
|
|
|
|
|
|
|
using namespace Nova;
|
|
|
|
|
|
|
|
Rights const revoke_rwx(true, true, true);
|
|
|
|
Crd crd = Mem_crd(revoke_page.addr >> 12, revoke_page.log2_order - 12,
|
|
|
|
revoke_rwx);
|
|
|
|
revoke(crd, false);
|
|
|
|
|
|
|
|
/* request next page(s) to be revoked */
|
|
|
|
revoke_page = fli.page();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" void pthread_yield(void)
|
|
|
|
{
|
|
|
|
Nova::ec_ctrl(Nova::EC_YIELD);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 14:40:37 +02:00
|
|
|
void *operator new (__SIZE_TYPE__ size, int log2_align)
|
2016-08-15 12:27:54 +02:00
|
|
|
{
|
2017-01-31 16:01:07 +01:00
|
|
|
static Libc::Mem_alloc_impl heap(genode_env().rm(), genode_env().ram());
|
2016-08-15 12:27:54 +02:00
|
|
|
return heap.alloc(size, log2_align);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 14:40:37 +02:00
|
|
|
bool create_emt_vcpu(pthread_t * pthread, ::size_t stack,
|
2016-08-15 12:27:54 +02:00
|
|
|
const pthread_attr_t *attr,
|
|
|
|
void *(*start_routine)(void *), void *arg,
|
|
|
|
Genode::Cpu_session * cpu_session,
|
|
|
|
Genode::Affinity::Location location,
|
2016-09-23 10:10:01 +02:00
|
|
|
unsigned int cpu_id, const char * name)
|
2016-08-15 12:27:54 +02:00
|
|
|
{
|
2017-01-05 13:45:37 +01:00
|
|
|
if (!hip_rom().has_feature_vmx() && !hip_rom().has_feature_svm())
|
2016-08-15 12:27:54 +02:00
|
|
|
return false;
|
|
|
|
|
2017-01-05 13:45:37 +01:00
|
|
|
static Genode::Pd_connection pd_vcpus(genode_env(), "VM");
|
2016-11-24 21:57:33 +01:00
|
|
|
|
2016-08-15 12:27:54 +02:00
|
|
|
Vcpu_handler *vcpu_handler = 0;
|
|
|
|
|
2017-01-05 13:45:37 +01:00
|
|
|
if (hip_rom().has_feature_vmx())
|
2016-11-23 17:07:49 +01:00
|
|
|
vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(),
|
|
|
|
stack, attr, start_routine,
|
2016-08-15 12:27:54 +02:00
|
|
|
arg, cpu_session, location,
|
2016-11-24 21:57:33 +01:00
|
|
|
cpu_id, name, pd_vcpus);
|
2016-08-15 12:27:54 +02:00
|
|
|
|
2017-01-05 13:45:37 +01:00
|
|
|
if (hip_rom().has_feature_svm())
|
2016-11-23 17:07:49 +01:00
|
|
|
vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(),
|
|
|
|
stack, attr, start_routine,
|
2016-08-15 12:27:54 +02:00
|
|
|
arg, cpu_session, location,
|
2016-11-24 21:57:33 +01:00
|
|
|
cpu_id, name, pd_vcpus);
|
2016-08-15 12:27:54 +02:00
|
|
|
|
|
|
|
Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf));
|
|
|
|
|
|
|
|
vcpu_handler_list().insert(vcpu_handler);
|
|
|
|
|
|
|
|
*pthread = vcpu_handler;
|
|
|
|
return true;
|
|
|
|
}
|