vbox: support resetting of a VM

Fixes #1290
This commit is contained in:
Alexander Boettcher 2014-11-11 16:57:01 +01:00 committed by Christian Helmuth
parent cb51d67c8d
commit 3babee4e19
9 changed files with 390 additions and 277 deletions

View File

@ -1 +1 @@
64bd2d2de0305c36048e46c05af5bc6578533ed3 cc82990bfeded59df2befde90f20004f2a5a331d

View File

@ -100,7 +100,7 @@ uint64_t genode_cpu_hz() {
} }
bool Vmm_memory::unmap_from_vm(RTGCPHYS GCPhys) bool Vmm_memory::revoke_from_vm(Region *r)
{ {
PWRN("%s unimplemented", __func__); PWRN("%s unimplemented", __func__);
return false; return false;

View File

@ -14,48 +14,48 @@
#include <base/printf.h> #include <base/printf.h>
#include <base/thread.h> #include <base/thread.h>
#include <iprt/types.h>
#include <stddef.h> #include <stddef.h>
#include <time.h> #include <time.h>
extern "C" { extern "C" {
typedef long DUMMY;
#define DUMMY(retval, name) \ #define DUMMY(retval, name) \
DUMMY name(void) { \ int name(void) { \
PDBG( #name " called, not implemented, eip=%p", __builtin_return_address(0)); \ PDBG( #name " called, not implemented, eip=%p", __builtin_return_address(0)); \
for (;;); \ for (;;); \
return retval; \ return retval; \
} }
#define CHECKED_DUMMY(retval, name) \ #define CHECKED_DUMMY(TYPE, retval, name) \
DUMMY name(void) { \ TYPE name(void) { \
PINF( #name " called, not implemented, eip=%p", __builtin_return_address(0)); \ PINF( #name " called, not implemented, eip=%p", __builtin_return_address(0)); \
return retval; \ return retval; \
} }
CHECKED_DUMMY( 0, cpumR3DbgInit) CHECKED_DUMMY(int, 0, cpumR3DbgInit)
CHECKED_DUMMY( 0, DBGFR3Init) /* debugger */ CHECKED_DUMMY(int, 0, DBGFR3Init) /* debugger */
DUMMY(-1, DBGFR3CoreWrite) DUMMY(-1, DBGFR3CoreWrite)
CHECKED_DUMMY( 0, FTMR3Init) /* fault tolerance manager */ CHECKED_DUMMY(int, 0, FTMR3Init) /* fault tolerance manager */
CHECKED_DUMMY( 0, pdmR3LdrInitU) /* module loader of pluggable device manager */ CHECKED_DUMMY(int, 0, pdmR3LdrInitU) /* module loader of pluggable device manager */
CHECKED_DUMMY( 0, PDMR3LdrLoadVMMR0U) /* pretend to have successfully loaded the r0 module */ CHECKED_DUMMY(int, 0, PDMR3LdrLoadVMMR0U) /* pretend to have successfully loaded the r0 module */
CHECKED_DUMMY( 0, pdmR3LoadR3U) CHECKED_DUMMY(int, 0, pdmR3LoadR3U)
CHECKED_DUMMY( 0, pthread_atfork) CHECKED_DUMMY(int, 0, pthread_atfork)
CHECKED_DUMMY( 0, pthread_attr_setdetachstate) CHECKED_DUMMY(int, 0, pthread_attr_setdetachstate)
CHECKED_DUMMY( 0, pthread_attr_setstacksize) CHECKED_DUMMY(int, 0, pthread_attr_setstacksize)
CHECKED_DUMMY( 0, RTMemProtect) CHECKED_DUMMY(int, 0, RTMemProtect)
CHECKED_DUMMY( 0, SELMR3Init) /* selector manager - GDT handling */ CHECKED_DUMMY(int, 0, SELMR3Init) /* selector manager - GDT handling */
CHECKED_DUMMY( 0, sigfillset) CHECKED_DUMMY(int, 0, sigfillset)
CHECKED_DUMMY( 0, vmmR3SwitcherInit) /* world switcher */ CHECKED_DUMMY(int, 0, vmmR3SwitcherInit) /* world switcher */
CHECKED_DUMMY(-1, atexit) CHECKED_DUMMY(int, -1, atexit)
CHECKED_DUMMY(-1, getpid) CHECKED_DUMMY(pid_t, -1, getpid)
CHECKED_DUMMY(-1, pdmR3FileR3) CHECKED_DUMMY(char *, (char *)-1, pdmR3FileR3)
CHECKED_DUMMY(0, setlocale) CHECKED_DUMMY(char *, nullptr, setlocale)
CHECKED_DUMMY(-1, sigaddset) CHECKED_DUMMY(int, -1, sigaddset)
CHECKED_DUMMY(-1, sigemptyset) CHECKED_DUMMY(int, -1, sigemptyset)
CHECKED_DUMMY(-1, siginterrupt) CHECKED_DUMMY(int, -1, siginterrupt)
CHECKED_DUMMY(-1, sysctl) CHECKED_DUMMY(int, -1, sysctl)
DUMMY( 0, RTErrCOMGet) DUMMY( 0, RTErrCOMGet)
void CPUMPushHyper() { } /* called by 'VMMR3InitRC', but we don't use GC */ void CPUMPushHyper() { } /* called by 'VMMR3InitRC', but we don't use GC */
DUMMY(-1, DBGCRegisterCommands) DUMMY(-1, DBGCRegisterCommands)
@ -63,12 +63,12 @@ DUMMY(-1, DBGFR3Event)
DUMMY(-1, DBGFR3EventAssertion) DUMMY(-1, DBGFR3EventAssertion)
DUMMY(-1, DBGFR3EventBreakpoint) DUMMY(-1, DBGFR3EventBreakpoint)
DUMMY(-1, DBGFR3EventSrc) DUMMY(-1, DBGFR3EventSrc)
CHECKED_DUMMY( 0, DBGFR3EventSrcV) CHECKED_DUMMY(int, 0, DBGFR3EventSrcV)
void DBGFR3Relocate() { } void DBGFR3Relocate() { }
DUMMY(-1, DBGFR3Term) DUMMY(-1, DBGFR3Term)
DUMMY(-1, DBGFR3VMMForcedAction) DUMMY(-1, DBGFR3VMMForcedAction)
CHECKED_DUMMY(-4, DBGFR3AsSymbolByAddr) /* -4 == VERR_INVALID_HANDLE */ CHECKED_DUMMY(int, -4, DBGFR3AsSymbolByAddr) /* -4 == VERR_INVALID_HANDLE */
DUMMY(-1, _flockfile) DUMMY(-1, _flockfile)
@ -85,12 +85,12 @@ DUMMY(-1, HWACCMR3PatchTprInstr)
DUMMY(-1, HWACCMR3CheckError) DUMMY(-1, HWACCMR3CheckError)
DUMMY(-1, HWACCMR3RestartPendingIOInstr) DUMMY(-1, HWACCMR3RestartPendingIOInstr)
void HWACCMR3Relocate() { } void HWACCMR3Relocate() { }
DUMMY(-1, HWACCMR3Reset) void HWACCMR3Reset() { }
DUMMY(-1, HWACCMR3Term) DUMMY(-1, HWACCMR3Term)
DUMMY(-1, HWACMMR3EnablePatching) DUMMY(-1, HWACMMR3EnablePatching)
DUMMY(-1, HWACMMR3DisablePatching) DUMMY(-1, HWACMMR3DisablePatching)
CHECKED_DUMMY( 0, IEMR3Init) /* interpreted execution manager (seems to be just a skeleton) */ CHECKED_DUMMY(int, 0, IEMR3Init) /* interpreted execution manager (seems to be just a skeleton) */
void IEMR3Relocate() { } void IEMR3Relocate() { }
DUMMY(-1, IEMR3Term) DUMMY(-1, IEMR3Term)
@ -98,17 +98,17 @@ DUMMY(-1, MMHyperR0ToCC)
DUMMY(-1, MMHyperR0ToR3) DUMMY(-1, MMHyperR0ToR3)
DUMMY(-1, MMHyperRCToCC) DUMMY(-1, MMHyperRCToCC)
DUMMY(-1, MMHyperRCToR3) DUMMY(-1, MMHyperRCToR3)
CHECKED_DUMMY(0, MMHyperGetArea) CHECKED_DUMMY(RTGCPTR, 0, MMHyperGetArea)
DUMMY(-1, MMR3HeapAPrintfV) DUMMY(-1, MMR3HeapAPrintfV)
CHECKED_DUMMY( 0, MMR3HyperInitFinalize) CHECKED_DUMMY(int, 0, MMR3HyperInitFinalize)
CHECKED_DUMMY( 0, MMR3HyperSetGuard) CHECKED_DUMMY(int, 0, MMR3HyperSetGuard)
DUMMY(-1, MMR3LockCall) DUMMY(-1, MMR3LockCall)
DUMMY(-1, MMR3Term) DUMMY(-1, MMR3Term)
DUMMY(-1, MMR3TermUVM) DUMMY(-1, MMR3TermUVM)
DUMMY(-1, PDMR3AsyncCompletionTemplateCreateDriver) DUMMY(-1, PDMR3AsyncCompletionTemplateCreateDriver)
DUMMY(-1, PDMR3LdrGetInterfaceSymbols) DUMMY(-1, PDMR3LdrGetInterfaceSymbols)
CHECKED_DUMMY( 0, PDMR3LdrRelocateU) void PDMR3LdrRelocateU() { }
DUMMY(-1, pdmR3LdrTermU) DUMMY(-1, pdmR3LdrTermU)
DUMMY(-1, PGMNotifyNxeChanged) DUMMY(-1, PGMNotifyNxeChanged)
@ -118,11 +118,11 @@ DUMMY(-1, PGMPhysSimpleReadGCPtr)
DUMMY(-1, PGMPhysSimpleWriteGCPtr) DUMMY(-1, PGMPhysSimpleWriteGCPtr)
DUMMY(-1, PGMSyncCR3) DUMMY(-1, PGMSyncCR3)
CHECKED_DUMMY( 0, PGMR3CheckIntegrity) CHECKED_DUMMY(int, 0, PGMR3CheckIntegrity)
CHECKED_DUMMY( 0, PGMR3FinalizeMappings) CHECKED_DUMMY(int, 0, PGMR3FinalizeMappings)
CHECKED_DUMMY( 0, PGMR3InitCompleted) CHECKED_DUMMY(int, 0, PGMR3InitCompleted)
CHECKED_DUMMY( 0, PGMR3InitDynMap) /* reserve space for "dynamic mappings" */ CHECKED_DUMMY(int, 0, PGMR3InitDynMap) /* reserve space for "dynamic mappings" */
CHECKED_DUMMY( 0, PGMR3InitFinalize) CHECKED_DUMMY(int, 0, PGMR3InitFinalize)
DUMMY(-1, PGMR3SharedModuleCheckAll) DUMMY(-1, PGMR3SharedModuleCheckAll)
DUMMY(-1, PGMR3SharedModuleUnregister) DUMMY(-1, PGMR3SharedModuleUnregister)
@ -130,7 +130,7 @@ DUMMY(-1, PGMR3SharedModuleRegister)
DUMMY(-1, PGMR3MappingsUnfix) DUMMY(-1, PGMR3MappingsUnfix)
DUMMY(-1, PGMR3PhysChangeMemBalloon) DUMMY(-1, PGMR3PhysChangeMemBalloon)
DUMMY(-1, PGMR3MappingsFix) DUMMY(-1, PGMR3MappingsFix)
CHECKED_DUMMY( 0, PGMR3MappingsDisable) DUMMY(-1, PGMR3MappingsDisable)
DUMMY(-1, PGMR3LockCall) DUMMY(-1, PGMR3LockCall)
DUMMY(-1, PGMR3PhysAllocateHandyPages) DUMMY(-1, PGMR3PhysAllocateHandyPages)
DUMMY(-1, PGMR3PhysAllocateLargeHandyPage) DUMMY(-1, PGMR3PhysAllocateLargeHandyPage)
@ -158,39 +158,39 @@ DUMMY(-1, PGMSetLargePageUsage)
DUMMY(-1, PGMPhysSimpleDirtyWriteGCPtr) DUMMY(-1, PGMPhysSimpleDirtyWriteGCPtr)
DUMMY(-1, PGMGetShadowMode) DUMMY(-1, PGMGetShadowMode)
DUMMY(-1, PGMGetHostMode) DUMMY(-1, PGMGetHostMode)
CHECKED_DUMMY(int, 0, PGMGetGuestMode) /* PGMMODE_INVALID == 0 */
int PGMChangeMode() { return 0; }
CHECKED_DUMMY(0, poll) /* needed by 'DrvHostSerial.cpp' */ CHECKED_DUMMY(int, 0, poll) /* needed by 'DrvHostSerial.cpp' */
DUMMY(-1, pthread_key_delete) DUMMY(-1, pthread_key_delete)
DUMMY(-1, RTMemExecFree) DUMMY(-1, RTMemExecFree)
DUMMY(-1, RTMemPageFree) DUMMY(-1, RTMemPageFree)
DUMMY(-1, RTPathAppend) DUMMY(-1, RTPathAppend)
DUMMY(-1, RTSemEventWaitEx) DUMMY(-1, RTSemEventWaitEx)
CHECKED_DUMMY( 0, SELMR3InitFinalize) CHECKED_DUMMY(int, 0, SELMR3InitFinalize)
void SELMR3Relocate() { } void SELMR3Relocate() { }
CHECKED_DUMMY( 0, SELMR3DisableMonitoring) void SELMR3DisableMonitoring () { }
DUMMY(-1, SELMR3Reset) void SELMR3Reset() { }
DUMMY(-1, SELMR3Term) DUMMY(-1, SELMR3Term)
DUMMY(-1, SELMR3GetSelectorInfo) DUMMY(-1, SELMR3GetSelectorInfo)
DUMMY(-1, libc_select_notify) /* needed for libc_terminal plugin */ DUMMY(-1, libc_select_notify) /* needed for libc_terminal plugin */
DUMMY(-1, DISInstrToStrEx) DUMMY(-1, DISInstrToStrEx)
CHECKED_DUMMY(-1, signal)
DUMMY(-1, strcat) DUMMY(-1, strcat)
DUMMY(-1, strerror) DUMMY(-1, strerror)
DUMMY(-1, strpbrk) DUMMY(-1, strpbrk)
CHECKED_DUMMY( 0, SUPR3SetVMForFastIOCtl) CHECKED_DUMMY(int, 0, SUPR3SetVMForFastIOCtl)
DUMMY(-1, SUPR3HardenedLdrLoadPlugIn) DUMMY(-1, SUPR3HardenedLdrLoadPlugIn)
DUMMY(-1, SUPR3Term) DUMMY(-1, SUPR3Term)
CHECKED_DUMMY(100000*10, SUPSemEventMultiGetResolution) /* called by 'vmR3HaltGlobal1Init' */ uint32_t SUPSemEventMultiGetResolution()
CHECKED_DUMMY(-1, __swsetup) { return 100000*10; /* called by 'vmR3HaltGlobal1Init' */ }
DUMMY(-1, VMMR3FatalDump) DUMMY(-1, VMMR3FatalDump)
void vmmR3SwitcherRelocate() { } void vmmR3SwitcherRelocate() { }
CHECKED_DUMMY( 0, VMMR3DisableSwitcher)
DUMMY(-1, VMMR3GetHostToGuestSwitcher) DUMMY(-1, VMMR3GetHostToGuestSwitcher)
DUMMY(-1, pthread_kill) DUMMY(-1, pthread_kill)
@ -202,7 +202,7 @@ DUMMY(-1, RTHeapSimpleFree)
DUMMY(-1, RTAvloU32Get) DUMMY(-1, RTAvloU32Get)
DUMMY(-1, RTAvloU32Remove) DUMMY(-1, RTAvloU32Remove)
DUMMY(-1, RTAvloU32GetBestFit) DUMMY(-1, RTAvloU32GetBestFit)
DUMMY( 0, RTAvloU32RemoveBestFit) CHECKED_DUMMY(void *, nullptr, RTAvloU32RemoveBestFit)
DUMMY(-1, RTAvlU32Destroy) DUMMY(-1, RTAvlU32Destroy)
DUMMY(-1, RTAvlU32GetBestFit) DUMMY(-1, RTAvlU32GetBestFit)
DUMMY(-1, RTAvloU32DoWithAll) DUMMY(-1, RTAvloU32DoWithAll)
@ -211,13 +211,13 @@ DUMMY(-1, RTAvlU32Get)
DUMMY(-1, RTAvlU32DoWithAll) DUMMY(-1, RTAvlU32DoWithAll)
DUMMY(-1, RTAvlU32Insert) DUMMY(-1, RTAvlU32Insert)
CHECKED_DUMMY( 0, IOMR3Init) CHECKED_DUMMY(int, 0, IOMR3Init)
int IOMR3IOPortRegisterR0() { return 0; } int IOMR3IOPortRegisterR0() { return 0; }
int IOMR3IOPortRegisterRC() { return 0; } int IOMR3IOPortRegisterRC() { return 0; }
CHECKED_DUMMY( 0, IOMR3MmioRegisterR0) CHECKED_DUMMY(int, 0, IOMR3MmioRegisterR0)
CHECKED_DUMMY( 0, IOMR3MmioRegisterRC) CHECKED_DUMMY(int, 0, IOMR3MmioRegisterRC)
void IOMR3Relocate() { } void IOMR3Relocate() { }
DUMMY(-1, IOMR3Reset) void IOMR3Reset() { }
DUMMY(-1, IOMR3Term) DUMMY(-1, IOMR3Term)
DUMMY(-1, IOMInterpretOUT) DUMMY(-1, IOMInterpretOUT)
@ -232,8 +232,8 @@ DUMMY(-1, RTFileQueryFsSizes)
DUMMY(-1, pthread_mutex_timedlock) DUMMY(-1, pthread_mutex_timedlock)
CHECKED_DUMMY( 0, PGMHandlerVirtualDeregister) /* XXX */ CHECKED_DUMMY(int, 0, PGMHandlerVirtualDeregister) /* XXX */
CHECKED_DUMMY( 0, PGMR3HandlerVirtualRegister) /* XXX */ CHECKED_DUMMY(int, 0, PGMR3HandlerVirtualRegister) /* XXX */
/* /*
* Dummies added for storage * Dummies added for storage
@ -278,8 +278,8 @@ DUMMY(-1, RTSymlinkDelete)
DUMMY(-1, RTNetIPv6PseudoChecksumEx) DUMMY(-1, RTNetIPv6PseudoChecksumEx)
CHECKED_DUMMY(0, futimes) CHECKED_DUMMY(int, 0, futimes)
CHECKED_DUMMY(0, lutimes) CHECKED_DUMMY(int, 0, lutimes)
int __isthreaded; int __isthreaded;
@ -290,10 +290,10 @@ int PGMFlushTLB() { return 0; }
int PGMInvalidatePage() { return 0; } /* seems to be needed on raw mode only */ int PGMInvalidatePage() { return 0; } /* seems to be needed on raw mode only */
int PGMHandlerPhysicalPageTempOff() { return 0; } int PGMHandlerPhysicalPageTempOff() { return 0; }
int PGMIsLockOwner() { return 0; } /* assertion in EMRemLock */ bool PGMIsLockOwner() { return false; } /* assertion in EMRemLock */
bool IOMIsLockOwner() { return 0; } /* XXX */ bool IOMIsLockOwner() { return false; } /* XXX */
int MMHyperIsInsideArea() { return 0; } /* used by dbgfR3DisasInstrRead */ int MMHyperIsInsideArea() { return 0; } /* used by dbgfR3DisasInstrRead */
int PGMPhysReleasePageMappingLock() { return 0; } void PGMPhysReleasePageMappingLock() { }
} /* extern "C" */ } /* extern "C" */

View File

@ -161,8 +161,11 @@ class Guest_ioports
/* /*
Range *r = _lookup(PortStart, cPorts); Range *r = _lookup(PortStart, cPorts);
if (r) { if (r) {
PERR("failure 0x%lx+0x%lx", PortStart, cPorts); PERR("io port inseration failure 0x%x+0x%x - '%s'",
while (1) {} PortStart, cPorts,
pDevIns && pDevIns->pReg ? pDevIns->pReg->szName : 0);
dump();
Assert(!r);
return VERR_GENERAL_FAILURE; return VERR_GENERAL_FAILURE;
} }
*/ */

View File

@ -152,24 +152,32 @@ uint64_t genode_cpu_hz()
} }
bool Vmm_memory::unmap_from_vm(RTGCPHYS GCPhys) bool Vmm_memory::revoke_from_vm(Region *r)
{ {
size_t const size = 1; Assert(r);
Region *r = _lookup_unsynchronized(GCPhys, size); using namespace Genode;
if (!r) return false;
using Genode::addr_t;
addr_t const vmm_local = (addr_t)r->local_addr<addr_t>(); addr_t const vmm_local = (addr_t)r->local_addr<addr_t>();
Assert(vmm_local); Assert(vmm_local);
Assert(!((r->size() - 1) & vmm_local));
Flexpage_iterator fli(vmm_local, r->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; using namespace Nova;
unsigned const order = Genode::log2(r->size() >> PAGE_SIZE_LOG2);
Rights rwx(true, true, true); Rights const revoke_rwx(true, true, true);
revoke(Mem_crd(vmm_local >> PAGE_SIZE_LOG2, order, rwx), false); 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; return true;
} }

View File

@ -66,7 +66,8 @@ static inline Genode::uint32_t sel_ar_conv_from_nova(Genode::uint16_t v)
* Used to map mmio memory to VM * Used to map mmio memory to VM
*/ */
extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite, extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite,
void **ppv); void **ppv, Genode::Flexpage_iterator &fli,
bool &writeable);
class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread> class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>
@ -213,6 +214,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>
enum { MAP_SIZE = 0x1000UL }; enum { MAP_SIZE = 0x1000UL };
bool writeable = true;
Flexpage_iterator fli; Flexpage_iterator fli;
void *pv = guest_memory()->lookup_ram(reason, MAP_SIZE, fli); void *pv = guest_memory()->lookup_ram(reason, MAP_SIZE, fli);
@ -221,11 +223,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>
* Check whether this is some mmio memory provided by VMM * Check whether this is some mmio memory provided by VMM
* we can map, e.g. VMMDev memory or framebuffer currently. * we can map, e.g. VMMDev memory or framebuffer currently.
*/ */
int res = MMIO2_MAPPED_SYNC(_current_vm, reason, MAP_SIZE, &pv); int res = MMIO2_MAPPED_SYNC(_current_vm, reason, MAP_SIZE, &pv,
if (pv && (res == VINF_SUCCESS)) fli, writeable);
fli = Genode::Flexpage_iterator((addr_t)pv, MAP_SIZE, if (res != VINF_SUCCESS)
reason, MAP_SIZE, reason);
else
pv = 0; pv = 0;
} }
@ -233,16 +233,16 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>
if (!pv) if (!pv)
_fpu_save_and_longjmp(); _fpu_save_and_longjmp();
/* fault region is ram - so map it */ /* fault region can be mapped - prepare utcb */
enum {
USER_PD = false, GUEST_PGT = true,
READABLE = true, WRITEABLE = true, EXECUTABLE = true
};
Rights const permission(READABLE, WRITEABLE, EXECUTABLE);
/* prepare utcb */
utcb->set_msg_word(0); utcb->set_msg_word(0);
utcb->mtd = Mtd::FPU; utcb->mtd = Mtd::FPU;
enum {
USER_PD = false, GUEST_PGT = true,
READABLE = true, EXECUTABLE = true
};
Rights permission(READABLE, writeable, EXECUTABLE);
/* add map items until no space is left on utcb anymore */ /* add map items until no space is left on utcb anymore */
bool res; bool res;

View File

@ -33,6 +33,8 @@
using Genode::Ram_session; using Genode::Ram_session;
using Genode::Rm_session; using Genode::Rm_session;
static bool debug = false;
static bool verbose_debug = false;
Vmm_memory *vmm_memory() Vmm_memory *vmm_memory()
{ {
@ -48,24 +50,60 @@ Guest_memory *guest_memory()
} }
static DECLCALLBACK(int) romwritehandler(PVM pVM, RTGCPHYS GCPhys,
void *pvPhys, void *pvBuf,
size_t cbBuf,
PGMACCESSTYPE enmAccessType,
void *pvUser)
{
while (1) {
Assert(!"Somebody tries to write to ROM");
}
return 0;
}
int PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, int PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
RTGCPHYS cb, const void *pvBinary, uint32_t cbBinary, RTGCPHYS cb, const void *pvBinary, uint32_t cbBinary,
uint32_t fFlags, const char *pszDesc) uint32_t fFlags, const char *pszDesc)
{ {
PLOG("PGMR3PhysRomRegister: GCPhys=0x%lx cb=0x%zx pvBinary=0x%p", PLOG("PGMR3PhysRomRegister: GCPhys=0x%llx cb=0x%llx pvBinary=0x%p - '%s'",
(long)GCPhys, (size_t)cb, pvBinary); GCPhys, cb, pvBinary, pszDesc);
try { try {
guest_memory()->add_rom_mapping(GCPhys, cb, pvBinary, pDevIns); RTGCPHYS GCPhysLast = GCPhys + (cb - 1);
/* size_t size = (size_t)cb;
* XXX Try to understand the fShadowed condition Assert(cb == size);
* (see pgmR3PhysRomRegister)
*/
REMR3NotifyPhysRomRegister(pVM, GCPhys, cb, NULL, false /* fShadowed */);
} catch (Guest_memory::Region_conflict) { void *pv = vmm_memory()->alloc_rom(size, pDevIns);
return VERR_PGM_MAPPING_CONFLICT; } Assert(pv);
memcpy(pv, pvBinary, size);
/* associate memory of VMM with guest VM */
vmm_memory()->map_to_vm(pDevIns, GCPhys);
guest_memory()->add_rom_mapping(GCPhys, cb, pv, pDevIns);
bool fShadowed = fFlags & PGMPHYS_ROM_FLAGS_SHADOWED;
Assert(!fShadowed);
int rc = PGMR3HandlerPhysicalRegister(pVM,
PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
GCPhys, GCPhysLast,
romwritehandler,
NULL,
NULL, NULL, 0,
NULL, NULL, 0, pszDesc);
Assert(rc == VINF_SUCCESS);
#ifdef VBOX_WITH_REM
REMR3NotifyPhysRomRegister(pVM, GCPhys, cb, NULL, fShadowed);
#endif
}
catch (Guest_memory::Region_conflict) { return VERR_PGM_MAPPING_CONFLICT; }
catch (Ram_session::Alloc_failed) { return VERR_PGM_MAPPING_CONFLICT; }
catch (Rm_session::Attach_failed) { return VERR_PGM_MAPPING_CONFLICT; }
return VINF_SUCCESS; return VINF_SUCCESS;
} }
@ -94,15 +132,15 @@ int PGMPhysWrite(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
int rc = pfnHandlerR3(pVM, GCPhys, 0, 0, cbWrite, PGMACCESSTYPE_WRITE, int rc = pfnHandlerR3(pVM, GCPhys, 0, 0, cbWrite, PGMACCESSTYPE_WRITE,
pvUserR3); pvUserR3);
if (rc == VINF_PGM_HANDLER_DO_DEFAULT) { if (rc != VINF_PGM_HANDLER_DO_DEFAULT) {
memcpy(pv, pvBuf, cbWrite);
return VINF_SUCCESS;
}
PERR("unexpected %s return code %d", __FUNCTION__, rc); PERR("unexpected %s return code %d", __FUNCTION__, rc);
return VERR_GENERAL_FAILURE; return VERR_GENERAL_FAILURE;
} }
memcpy(pv, pvBuf, cbWrite);
return VINF_SUCCESS;
}
int PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, int PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf,
size_t cbWrite, const char *pszWho) size_t cbWrite, const char *pszWho)
@ -168,7 +206,7 @@ int PGMR3PhysMMIO2Register(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
int PGMR3PhysMMIO2Map(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, int PGMR3PhysMMIO2Map(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS GCPhys) RTGCPHYS GCPhys)
{ {
size_t cb = vmm_memory()->map_to_vm(pDevIns, iRegion, GCPhys); size_t cb = vmm_memory()->map_to_vm(pDevIns, GCPhys, iRegion);
if (cb == 0) { if (cb == 0) {
PERR("PGMR3PhysMMIO2Map: lookup for pDevIns=%p iRegion=%u failed\n", PERR("PGMR3PhysMMIO2Map: lookup for pDevIns=%p iRegion=%u failed\n",
pDevIns, iRegion); pDevIns, iRegion);
@ -178,7 +216,9 @@ int PGMR3PhysMMIO2Map(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
PLOG("PGMR3PhysMMIO2Map: pDevIns=%p iRegion=%u cb=0x%zx GCPhys=0x%lx\n", PLOG("PGMR3PhysMMIO2Map: pDevIns=%p iRegion=%u cb=0x%zx GCPhys=0x%lx\n",
pDevIns, iRegion, cb, (long)GCPhys); pDevIns, iRegion, cb, (long)GCPhys);
#ifdef VBOX_WITH_REM
REMR3NotifyPhysRamRegister(pVM, GCPhys, cb, REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2); REMR3NotifyPhysRamRegister(pVM, GCPhys, cb, REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2);
#endif
return VINF_SUCCESS; return VINF_SUCCESS;
} }
@ -187,10 +227,20 @@ int PGMR3PhysMMIO2Map(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
int PGMR3PhysMMIO2Unmap(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, int PGMR3PhysMMIO2Unmap(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS GCPhys) RTGCPHYS GCPhys)
{ {
PDBG("called %x %x", GCPhys, iRegion); if (debug)
PDBG("called phys=%llx iRegion=0x%x", GCPhys, iRegion);
vmm_memory()->map_to_vm(pDevIns, iRegion, 0); size_t size = 1;
bool INVALIDATE = true;
bool ok = vmm_memory()->unmap_from_vm(GCPhys, size, INVALIDATE);
Assert(ok);
#ifdef VBOX_WITH_REM
#if 0 /* XXX */
if (fInformREM)
REMR3NotifyPhysRamDeregister(pVM, GCPhysRangeREM, cbRangeREM);
#endif
#endif
return VINF_SUCCESS; return VINF_SUCCESS;
} }
@ -198,7 +248,8 @@ int PGMR3PhysMMIO2Unmap(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
bool PGMR3PhysMMIO2IsBase(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys) bool PGMR3PhysMMIO2IsBase(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
{ {
bool res = vmm_memory()->lookup(GCPhys, 1); bool res = vmm_memory()->lookup(GCPhys, 1);
PDBG("called %x %u", GCPhys, res); if (debug)
PDBG("called phys=%llx res=%u", GCPhys, res);
return res; return res;
} }
@ -212,13 +263,18 @@ int PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType,
const char *pszHandlerRC, const char *pszHandlerRC,
RTRCPTR pvUserRC, const char *pszDesc) RTRCPTR pvUserRC, const char *pszDesc)
{ {
PLOG("PGMR3HandlerPhysicalRegister: pszDesc=%s %u GCPhys=0x%lx GCPhysLast=0x%lx r3=0x%p\n", PLOG("PGMR3HandlerPhysicalRegister: GCPhys=0x%llx-%llx r3=0x%p "
pszDesc, enmType, (long)GCPhys, (long)GCPhysLast, (void *)pfnHandlerR3); "enmType=%x - '%s'\n",
GCPhys, GCPhysLast, pfnHandlerR3, enmType, pszDesc);
REMR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast - GCPhys + 1, !!pfnHandlerR3); bool ok = vmm_memory()->add_handler(GCPhys, GCPhysLast - GCPhys + 1,
pfnHandlerR3, pvUserR3, enmType);
Assert(ok);
vmm_memory()->add_handler(GCPhys, GCPhysLast - GCPhys + 1, pfnHandlerR3, #ifdef VBOX_WITH_REM
pvUserR3); REMR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast -
GCPhys + 1, !!pfnHandlerR3);
#endif
return VINF_SUCCESS; return VINF_SUCCESS;
} }
@ -226,15 +282,36 @@ int PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType,
int PGMHandlerPhysicalDeregister(PVM pVM, RTGCPHYS GCPhys) int PGMHandlerPhysicalDeregister(PVM pVM, RTGCPHYS GCPhys)
{ {
PDBG("called %x", GCPhys); size_t size = 1;
/*
for(;;); #ifdef VBOX_WITH_REM
pgmHandlerPhysicalResetRamFlags(pVM, pCur); PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0;
REMR3NotifyHandlerPhysicalDeregister(pVM, pCur->enmType, GCPhysStart, GCPhysLast - GCPhysStart + 1, !!pCur->pfnHandlerR3, fRestoreAsRAM); PGMPHYSHANDLERTYPE enmType;
*/
vmm_memory()->add_handler(GCPhys, GCPhys + 1, 0, 0); void * pv = vmm_memory()->lookup(GCPhys, size, &pfnHandlerR3, 0, &enmType);
Assert(pv);
if (debug)
PDBG("called phys=%llx enmType=%x", GCPhys, enmType);
#endif
bool ok = vmm_memory()->add_handler(GCPhys, size, 0, 0);
Assert(ok);
#ifdef VBOX_WITH_REM
bool fRestoreAsRAM = pfnHandlerR3 && enmType != PGMPHYSHANDLERTYPE_MMIO;
/* GCPhysstart and size gets written ! */
RTGCPHYS GCPhysStart = GCPhys;
bool io = vmm_memory()->lookup_range(GCPhysStart, size);
Assert(io);
REMR3NotifyHandlerPhysicalDeregister(pVM, enmType, GCPhysStart, size,
!!pfnHandlerR3, fRestoreAsRAM);
#endif
return VINF_SUCCESS; return VINF_SUCCESS;
return VERR_PGM_HANDLER_NOT_FOUND;
} }
@ -251,7 +328,9 @@ int PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb,
* The lack of allocation-related VERR_PGM_ error codes suggests * The lack of allocation-related VERR_PGM_ error codes suggests
* so. * so.
*/ */
void *pv = vmm_memory()->alloc_ram((size_t)cb); size_t size = (size_t)cb;
Assert(cb == size);
void *pv = vmm_memory()->alloc_ram(size);
guest_memory()->add_ram_mapping(GCPhys, cb, pv); guest_memory()->add_ram_mapping(GCPhys, cb, pv);
@ -270,8 +349,8 @@ int PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb,
int PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags) int PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags)
{ {
PLOG("PGMMapSetPage: GCPtr=0x%lx cb=0x%lx, flags=0x%lx", PLOG("PGMMapSetPage: GCPtr=0x%llx cb=0x%llx, flags=0x%llx",
(long)GCPtr, (long)cb, (long)fFlags); GCPtr, cb, fFlags);
return VINF_SUCCESS; return VINF_SUCCESS;
} }
@ -303,33 +382,57 @@ int PGMR3Init(PVM pVM)
} }
int PGMPhysGCPtr2CCPtrReadOnly(PVMCPU pVCpu, RTGCPTR GCPtr, void const **ppv,
PPGMPAGEMAPLOCK pLock)
{
PERR("%s not implemented - caller 0x%p",
__func__, __builtin_return_address(0));
while (1) { asm volatile ("ud2a"); }
return VERR_GENERAL_FAILURE;
}
int PGMR3PhysTlbGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, void **ppv) int PGMR3PhysTlbGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, void **ppv)
{ {
size_t const size = 1; size_t const size = 1;
void *pv = guest_memory()->lookup(GCPhys, size);
if (pv) {
*ppv = pv;
return VINF_SUCCESS;
}
PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0; PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0;
void *pvUserR3 = 0; void *pvUserR3 = 0;
PGMPHYSHANDLERTYPE enmType;
pv = vmm_memory()->lookup(GCPhys, size, &pfnHandlerR3, &pvUserR3); void * pv = vmm_memory()->lookup(GCPhys, size, &pfnHandlerR3, &pvUserR3,
&enmType);
if (!pv) {
/* It could be ordinary guest memory - look it up. */
pv = guest_memory()->lookup(GCPhys, size);
if (!pv) { if (!pv) {
PERR("%s: lookup for GCPhys=0x%p failed", __func__, GCPhys); PERR("%s: lookup for GCPhys=0x%llx failed", __func__, GCPhys);
return VERR_PGM_PHYS_TLB_UNASSIGNED; return VERR_PGM_PHYS_TLB_UNASSIGNED;
} }
*ppv = pv;
if (verbose_debug)
PDBG("%llx %u -> 0x%p", GCPhys, fWritable, pv);
return VINF_SUCCESS;
}
/* pv valid - check handlers next */ /* pv valid - check handlers next */
if (!pfnHandlerR3 && !pvUserR3) { if (!pfnHandlerR3 && !pvUserR3) {
PERR("%s: %llx %u -> 0x%p no handlers", __func__, GCPhys, fWritable, pv);
*ppv = pv; *ppv = pv;
return VINF_SUCCESS; return VINF_SUCCESS;
} }
PERR("%s: denied access - handlers set - GCPhys=0x%p", __func__, GCPhys); if (enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE) {
*ppv = pv;
return VINF_PGM_PHYS_TLB_CATCH_WRITE;
}
PERR("%s: denied access - handlers set - GCPhys=0x%llx %p %p %x", __func__, GCPhys, pfnHandlerR3, pvUserR3, enmType);
return VERR_PGM_PHYS_TLB_CATCH_ALL; return VERR_PGM_PHYS_TLB_CATCH_ALL;
} }
@ -338,7 +441,9 @@ void PGMR3PhysSetA20(PVMCPU pVCpu, bool fEnable)
{ {
if (!pVCpu->pgm.s.fA20Enabled != fEnable) { if (!pVCpu->pgm.s.fA20Enabled != fEnable) {
pVCpu->pgm.s.fA20Enabled = fEnable; pVCpu->pgm.s.fA20Enabled = fEnable;
#ifdef VBOX_WITH_REM
REMR3A20Set(pVCpu->pVMR3, pVCpu, fEnable); REMR3A20Set(pVCpu->pVMR3, pVCpu, fEnable);
#endif
} }
return; return;
@ -356,7 +461,7 @@ void PGMR3PhysWriteU8(PVM pVM, RTGCPHYS GCPhys, uint8_t value)
void *pv = guest_memory()->lookup(GCPhys, sizeof(value)); void *pv = guest_memory()->lookup(GCPhys, sizeof(value));
if (!pv) { if (!pv) {
PDBG("invalid write attempt"); PERR("%s: invalid write attempt phy=%llx", __func__, GCPhys);
return; return;
} }
@ -369,7 +474,7 @@ void PGMR3PhysWriteU16(PVM pVM, RTGCPHYS GCPhys, uint16_t value)
void *pv = guest_memory()->lookup(GCPhys, sizeof(value)); void *pv = guest_memory()->lookup(GCPhys, sizeof(value));
if (!pv) { if (!pv) {
PDBG("invalid write attempt"); PERR("%s: invalid write attempt phy=%llx", __func__, GCPhys);
return; return;
} }
@ -382,7 +487,7 @@ void PGMR3PhysWriteU32(PVM pVM, RTGCPHYS GCPhys, uint32_t value)
void *pv = guest_memory()->lookup(GCPhys, sizeof(value)); void *pv = guest_memory()->lookup(GCPhys, sizeof(value));
if (!pv) { if (!pv) {
PDBG("invalid write attempt"); PERR("%s: invalid write attempt phy=%llx", __func__, GCPhys);
return; return;
} }
@ -395,7 +500,7 @@ uint32_t PGMR3PhysReadU32(PVM pVM, RTGCPHYS GCPhys)
void *pv = guest_memory()->lookup(GCPhys, 4); void *pv = guest_memory()->lookup(GCPhys, 4);
if (!pv) { if (!pv) {
PDBG("invalid read attempt"); PERR("%s: invalid read attempt phys=%llx", __func__, GCPhys);
return 0; return 0;
} }
@ -403,113 +508,13 @@ uint32_t PGMR3PhysReadU32(PVM pVM, RTGCPHYS GCPhys)
} }
int PGMPhysGCPhys2CCPtrReadOnly(PVM pVM, RTGCPHYS GCPhys, void const **ppv,
int PGMPhysGCPtr2CCPtrReadOnly(PVMCPU pVCpu, RTGCPTR GCPtr, void const **ppv,
PPGMPAGEMAPLOCK pLock) PPGMPAGEMAPLOCK pLock)
{
PDBG("not implemented");
while (1) {}
return VINF_SUCCESS;
}
int PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode) {
// Assert(pVCpu->pgm.s.enmShadowMode == PGMMODE_EPT);
// PDBG("not implemented %x %x", pVCpu->pgm.s.enmShadowMode, PGMMODE_EPT);
pVCpu->pgm.s.enmGuestMode = enmGuestMode;
HWACCMR3PagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
return VINF_SUCCESS;
}
int PGMChangeMode(PVMCPU pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer)
{
PGMMODE enmGuestMode;
VMCPU_ASSERT_EMT(pVCpu);
/*
* Calc the new guest mode.
*/
if (!(cr0 & X86_CR0_PE))
enmGuestMode = PGMMODE_REAL;
else if (!(cr0 & X86_CR0_PG))
enmGuestMode = PGMMODE_PROTECTED;
else if (!(cr4 & X86_CR4_PAE))
{
bool const fPse = !!(cr4 & X86_CR4_PSE);
if (pVCpu->pgm.s.fGst32BitPageSizeExtension != fPse)
Log(("PGMChangeMode: CR4.PSE %d -> %d\n", pVCpu->pgm.s.fGst32BitPageSizeExtension, fPse));
pVCpu->pgm.s.fGst32BitPageSizeExtension = fPse;
enmGuestMode = PGMMODE_32_BIT;
}
else if (!(efer & MSR_K6_EFER_LME))
{
if (!(efer & MSR_K6_EFER_NXE))
enmGuestMode = PGMMODE_PAE;
else
enmGuestMode = PGMMODE_PAE_NX;
}
else
{
if (!(efer & MSR_K6_EFER_NXE))
enmGuestMode = PGMMODE_AMD64;
else
enmGuestMode = PGMMODE_AMD64_NX;
}
/*
* Did it change?
*/
if (pVCpu->pgm.s.enmGuestMode == enmGuestMode)
return VINF_SUCCESS;
/* Flush the TLB */
// PGM_INVL_VCPU_TLBS(pVCpu);
VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
// PDBG("not implemented %x %x before", enmGuestMode, pVCpu->pgm.s.enmGuestMode);
int rc = PGMR3ChangeMode(pVCpu->CTX_SUFF(pVM), pVCpu, enmGuestMode);
// PDBG("not implemented %x %x out %p", enmGuestMode, pVCpu->pgm.s.enmGuestMode, __builtin_return_address(0));
// return VINF_PGM_CHANGE_MODE;
return rc;
}
/*
* Copied from src/VBox/VMM/VMMAll/PGMAll.cpp
*/
PGMMODE PGMGetGuestMode(PVMCPU pVCpu) { return pVCpu->pgm.s.enmGuestMode; }
VMMDECL(const char *) PGMGetModeName(PGMMODE enmMode)
{
switch (enmMode)
{
case PGMMODE_REAL: return "Real";
case PGMMODE_PROTECTED: return "Protected";
case PGMMODE_32_BIT: return "32-bit";
case PGMMODE_PAE: return "PAE";
case PGMMODE_PAE_NX: return "PAE+NX";
case PGMMODE_AMD64: return "AMD64";
case PGMMODE_AMD64_NX: return "AMD64+NX";
case PGMMODE_NESTED: return "Nested";
case PGMMODE_EPT: return "EPT";
default: return "unknown mode value";
}
}
int PGMPhysGCPhys2CCPtrReadOnly(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock)
{ {
void *pv = guest_memory()->lookup(GCPhys, 0x1000); void *pv = guest_memory()->lookup(GCPhys, 0x1000);
if (!pv) { if (!pv) {
PDBG("unknown address pv=%p ppv=%p GCPhys=%llx", pv, ppv, GCPhys); PERR("unknown address pv=%p ppv=%p GCPhys=%llx", pv, ppv, GCPhys);
guest_memory()->dump(); guest_memory()->dump();
@ -526,16 +531,21 @@ int PGMPhysGCPhys2CCPtrReadOnly(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGM
int PGMHandlerPhysicalReset(PVM, RTGCPHYS GCPhys) int PGMHandlerPhysicalReset(PVM, RTGCPHYS GCPhys)
{ {
if (!vmm_memory()->unmap_from_vm(GCPhys)) size_t size = 1;
PWRN("%s: unbacked region - GCPhys %lx", __func__, GCPhys); if (!vmm_memory()->unmap_from_vm(GCPhys, size))
PWRN("%s: unbacked region - GCPhys %llx", __func__, GCPhys);
return VINF_SUCCESS; return VINF_SUCCESS;
} }
extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite, extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite,
void **ppv) void **ppv, Genode::Flexpage_iterator &fli,
bool &writeable)
{ {
using Genode::Flexpage_iterator;
using Genode::addr_t;
/* DON'T USE normal printf in this function - corrupts unsaved UTCB !!! */ /* DON'T USE normal printf in this function - corrupts unsaved UTCB !!! */
PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0; PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0;
@ -546,6 +556,8 @@ extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite,
if (!pv) if (!pv)
return VERR_PGM_PHYS_TLB_UNASSIGNED; return VERR_PGM_PHYS_TLB_UNASSIGNED;
fli = Flexpage_iterator((addr_t)pv, cbWrite, GCPhys, cbWrite, GCPhys);
if (!pfnHandlerR3 && !pvUserR3) { if (!pfnHandlerR3 && !pvUserR3) {
*ppv = pv; *ppv = pv;
/* you may map it */ /* you may map it */
@ -567,9 +579,25 @@ extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite,
return rc; return rc;
} }
Vmm::printf("%s: GCPhys=0x%lx failed - unexpected state \n", RTGCPHYS map_start = GCPhys;
__func__, GCPhys); size_t map_size = 1;
return VERR_GENERAL_FAILURE;
bool io = vmm_memory()->lookup_range(map_start, map_size);
Assert(io);
pv = vmm_memory()->lookup(map_start, map_size);
Assert(pv);
fli = Flexpage_iterator((addr_t)pv, map_size, map_start, map_size, map_start);
if (debug)
Vmm::printf("%s: GCPhys=0x%llx - %llx+%zx\n",
__func__, GCPhys, map_start, map_size);
*ppv = pv;
writeable = false;
return VINF_SUCCESS;
} }
@ -579,8 +607,8 @@ void PGMR3Reset(PVM pVM)
for (VMCPUID i = 0; i < pVM->cCpus; i++) for (VMCPUID i = 0; i < pVM->cCpus; i++)
{ {
int rc = PGMR3ChangeMode(pVM, &pVM->aCpus[i], PGMMODE_REAL); // int rc = PGMR3ChangeMode(pVM, &pVM->aCpus[i], PGMMODE_REAL);
AssertRC(rc); // AssertRC(rc);
} }
for (VMCPUID i = 0; i < pVM->cCpus; i++) for (VMCPUID i = 0; i < pVM->cCpus; i++)
@ -590,6 +618,8 @@ void PGMR3Reset(PVM pVM)
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3); VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL); VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
if (!pVCpu->pgm.s.fA20Enabled) if (!pVCpu->pgm.s.fA20Enabled)
{ {
pVCpu->pgm.s.fA20Enabled = true; pVCpu->pgm.s.fA20Enabled = true;
@ -602,7 +632,7 @@ void PGMR3Reset(PVM pVM)
} }
} }
PERR("clearing ram and rom areas missing !!!!!!!"); vmm_memory()->revoke_all();
} }

View File

@ -0,0 +1,11 @@
+++ src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
@@ -536,7 +536,8 @@
pView->u32VBVAOffset = HGSMIOFFSET_VOID;
}
- pVGAState->pDrv->pfnVBVADisable (pVGAState->pDrv, uScreenId);
+ if (pVGAState->pDrv->pfnVBVADisable)
+ pVGAState->pDrv->pfnVBVADisable (pVGAState->pDrv, uScreenId);
return VINF_SUCCESS;
}

View File

@ -54,6 +54,7 @@ class Vmm_memory
RTGCPHYS vm_phys; RTGCPHYS vm_phys;
PFNPGMR3PHYSHANDLER pfnHandlerR3; PFNPGMR3PHYSHANDLER pfnHandlerR3;
void *pvUserR3; void *pvUserR3;
PGMPHYSHANDLERTYPE enmType;
Region(Ram_session &ram, size_t size, PPDMDEVINS pDevIns, Region(Ram_session &ram, size_t size, PPDMDEVINS pDevIns,
unsigned iRegion) unsigned iRegion)
@ -122,12 +123,69 @@ class Vmm_memory
return 0; return 0;
} }
void *alloc_ram(size_t cb) void *alloc_rom(size_t cb, PPDMDEVINS pDevIns)
{ {
return alloc(cb, 0, 0); return alloc(cb, pDevIns, ~0U);
} }
size_t map_to_vm(PPDMDEVINS pDevIns, unsigned iRegion, RTGCPHYS GCPhys) void *alloc_ram(size_t cb)
{
return alloc(cb, 0, ~0U);
}
bool add_handler(RTGCPHYS vm_phys, size_t size,
PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3,
PGMPHYSHANDLERTYPE enmType = PGMPHYSHANDLERTYPE_PHYSICAL_ALL)
{
Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size);
if (!r) return false;
r->enmType = enmType;
r->pfnHandlerR3 = pfnHandlerR3;
r->pvUserR3 = pvUserR3;
return true;
}
void * lookup(RTGCPHYS vm_phys, size_t size,
PFNPGMR3PHYSHANDLER *ppfnHandlerR3 = 0,
void **ppvUserR3 = 0,
PGMPHYSHANDLERTYPE *enmType = 0)
{
Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size);
if (!r) return 0;
if (enmType) *enmType = r->enmType;
if (ppfnHandlerR3) *ppfnHandlerR3 = r->pfnHandlerR3;
if (ppvUserR3) *ppvUserR3 = r->pvUserR3;
return reinterpret_cast<void *>(r->local_addr<uint8_t>() +
(vm_phys - r->vm_phys));
}
bool lookup_range(RTGCPHYS &vm_phys, size_t &size)
{
Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size);
if (!r)
return false;
vm_phys = r->vm_phys;
size = r->size();
return true;
}
size_t map_to_vm(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
unsigned iRegion = ~0U)
{ {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
@ -138,36 +196,39 @@ class Vmm_memory
return r ? r->size() : 0; return r ? r->size() : 0;
} }
void add_handler(RTGCPHYS vm_phys, size_t size, bool unmap_from_vm(RTGCPHYS GCPhys, size_t size, bool invalidate = false)
PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3)
{ {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size); Region *r = _lookup_unsynchronized(GCPhys, size);
if (!r) return false;
if (!r) return; bool result = revoke_from_vm(r);
r->pfnHandlerR3 = pfnHandlerR3; if (invalidate)
r->pvUserR3 = pvUserR3; r->vm_phys = 0ULL;
return result;
} }
void * lookup(RTGCPHYS vm_phys, size_t size, /**
PFNPGMR3PHYSHANDLER *ppfnHandlerR3 = 0, void **ppvUserR3 = 0) * Platform specific implemented.
*/
bool revoke_from_vm(Region *r);
/**
* Revoke all memory (RAM or ROM) from VM
*/
void revoke_all()
{ {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size); for (Region *r = _regions.first(); r; r = r->next())
{
if (!r) return 0; bool ok = revoke_from_vm(r);
Assert(ok);
if (ppfnHandlerR3) *ppfnHandlerR3 = r->pfnHandlerR3; }
if (ppvUserR3) *ppvUserR3 = r->pvUserR3;
return reinterpret_cast<void *>(r->local_addr<uint8_t>() +
(vm_phys - r->vm_phys));
} }
bool unmap_from_vm(RTGCPHYS GCPhys);
}; };