More code cleanups.
This commit is contained in:
parent
31a4a389a1
commit
ae92b55818
@ -1,5 +1,5 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//// $Id: plex86-interface.cc,v 1.3 2003-01-02 02:11:40 kevinlawton Exp $
|
//// $Id: plex86-interface.cc,v 1.4 2003-01-02 17:05:47 kevinlawton Exp $
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
////
|
////
|
||||||
//// Copyright (C) 2002 Kevin P. Lawton
|
//// Copyright (C) 2002 Kevin P. Lawton
|
||||||
@ -49,22 +49,22 @@ openFD(void)
|
|||||||
{
|
{
|
||||||
if (plex86State) {
|
if (plex86State) {
|
||||||
// This should be the first operation; no state should be set yet.
|
// This should be the first operation; no state should be set yet.
|
||||||
fprintf(stderr, "openFD: plex86State = 0x%x\n", plex86State);
|
fprintf(stderr, "plex86: openFD: plex86State = 0x%x\n", plex86State);
|
||||||
return(0); // Error.
|
return(0); // Error.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a new VM.
|
// Open a new VM.
|
||||||
fprintf(stderr, "Opening VM.\n");
|
fprintf(stderr, "plex86: opening VM.\n");
|
||||||
fprintf(stderr, "Trying /dev/misc/plex86...");
|
fprintf(stderr, "plex86: trying /dev/misc/plex86...");
|
||||||
plex86FD = open("/dev/misc/plex86", O_RDWR);
|
plex86FD = open("/dev/misc/plex86", O_RDWR);
|
||||||
if (plex86FD < 0) {
|
if (plex86FD < 0) {
|
||||||
fprintf(stderr, "failed.\n");
|
fprintf(stderr, "failed.\n");
|
||||||
// Try the old name.
|
// Try the old name.
|
||||||
fprintf(stderr, "Trying /dev/plex86...");
|
fprintf(stderr, "plex86: trying /dev/plex86...");
|
||||||
plex86FD = open("/dev/plex86", O_RDWR);
|
plex86FD = open("/dev/plex86", O_RDWR);
|
||||||
if (plex86FD < 0) {
|
if (plex86FD < 0) {
|
||||||
fprintf(stderr, "failed.\n");
|
fprintf(stderr, "failed.\n");
|
||||||
fprintf(stderr, "Did you load the kernel module?"
|
fprintf(stderr, "plex86: did you load the kernel module?"
|
||||||
" Read the toplevel README file!\n");
|
" Read the toplevel README file!\n");
|
||||||
perror ("open");
|
perror ("open");
|
||||||
return(-1); // Error.
|
return(-1); // Error.
|
||||||
@ -92,7 +92,7 @@ plex86CpuInfo(BX_CPU_C *cpu)
|
|||||||
bochsCPUID.procSignature.raw = cpu->cpuidInfo.procSignature;
|
bochsCPUID.procSignature.raw = cpu->cpuidInfo.procSignature;
|
||||||
bochsCPUID.featureFlags.raw = cpu->cpuidInfo.featureFlags;
|
bochsCPUID.featureFlags.raw = cpu->cpuidInfo.featureFlags;
|
||||||
|
|
||||||
fprintf(stderr, "Passing guest CPUID to plex86.\n");
|
fprintf(stderr, "plex86: passing guest CPUID to plex86.\n");
|
||||||
if ( ioctl(plex86FD, PLEX86_CPUID, &bochsCPUID) ) {
|
if ( ioctl(plex86FD, PLEX86_CPUID, &bochsCPUID) ) {
|
||||||
perror("ioctl CPUID: ");
|
perror("ioctl CPUID: ");
|
||||||
return(0); // Error.
|
return(0); // Error.
|
||||||
@ -116,7 +116,7 @@ plex86AllocateMemory(unsigned nMegs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory from the host OS for the virtual physical memory.
|
// Allocate memory from the host OS for the virtual physical memory.
|
||||||
fprintf(stderr, "Allocating %dMB of physical memory in VM.\n", nMegs);
|
fprintf(stderr, "plex86: allocating %dMB of physical memory in VM.\n", nMegs);
|
||||||
if (ioctl(plex86FD, PLEX86_ALLOCVPHYS, nMegs) == -1) {
|
if (ioctl(plex86FD, PLEX86_ALLOCVPHYS, nMegs) == -1) {
|
||||||
perror("ioctl ALLOCVPHYS: ");
|
perror("ioctl ALLOCVPHYS: ");
|
||||||
plex86TearDown();
|
plex86TearDown();
|
||||||
@ -125,7 +125,7 @@ plex86AllocateMemory(unsigned nMegs)
|
|||||||
plex86State |= Plex86StateMemAllocated;
|
plex86State |= Plex86StateMemAllocated;
|
||||||
|
|
||||||
// Map guest virtual physical memory into user address space and zero it.
|
// Map guest virtual physical memory into user address space and zero it.
|
||||||
fprintf(stderr, "Mapping virtualized physical memory into monitor.\n");
|
fprintf(stderr, "plex86: mapping virtualized physical memory into monitor.\n");
|
||||||
ptr = (Bit8u*) mmap(NULL, plex86MemSize, PROT_READ | PROT_WRITE,
|
ptr = (Bit8u*) mmap(NULL, plex86MemSize, PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED, plex86FD, 0);
|
MAP_SHARED, plex86FD, 0);
|
||||||
if (ptr == (void *) -1) {
|
if (ptr == (void *) -1) {
|
||||||
@ -141,7 +141,7 @@ plex86AllocateMemory(unsigned nMegs)
|
|||||||
// Create a memory mapping of the monitor's print buffer into
|
// Create a memory mapping of the monitor's print buffer into
|
||||||
// user memory. This is used for efficient printing of info that
|
// user memory. This is used for efficient printing of info that
|
||||||
// the monitor prints out.
|
// the monitor prints out.
|
||||||
fprintf(stderr, "Mapping monitor print buffer into user mem.\n");
|
fprintf(stderr, "plex86: mapping monitor print buffer into user mem.\n");
|
||||||
plex86PrintBuffer = (Bit8u*) mmap(NULL, 4096, PROT_READ,
|
plex86PrintBuffer = (Bit8u*) mmap(NULL, 4096, PROT_READ,
|
||||||
MAP_SHARED, plex86FD, plex86MemSize + 0*4096);
|
MAP_SHARED, plex86FD, plex86MemSize + 0*4096);
|
||||||
if (plex86PrintBuffer == (void *) -1) {
|
if (plex86PrintBuffer == (void *) -1) {
|
||||||
@ -154,7 +154,7 @@ plex86AllocateMemory(unsigned nMegs)
|
|||||||
// Create a memory mapping of the monitor's guest_cpu structure into
|
// Create a memory mapping of the monitor's guest_cpu structure into
|
||||||
// user memory. This is used for passing the guest_cpu state between
|
// user memory. This is used for passing the guest_cpu state between
|
||||||
// user and kernel/monitor space.
|
// user and kernel/monitor space.
|
||||||
fprintf(stderr, "Mapping guest_cpu structure into user mem.\n");
|
fprintf(stderr, "plex86: mapping guest_cpu structure into user mem.\n");
|
||||||
plex86GuestCPU = (guest_cpu_t *) mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
plex86GuestCPU = (guest_cpu_t *) mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED, plex86FD, plex86MemSize + 1*4096);
|
MAP_SHARED, plex86FD, plex86MemSize + 1*4096);
|
||||||
if (plex86GuestCPU == (void *) -1) {
|
if (plex86GuestCPU == (void *) -1) {
|
||||||
@ -171,21 +171,21 @@ plex86AllocateMemory(unsigned nMegs)
|
|||||||
unsigned
|
unsigned
|
||||||
plex86TearDown(void)
|
plex86TearDown(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "plex86TearDown called.\n");
|
fprintf(stderr, "plex86: plex86TearDown called.\n");
|
||||||
|
|
||||||
fprintf(stderr, "Guest Fault Count (FYI):\n");
|
fprintf(stderr, "plex86: guest Fault Count (FYI):\n");
|
||||||
for (unsigned f=0; f<32; f++) {
|
for (unsigned f=0; f<32; f++) {
|
||||||
if (faultCount[f])
|
if (faultCount[f])
|
||||||
fprintf(stderr, "FC[%u] = %u\n", f, faultCount[f]);
|
fprintf(stderr, "plex86: FC[%u] = %u\n", f, faultCount[f]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( plex86FD < 0 ) {
|
if ( plex86FD < 0 ) {
|
||||||
fprintf(stderr, "plex86TearDown: FD not open.\n");
|
fprintf(stderr, "plex86: plex86TearDown: FD not open.\n");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( plex86State & Plex86StateMMapPhyMem ) {
|
if ( plex86State & Plex86StateMMapPhyMem ) {
|
||||||
fprintf(stderr, "Unmapping guest physical memory.\n");
|
fprintf(stderr, "plex86: unmapping guest physical memory.\n");
|
||||||
if (munmap(plex86MemPtr, plex86MemSize) != 0) {
|
if (munmap(plex86MemPtr, plex86MemSize) != 0) {
|
||||||
perror ("munmap of guest physical memory");
|
perror ("munmap of guest physical memory");
|
||||||
return(0); // Failed.
|
return(0); // Failed.
|
||||||
@ -194,7 +194,7 @@ plex86TearDown(void)
|
|||||||
plex86State &= ~Plex86StateMMapPhyMem;
|
plex86State &= ~Plex86StateMMapPhyMem;
|
||||||
|
|
||||||
if ( plex86State & Plex86StateMMapPrintBuffer ) {
|
if ( plex86State & Plex86StateMMapPrintBuffer ) {
|
||||||
fprintf(stderr, "Unmapping print buffer.\n");
|
fprintf(stderr, "plex86: unmapping print buffer.\n");
|
||||||
if (munmap(plex86PrintBuffer, 4096) != 0) {
|
if (munmap(plex86PrintBuffer, 4096) != 0) {
|
||||||
perror("munmap of print buffer.");
|
perror("munmap of print buffer.");
|
||||||
return(0); // Failed.
|
return(0); // Failed.
|
||||||
@ -203,7 +203,7 @@ plex86TearDown(void)
|
|||||||
plex86State &= ~Plex86StateMMapPrintBuffer;
|
plex86State &= ~Plex86StateMMapPrintBuffer;
|
||||||
|
|
||||||
if ( plex86State & Plex86StateMMapGuestCPU ) {
|
if ( plex86State & Plex86StateMMapGuestCPU ) {
|
||||||
fprintf(stderr, "Unmapping guest_cpu structure.\n");
|
fprintf(stderr, "plex86: unmapping guest_cpu structure.\n");
|
||||||
if (munmap(plex86GuestCPU, 4096) != 0) {
|
if (munmap(plex86GuestCPU, 4096) != 0) {
|
||||||
perror("munmap of guest_cpu structure.");
|
perror("munmap of guest_cpu structure.");
|
||||||
return(0); // Failed.
|
return(0); // Failed.
|
||||||
@ -211,7 +211,7 @@ plex86TearDown(void)
|
|||||||
}
|
}
|
||||||
plex86State &= ~Plex86StateMMapGuestCPU;
|
plex86State &= ~Plex86StateMMapGuestCPU;
|
||||||
|
|
||||||
fprintf(stderr, "Tearing down VM.\n");
|
fprintf(stderr, "plex86: tearing down VM.\n");
|
||||||
if (ioctl(plex86FD, PLEX86_TEARDOWN, 0) == -1) {
|
if (ioctl(plex86FD, PLEX86_TEARDOWN, 0) == -1) {
|
||||||
perror("ioctl TEARDOWN: ");
|
perror("ioctl TEARDOWN: ");
|
||||||
return(0); // Failed.
|
return(0); // Failed.
|
||||||
@ -219,12 +219,14 @@ plex86TearDown(void)
|
|||||||
plex86State &= ~Plex86StateMemAllocated;
|
plex86State &= ~Plex86StateMemAllocated;
|
||||||
|
|
||||||
// Close the connection to the kernel module.
|
// Close the connection to the kernel module.
|
||||||
fprintf(stderr, "Closing VM device.\n");
|
fprintf(stderr, "plex86: closing VM device.\n");
|
||||||
if (close(plex86FD) == -1) {
|
if (close(plex86FD) == -1) {
|
||||||
perror("close of VM device\n");
|
perror("close of VM device\n");
|
||||||
return(0); // Failed.
|
return(0); // Failed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plex86FD = -1; // File descriptor is now closed.
|
||||||
|
|
||||||
plex86State = 0; // For good measure.
|
plex86State = 0; // For good measure.
|
||||||
|
|
||||||
return(1); // OK.
|
return(1); // OK.
|
||||||
@ -237,7 +239,7 @@ plex86ExecuteInVM(BX_CPU_C *cpu)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ( plex86State != Plex86StateReady ) {
|
if ( plex86State != Plex86StateReady ) {
|
||||||
fprintf(stderr, "plex86ExecuteInVM: not in ready state (0x%x)\n",
|
fprintf(stderr, "plex86: plex86ExecuteInVM: not in ready state (0x%x)\n",
|
||||||
plex86State);
|
plex86State);
|
||||||
BX_PANIC(("plex86ExecuteInVM: bailing"));
|
BX_PANIC(("plex86ExecuteInVM: bailing"));
|
||||||
return(0);
|
return(0);
|
||||||
@ -302,31 +304,65 @@ plex86ExecuteInVM(BX_CPU_C *cpu)
|
|||||||
plex86GuestCPU->a20Enable = BX_GET_ENABLE_A20();
|
plex86GuestCPU->a20Enable = BX_GET_ENABLE_A20();
|
||||||
|
|
||||||
ret = ioctl(plex86FD, PLEX86_EXECUTE, &executeMsg);
|
ret = ioctl(plex86FD, PLEX86_EXECUTE, &executeMsg);
|
||||||
if (ret < 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "ioctl(PLEX86_EXECUTE) returns < 0\n");
|
fprintf(stderr, "plex86: ioctl(PLEX86_EXECUTE): ");
|
||||||
|
switch (ret) {
|
||||||
|
case Plex86NoExecute_Method:
|
||||||
|
fprintf(stderr, "bad execute method.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_CR0:
|
||||||
|
fprintf(stderr, "bad CR0 value.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_CR4:
|
||||||
|
fprintf(stderr, "bad CR4 value.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_CS:
|
||||||
|
fprintf(stderr, "bad CS value.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_A20:
|
||||||
|
fprintf(stderr, "bad A20 enable value.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_Selector:
|
||||||
|
fprintf(stderr, "bad selector value.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_DPL:
|
||||||
|
fprintf(stderr, "bad descriptor DPL.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_EFlags:
|
||||||
|
fprintf(stderr, "bad EFlags.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_Panic:
|
||||||
|
fprintf(stderr, "panic.\n");
|
||||||
|
break;
|
||||||
|
case Plex86NoExecute_VMState:
|
||||||
|
fprintf(stderr, "bad VM state.\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "ret = %d\n", ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
switch ( executeMsg.monitorState.request ) {
|
||||||
switch ( executeMsg.monitorState.request ) {
|
case MonReqFlushPrintBuf:
|
||||||
case MonReqFlushPrintBuf:
|
fprintf(stderr, "plex86: MonReqFlushPrintBuf:\n");
|
||||||
fprintf(stderr, "MonReqFlushPrintBuf:\n");
|
fprintf(stderr, "::%s\n", plex86PrintBuffer);
|
||||||
fprintf(stderr, "::%s\n", plex86PrintBuffer);
|
break;
|
||||||
break;
|
case MonReqPanic:
|
||||||
case MonReqPanic:
|
fprintf(stderr, "plex86: MonReqPanic:\n");
|
||||||
fprintf(stderr, "MonReqPanic:\n");
|
fprintf(stderr, "::%s\n", plex86PrintBuffer);
|
||||||
fprintf(stderr, "::%s\n", plex86PrintBuffer);
|
break;
|
||||||
break;
|
//case MonReqNone:
|
||||||
//case MonReqNone:
|
// copyPlex86StateToBochs(cpu);
|
||||||
// copyPlex86StateToBochs(cpu);
|
// return(0); /* All OK. */
|
||||||
// return(0); /* All OK. */
|
case MonReqGuestFault:
|
||||||
case MonReqGuestFault:
|
faultCount[ executeMsg.monitorState.guestFaultNo ]++;
|
||||||
faultCount[ executeMsg.monitorState.guestFaultNo ]++;
|
copyPlex86StateToBochs(cpu);
|
||||||
copyPlex86StateToBochs(cpu);
|
return(0); /* All OK. */
|
||||||
return(0); /* All OK. */
|
default:
|
||||||
default:
|
fprintf(stderr, "plex86: executeMsg.request = %u\n",
|
||||||
fprintf(stderr, "executeMsg.request = %u\n",
|
executeMsg.monitorState.request);
|
||||||
executeMsg.monitorState.request);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plex86TearDown();
|
plex86TearDown();
|
||||||
|
@ -1,47 +1,39 @@
|
|||||||
Fix monPrint and friends.
|
Fix monPrint and friends.
|
||||||
|
monpanic breaks up into 2 monprints which hit user space twice.
|
||||||
|
|
||||||
Could put the GDT/LDT in linear memory where the guest
|
Could put the GDT/LDT in linear memory where the guest
|
||||||
expect them.
|
expects them.
|
||||||
|
|
||||||
Synchronize page writes with iCache in bochs.
|
Synchronize page writes with iCache in bochs.
|
||||||
|
|
||||||
Deal with cycle counts of guest execution in VM, and in
|
Deal with cycle counts of guest execution in VM, and in
|
||||||
bochs/plex86 shim.
|
bochs/plex86 shim.
|
||||||
|
|
||||||
Make a host-null.c file to demonstrate/test the OS-specific
|
|
||||||
files that are needed for a host port.
|
|
||||||
|
|
||||||
Deal with page_usage. How do we update this between timeslices?
|
Deal with page_usage. How do we update this between timeslices?
|
||||||
Do we always clear it? Maybe we should keep a log of things to
|
Do we always clear it? Maybe we should keep a log of things to
|
||||||
clear (page_usage, GDT entries, PDE entries, ...) and clear those
|
clear (page_usage, GDT entries, PDE entries, ...) and clear those
|
||||||
before returning to user space.
|
before returning to user space.
|
||||||
|
|
||||||
monpanic breaks up into 2 monprints which hit user space twice.
|
GDT entries for guest need to be cleared upon return from guest
|
||||||
|
execution, or just cleared before invocation of the guest.
|
||||||
|
|
||||||
Task segment must be a 32-bit'er.
|
Task segment must be a 32-bit'er.
|
||||||
|
|
||||||
Save/restore floating point state of host/VM.
|
Save/restore floating point state of host/VM.
|
||||||
|
|
||||||
pack guest_cpu_t structure.
|
|
||||||
|
|
||||||
deduct off some cycles for the IRET/int sequence.
|
deduct off some cycles for the IRET/int sequence.
|
||||||
|
|
||||||
Delete use of vm->addr, and split print-nexus into parts so we can
|
Conditions for bochs compile using plex86:
|
||||||
use direct host or guest fields. I don't like having implicit
|
- Not compiled for debug
|
||||||
pointer usage.
|
- x86 host
|
||||||
|
|
||||||
Not compiled for debug
|
paging-mon.c: We can eliminate any code other than CPL==3.
|
||||||
Compiled for BX_SMP_PROCESSORS == 1
|
|
||||||
cpuid match
|
|
||||||
x86 host
|
|
||||||
|
|
||||||
monitor uses slots 1,2,3 so guest ring3 should not
|
Fix extra PDBR reload in nexus.S
|
||||||
use these slots.
|
|
||||||
|
|
||||||
FIX a20 in system fields.
|
|
||||||
FIX use of CPL in paging-mon.c. We can eliminate any
|
|
||||||
code other than CPL==3.
|
|
||||||
|
|
||||||
|
Manipulation/reading of host page tables needs to be SMP/preempt
|
||||||
|
compatible. Need to do spin-lock (big kernel lock for old Linux)
|
||||||
|
on vma.
|
||||||
|
|
||||||
==================== From previous plex86 TODO file ====================
|
==================== From previous plex86 TODO file ====================
|
||||||
|
|
||||||
@ -64,8 +56,6 @@ FIX use of CPL in paging-mon.c. We can eliminate any
|
|||||||
|
|
||||||
- Many performance enhancements (see PERFORMANCE)
|
- Many performance enhancements (see PERFORMANCE)
|
||||||
|
|
||||||
- Test and get more guests running; list in 'GUESTS'.
|
|
||||||
|
|
||||||
- Allow memory to be mapped anywhere in the physical address
|
- Allow memory to be mapped anywhere in the physical address
|
||||||
space.
|
space.
|
||||||
|
|
||||||
@ -80,17 +70,5 @@ FIX use of CPL in paging-mon.c. We can eliminate any
|
|||||||
- Deal with LDT
|
- Deal with LDT
|
||||||
|
|
||||||
|
|
||||||
Use monitor unmapped IO port handler rather than user space.
|
|
||||||
|
|
||||||
Get rid of VM message count instrumentation spew to kernel log
|
|
||||||
|
|
||||||
unallocVmPages/unreserve_guest_pages called twice,
|
unallocVmPages/unreserve_guest_pages called twice,
|
||||||
release & teardown.
|
release & teardown.
|
||||||
|
|
||||||
move mapMonitor to -host.c
|
|
||||||
|
|
||||||
Zero out GDT when remapped.
|
|
||||||
|
|
||||||
When is mapMonitor called?
|
|
||||||
|
|
||||||
Fix extra PDBR reload in nexus.S
|
|
||||||
|
@ -396,8 +396,8 @@ typedef struct {
|
|||||||
struct {
|
struct {
|
||||||
Bit64u t0; /* TSC before excecution of guest code */
|
Bit64u t0; /* TSC before excecution of guest code */
|
||||||
Bit64u cyclesElapsed; /* Cycles of guest execution */
|
Bit64u cyclesElapsed; /* Cycles of guest execution */
|
||||||
unsigned a20; /* address 20 line enabled */
|
unsigned a20Enable; /* A20 line enabled? */
|
||||||
Bit32u a20AddrMask; /* mask to apply to phy address */
|
Bit32u a20AddrMask; /* mask to apply to phy address */
|
||||||
Bit32u a20IndexMask; /* mask to apply to phy address */
|
Bit32u a20IndexMask; /* mask to apply to phy address */
|
||||||
} system;
|
} system;
|
||||||
|
|
||||||
@ -495,6 +495,14 @@ void mon_memzero(void *ptr, int size);
|
|||||||
void mon_memcpy(void *dst, void *src, int size);
|
void mon_memcpy(void *dst, void *src, int size);
|
||||||
void *mon_memset(void *s, unsigned c, unsigned n);
|
void *mon_memset(void *s, unsigned c, unsigned n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to set the monitor CS/DS base address so that the module pages,
|
||||||
|
* which are mapped starting at linear address 'laddr' into the guest address
|
||||||
|
* space, reside at the same offset relative to the monitor CS base as they
|
||||||
|
* reside relative to the kernel CS base in the host address space. This way,
|
||||||
|
* we can execute the (non-relocatable) module code within the guest address
|
||||||
|
* space ...
|
||||||
|
*/
|
||||||
#define MON_BASE_FROM_LADDR(laddr) \
|
#define MON_BASE_FROM_LADDR(laddr) \
|
||||||
((laddr) - monitor_pages.startOffsetPageAligned)
|
((laddr) - monitor_pages.startOffsetPageAligned)
|
||||||
|
|
||||||
@ -662,9 +670,6 @@ unsigned getMonPTi(vm_t *, unsigned pdi, unsigned source);
|
|||||||
#define CLI() asm volatile ("cli": : : "memory")
|
#define CLI() asm volatile ("cli": : : "memory")
|
||||||
#define STI() asm volatile ("sti": : : "memory")
|
#define STI() asm volatile ("sti": : : "memory")
|
||||||
|
|
||||||
extern const selector_t nullSelector;
|
|
||||||
extern const descriptor_t nullDescriptor;
|
|
||||||
|
|
||||||
#endif /* MONITOR Space. */
|
#endif /* MONITOR Space. */
|
||||||
|
|
||||||
#endif /* __MONITOR_H__ */
|
#endif /* __MONITOR_H__ */
|
||||||
|
@ -51,18 +51,6 @@ static void mapBlankPage(vm_t *vm, Bit32u *laddr_p, page_t *pageTable);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to set the monitor CS/DS base address so that the module pages,
|
|
||||||
* which are mapped starting at linear address 'laddr' into the guest address
|
|
||||||
* space, reside at the same offset relative to the monitor CS base as they
|
|
||||||
* reside relative to the kernel CS base in the host address space. This way,
|
|
||||||
* we can execute the (non-relocatable) module code within the guest address
|
|
||||||
* space ...
|
|
||||||
*/
|
|
||||||
#define MON_BASE_FROM_LADDR(laddr) \
|
|
||||||
((laddr) - monitor_pages.startOffsetPageAligned)
|
|
||||||
|
|
||||||
|
|
||||||
static const selector_t nullSelector = { raw: 0 };
|
static const selector_t nullSelector = { raw: 0 };
|
||||||
static const descriptor_t nullDescriptor = {
|
static const descriptor_t nullDescriptor = {
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@ -126,9 +114,9 @@ initMonitor(vm_t *vm)
|
|||||||
|
|
||||||
vm->kernel_offset = hostKernelOffset();
|
vm->kernel_offset = hostKernelOffset();
|
||||||
|
|
||||||
vm->system.a20 = 1; /* start with A20 line enabled */
|
vm->system.a20Enable = 1; /* Start with A20 line enabled. */
|
||||||
vm->system.a20AddrMask = 0xffffffff; /* all address lines contribute */
|
vm->system.a20AddrMask = 0xffffffff; /* All address lines contribute. */
|
||||||
vm->system.a20IndexMask = 0x000fffff; /* all address lines contribute */
|
vm->system.a20IndexMask = 0x000fffff; /* All address lines contribute. */
|
||||||
|
|
||||||
/* Initialize nexus */
|
/* Initialize nexus */
|
||||||
mon_memzero(vm->host.addr.nexus, 4096);
|
mon_memzero(vm->host.addr.nexus, 4096);
|
||||||
@ -778,7 +766,7 @@ ioctlGeneric(vm_t *vm, void *inode, void *filp,
|
|||||||
ret = ioctlExecute(vm, &executeMsg);
|
ret = ioctlExecute(vm, &executeMsg);
|
||||||
if ( hostCopyToUser((void *)arg, &executeMsg, sizeof(executeMsg)) )
|
if ( hostCopyToUser((void *)arg, &executeMsg, sizeof(executeMsg)) )
|
||||||
return -Plex86ErrnoEFAULT;
|
return -Plex86ErrnoEFAULT;
|
||||||
return ret; /* OK. */
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -803,11 +791,11 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
guest_context_t *guest_stack_context;
|
guest_context_t *guest_stack_context;
|
||||||
nexus_t *nexus;
|
nexus_t *nexus;
|
||||||
unsigned s;
|
unsigned s;
|
||||||
int retval = 100;
|
int retval;
|
||||||
|
|
||||||
if ( (vm->vmState != VMStateReady) ||
|
if ( (vm->vmState != VMStateReady) ||
|
||||||
(vm->mon_request != MonReqNone) ) {
|
(vm->mon_request != MonReqNone) ) {
|
||||||
retval = 1; /* Fail. */
|
retval = Plex86NoExecute_VMState; /* Fail. */
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,7 +805,7 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
* cosimulation.
|
* cosimulation.
|
||||||
*/
|
*/
|
||||||
if (executeMsg->executeMethod != Plex86ExecuteMethodNative) {
|
if (executeMsg->executeMethod != Plex86ExecuteMethodNative) {
|
||||||
retval = 2; /* Fail. */
|
retval = Plex86NoExecute_Method; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,7 +840,7 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
/* 0x8005003b */
|
/* 0x8005003b */
|
||||||
if ( (guest_cpu->cr0.raw & 0xe0000037) != 0x80000033 ) {
|
if ( (guest_cpu->cr0.raw & 0xe0000037) != 0x80000033 ) {
|
||||||
hostPrint("plex86: guest CR0=0x%x\n", guest_cpu->cr0.raw);
|
hostPrint("plex86: guest CR0=0x%x\n", guest_cpu->cr0.raw);
|
||||||
retval = 3; /* Fail. */
|
retval = Plex86NoExecute_CR0; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,7 +859,7 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
*/
|
*/
|
||||||
if ( (guest_cpu->cr4.raw & 0x000007ff) != 0x00000000 ) {
|
if ( (guest_cpu->cr4.raw & 0x000007ff) != 0x00000000 ) {
|
||||||
hostPrint("plex86: guest CR4=0x%x\n", guest_cpu->cr4.raw);
|
hostPrint("plex86: guest CR4=0x%x\n", guest_cpu->cr4.raw);
|
||||||
retval = 4; /* Fail. */
|
retval = Plex86NoExecute_CR4; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,16 +869,34 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
if ( (guest_cpu->sreg[SRegCS].sel.fields.rpl != 3) ||
|
if ( (guest_cpu->sreg[SRegCS].sel.fields.rpl != 3) ||
|
||||||
(guest_cpu->sreg[SRegCS].sel.fields.index == 0) ||
|
(guest_cpu->sreg[SRegCS].sel.fields.index == 0) ||
|
||||||
(guest_cpu->sreg[SRegCS].des.dpl != 3) ) {
|
(guest_cpu->sreg[SRegCS].des.dpl != 3) ) {
|
||||||
retval = 5; /* Fail. */
|
retval = Plex86NoExecute_CS; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A20 line must be enabled. */
|
/* A20 line must be enabled. */
|
||||||
if ( guest_cpu->a20Enable != 1 ) {
|
if ( guest_cpu->a20Enable != 1 ) {
|
||||||
retval = 6; /* Fail. */
|
retval = Plex86NoExecute_A20; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some code not really used now, since we only support A20 being enabled. */
|
||||||
|
{
|
||||||
|
unsigned newA20Enable;
|
||||||
|
newA20Enable = guest_cpu->a20Enable > 0; /* Make 0 or 1. */
|
||||||
|
if ( newA20Enable != vm->system.a20Enable ) {
|
||||||
|
if ( (!newA20Enable) && guest_cpu->cr0.fields.pg ) {
|
||||||
|
/* A20 disabled, paging on not supported. Well, really I have to
|
||||||
|
* see if it matters. This check was in old plex86 code.
|
||||||
|
*/
|
||||||
|
retval = Plex86NoExecute_A20; /* Fail. */
|
||||||
|
goto handleFail;
|
||||||
|
}
|
||||||
|
vm->system.a20Enable = newA20Enable;
|
||||||
|
vm->system.a20AddrMask = 0xffefffff | (newA20Enable << 20);
|
||||||
|
vm->system.a20IndexMask = 0x000ffeff | (newA20Enable << 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* LDT not supported.
|
/* LDT not supported.
|
||||||
* Monitor uses GDT slots 1,2,3, so guest segments can not.
|
* Monitor uses GDT slots 1,2,3, so guest segments can not.
|
||||||
* Segment descriptor cache DPL should equal 3.
|
* Segment descriptor cache DPL should equal 3.
|
||||||
@ -902,22 +908,22 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
if ( selector & 0xfffc ) {
|
if ( selector & 0xfffc ) {
|
||||||
if ( (selector & 0x0007) != 3 ) {
|
if ( (selector & 0x0007) != 3 ) {
|
||||||
/* Either TI=1 (LDT usage) or RPL!=3. */
|
/* Either TI=1 (LDT usage) or RPL!=3. */
|
||||||
retval = 7; /* Fail. */
|
retval = Plex86NoExecute_Selector; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
index = selector >> 3;
|
index = selector >> 3;
|
||||||
if ( index <= 3 ) {
|
if ( index <= 3 ) {
|
||||||
/* Selector index field uses one of the monitor GDT slots. */
|
/* Selector index field uses one of the monitor GDT slots. */
|
||||||
retval = 8; /* Fail. */
|
retval = Plex86NoExecute_Selector; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
if ( index >= (MON_GDT_SIZE/8) ) {
|
if ( index >= (MON_GDT_SIZE/8) ) {
|
||||||
/* Selector index field uses a slot beyond the monitor GDT size. */
|
/* Selector index field uses a slot beyond the monitor GDT size. */
|
||||||
retval = 9; /* Fail. */
|
retval = Plex86NoExecute_Selector; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
if ( guest_cpu->sreg[s].des.dpl != 3 ) {
|
if ( guest_cpu->sreg[s].des.dpl != 3 ) {
|
||||||
retval = 10; /* Fail. */
|
retval = Plex86NoExecute_DPL; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -935,7 +941,7 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
*/
|
*/
|
||||||
if ( (guest_cpu->eflags & (0x001b7302)) !=
|
if ( (guest_cpu->eflags & (0x001b7302)) !=
|
||||||
(0x00000202) ) {
|
(0x00000202) ) {
|
||||||
retval = 11; /* Fail. */
|
retval = Plex86NoExecute_EFlags; /* Fail. */
|
||||||
goto handleFail;
|
goto handleFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,7 +1037,7 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
if (!(eflags & 0x200)) {
|
if (!(eflags & 0x200)) {
|
||||||
vm_restore_flags(eflags);
|
vm_restore_flags(eflags);
|
||||||
hostPrint("ioctlExecute: EFLAGS.IF==0\n");
|
hostPrint("ioctlExecute: EFLAGS.IF==0\n");
|
||||||
retval = 12; /* Fail. */
|
retval = 101; /* Fail. */
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1062,17 +1068,17 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
else {
|
else {
|
||||||
hostPrint("mapMonitor failed.\n");
|
hostPrint("mapMonitor failed.\n");
|
||||||
hostPrint("Panic w/ abort_code=%u\n", vm->abort_code);
|
hostPrint("Panic w/ abort_code=%u\n", vm->abort_code);
|
||||||
retval = 100;
|
retval = 102;
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
hostPrint("ioctlExecute: case MonReqRemapMonitor.\n");
|
hostPrint("ioctlExecute: case MonReqRemapMonitor.\n");
|
||||||
retval = 13;
|
retval = 103;
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
|
|
||||||
case MonReqFlushPrintBuf:
|
case MonReqFlushPrintBuf:
|
||||||
hostPrint("ioctlExecute: case MonReqFlushPrintBuf.\n");
|
hostPrint("ioctlExecute: case MonReqFlushPrintBuf.\n");
|
||||||
retval = 14;
|
retval = 104;
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
|
|
||||||
case MonReqGuestFault:
|
case MonReqGuestFault:
|
||||||
@ -1084,18 +1090,18 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
executeMsg->monitorState.request = vm->mon_request;
|
executeMsg->monitorState.request = vm->mon_request;
|
||||||
executeMsg->monitorState.guestFaultNo = vm->guestFaultNo;
|
executeMsg->monitorState.guestFaultNo = vm->guestFaultNo;
|
||||||
vm->mon_request = MonReqNone;
|
vm->mon_request = MonReqNone;
|
||||||
return 15;
|
return 0;
|
||||||
|
|
||||||
case MonReqPanic:
|
case MonReqPanic:
|
||||||
if (vm->abort_code)
|
if (vm->abort_code)
|
||||||
hostPrint("Panic w/ abort_code=%u\n", vm->abort_code);
|
hostPrint("Panic w/ abort_code=%u\n", vm->abort_code);
|
||||||
hostPrint("ioctlExecute: case MonReqPanic.\n");
|
hostPrint("ioctlExecute: case MonReqPanic.\n");
|
||||||
retval = 16;
|
retval = 106;
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hostPrint("ioctlExecute: default case (%u).\n", vm->mon_request);
|
hostPrint("ioctlExecute: default case (%u).\n", vm->mon_request);
|
||||||
retval = 17;
|
retval = 107;
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1112,7 +1118,7 @@ ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Should not get here. */
|
/* Should not get here. */
|
||||||
retval = 100;
|
retval = 108;
|
||||||
goto handlePanic;
|
goto handlePanic;
|
||||||
|
|
||||||
handleFail:
|
handleFail:
|
||||||
@ -1275,40 +1281,11 @@ hostPrint("plex86: vm_t size is %u\n", sizeof(vm_t));
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
int
|
|
||||||
ioctlSetA20E(vm_t *vm, unsigned long val)
|
|
||||||
{
|
|
||||||
unsigned prev_a20;
|
|
||||||
|
|
||||||
if ( !val && vm->host.addr.guest_cpu->cr0.fields.pg ) {
|
|
||||||
/* Disabling the A20 line with paging on, is not
|
|
||||||
* currently handled.
|
|
||||||
*/
|
|
||||||
xxxprint(vm, "SetA20E: val=0, CR0.PG=1 unhandled\n");
|
|
||||||
return 0; /* fail */
|
|
||||||
}
|
|
||||||
val = (val > 0); /* make 0 or 1 */
|
|
||||||
prev_a20 = vm->system.a20;
|
|
||||||
|
|
||||||
vm->system.a20 = val;
|
|
||||||
vm->system.a20AddrMask = 0xffefffff | (val << 20);
|
|
||||||
vm->system.a20IndexMask = 0x000ffeff | (val << 8);
|
|
||||||
|
|
||||||
if ( prev_a20 != vm->system.a20 ) {
|
|
||||||
/* change in A20 line enable status */
|
|
||||||
vm->modeChange |= ModeChangeEventPaging | ModeChangeRequestPaging;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
/* */
|
* Allocate various pages/memory needed by monitor.
|
||||||
/* Allocate various pages/memory needed by monitor */
|
*/
|
||||||
/* */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
allocVmPages( vm_t *vm, unsigned nmegs )
|
allocVmPages( vm_t *vm, unsigned nmegs )
|
||||||
@ -1696,17 +1673,6 @@ initShadowPaging(vm_t *vm)
|
|||||||
/* Update vpaging timestamp. */
|
/* Update vpaging timestamp. */
|
||||||
vm->vpaging_tsc = vm_rdtsc();
|
vm->vpaging_tsc = vm_rdtsc();
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Flush TLB cache. */
|
|
||||||
asm volatile (
|
|
||||||
"movl %%cr3, %%eax\n\t"
|
|
||||||
"movl %%eax, %%cr3"
|
|
||||||
: /* no outputs */
|
|
||||||
: /* no inputs */
|
|
||||||
: "eax", "memory" /* modified */
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* When we remap the monitor page tables, IF guest paging is
|
/* When we remap the monitor page tables, IF guest paging is
|
||||||
* enabled, then mark the page containing the guest page directory
|
* enabled, then mark the page containing the guest page directory
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
* $Id: plex86.h,v 1.2 2003-01-02 01:08:43 kevinlawton Exp $
|
* $Id: plex86.h,v 1.3 2003-01-02 17:05:06 kevinlawton Exp $
|
||||||
************************************************************************
|
************************************************************************
|
||||||
*
|
*
|
||||||
* plex86: run multiple x86 operating systems concurrently
|
* plex86: run multiple x86 operating systems concurrently
|
||||||
@ -33,7 +33,7 @@ typedef struct {
|
|||||||
selector_t sel;
|
selector_t sel;
|
||||||
descriptor_t des;
|
descriptor_t des;
|
||||||
unsigned valid;
|
unsigned valid;
|
||||||
} guest_sreg_t;
|
} __attribute__ ((packed)) guest_sreg_t;
|
||||||
|
|
||||||
#define SRegES 0
|
#define SRegES 0
|
||||||
#define SRegCS 1
|
#define SRegCS 1
|
||||||
@ -120,7 +120,7 @@ typedef struct {
|
|||||||
Bit32u Reserved31_25:7;
|
Bit32u Reserved31_25:7;
|
||||||
} __attribute__ ((packed)) fields;
|
} __attribute__ ((packed)) fields;
|
||||||
} __attribute__ ((packed)) featureFlags;
|
} __attribute__ ((packed)) featureFlags;
|
||||||
} cpuid_info_t;
|
} __attribute__ ((packed)) cpuid_info_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Bit32u edi;
|
Bit32u edi;
|
||||||
@ -145,7 +145,7 @@ typedef struct {
|
|||||||
Bit32u cr1, cr2, cr3;
|
Bit32u cr1, cr2, cr3;
|
||||||
cr4_t cr4;
|
cr4_t cr4;
|
||||||
unsigned a20Enable;
|
unsigned a20Enable;
|
||||||
} guest_cpu_t;
|
} __attribute__ ((packed)) guest_cpu_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -175,6 +175,18 @@ typedef struct {
|
|||||||
#define PLEX86_CPUID 0x6b06
|
#define PLEX86_CPUID 0x6b06
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Reasons why plex86 could not execute the guest context in the VM. */
|
||||||
|
#define Plex86NoExecute_Method 1
|
||||||
|
#define Plex86NoExecute_CR0 2
|
||||||
|
#define Plex86NoExecute_CR4 3
|
||||||
|
#define Plex86NoExecute_CS 4
|
||||||
|
#define Plex86NoExecute_A20 5
|
||||||
|
#define Plex86NoExecute_Selector 6
|
||||||
|
#define Plex86NoExecute_DPL 7
|
||||||
|
#define Plex86NoExecute_EFlags 8
|
||||||
|
#define Plex86NoExecute_Panic 9
|
||||||
|
#define Plex86NoExecute_VMState 10
|
||||||
|
|
||||||
|
|
||||||
/* Requests that the VM monitor makes to host-kernel space or
|
/* Requests that the VM monitor makes to host-kernel space or
|
||||||
* host-user space.
|
* host-user space.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user