More code cleanups.

This commit is contained in:
Kevin Lawton 2003-01-02 17:05:47 +00:00
parent 31a4a389a1
commit ae92b55818
5 changed files with 164 additions and 167 deletions

View File

@ -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();

View File

@ -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

View File

@ -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__ */

View File

@ -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

View File

@ -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.