*** kernel/host-nt.c Wed Dec 31 14:00:00 1969 --- kernel/host-nt.c Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,794 ---- + /* + * plex86: run multiple x86 operating systems concurrently + * Copyright (C) 1999-2000 Kevin P. Lawton + * + * host-nt.c: Windows NT specific VM host driver functionality + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + // Named type in parenthesis + #pragma warning(disable:4115) + // Nonstandard extension warning: bitfield types other than int + #pragma warning(disable:4214) + // Nonstandard extension warning: nameless struct/union + #pragma warning(disable:4201) + // Unused inline function removed warning + #pragma warning(disable:4514) + + #include <ddk\ntddk.h> + + /************************************************************************/ + /* Declarations */ + /************************************************************************/ + + /* The kernel segment base */ + #define KERNEL_OFFSET 0x80000000 + #define PAGE_OFFSET 0x80000000 + + // NT device name + #define PLEX86_DEVICE_NAME L"\\Device\\PLEX86" + + // DOS device name + #define DOS_PLEX86_DEVICE_NAME L"\\DosDevices\\PLEX86" + + // Define the various device type values. Note that values used by Microsoft + // Corporation are in the range 0-32767, and 32768-65535 are reserved for use + // by customers. + // IOCTL interface definitions + // Device type -- in the "User Defined" range." + #define PLEX86_TYPE 0x00008000 + + // driver local data structure specific to each device object + typedef struct _PLEX86_EXTENSION + { + PDEVICE_OBJECT deviceObject; // The PLEX86 device object. + + } PLEX86_EXTENSION, *PPLEX86_EXTENSION; + + typedef unsigned long Bit32u; + + /************************************************************************/ + /* Structures / Variables */ + /************************************************************************/ + + NTSTATUS NTAPI DriverEntry ( IN PDRIVER_OBJECT pDriverObject, + IN PUNICODE_STRING registryPath ); + + NTSTATUS NTAPI PLEX86Dispatch ( IN PDEVICE_OBJECT pDO, + IN PIRP pIORequestPacket ); + + NTSTATUS NTAPI PLEX86ReadPort ( IN PPLEX86_EXTENSION pLDI, + IN PIRP pIORequestPacket, + IN PIO_STACK_LOCATION pIrpStack ); + + VOID NTAPI PLEX86Unload ( IN PDRIVER_OBJECT pDriverObject ); + + extern int __stdcall nt_driver_startup( void ); + + extern int __stdcall nt_driver_dispatch + ( + unsigned uCommand, + void* pvParameter, + int* pnRetSize, + void* pvFileData + ); + + extern void* __stdcall nt_driver_open( void ); + extern void __stdcall nt_driver_close( void* pvParam ); + + extern int __stdcall retrieve_monitor_pages(void); + + #if defined( DBG ) + #define PLEX86KdPrint(x) DbgPrint x + #define printk DbgPrint + #else + #define PLEX86KdPrint(x) + #define printk + #endif + + #define KERN_WARNING "Warning: " + + #define MON_HOST_DECL __stdcall + + /************************************************************************/ + /* Main kernel module code */ + /************************************************************************/ + + /////////////////////////////////////////////////////////////////////////////// + + NTSTATUS + NTAPI + DriverEntry( + IN PDRIVER_OBJECT driverObject, + IN PUNICODE_STRING registryPath ) + + /* + + Routine Description: + This routine is the entry point for the driver. It is responsible + for setting the dispatch entry points in the driver object and creating + the device object. Any resources such as ports, interrupts and DMA + channels used must be reported. A symbolic link must be created between + the device name and an entry in \DosDevices in order to allow Win32 + applications to open the device. + + Arguments: + + driverObject - Pointer to driver object created by the system. + + Return Value: + + STATUS_SUCCESS if the driver initialized correctly, otherwise an error + indicating the reason for failure. + + */ + + { + PDEVICE_OBJECT deviceObject = NULL; + + // NT Device Name + WCHAR deviceNameBuffer[] = PLEX86_DEVICE_NAME; + UNICODE_STRING deviceNameUnicodeString; + + // DOS-Win32 Device Link + WCHAR deviceLinkBuffer[] = DOS_PLEX86_DEVICE_NAME; + UNICODE_STRING deviceLinkUnicodeString; + + PLEX86_EXTENSION *extension; // Device extension + + BOOLEAN result; + NTSTATUS status; + + registryPath = registryPath; + + // Initialize the driver object dispatch table. + // NT sends requests to these routines. + + driverObject->MajorFunction[IRP_MJ_CREATE] = PLEX86Dispatch; + driverObject->MajorFunction[IRP_MJ_CLOSE] = PLEX86Dispatch; + driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PLEX86Dispatch; + driverObject->DriverUnload = PLEX86Unload; + + PLEX86KdPrint (("plex86.sys: In DriverEntry\n")); + + RtlInitUnicodeString (&deviceNameUnicodeString, + deviceNameBuffer); + + status = IoCreateDevice( driverObject, + sizeof(PLEX86_EXTENSION), + &deviceNameUnicodeString, + PLEX86_TYPE, + 0, + FALSE, + &deviceObject ); + + + if (NT_SUCCESS(status)) + { + + // Create a symbolic link, e.g. a name that a Win32 app can specify + // to open the device + RtlInitUnicodeString( &deviceLinkUnicodeString, + deviceLinkBuffer ); + + status = IoCreateSymbolicLink( &deviceLinkUnicodeString, + &deviceNameUnicodeString ); + + if (!NT_SUCCESS(status)) // failed to create symbolic link + { + // Symbolic link creation failed- note this & then delete the + // device object (it's useless if a Win32 app can't get at it). + + printk("plex86.sys: IoCreateSymbolicLink failed\n"); + + IoDeleteDevice (deviceObject); + } + else // else create symbolic link successful + { + // Clear local device extension memory + RtlZeroMemory(deviceObject->DeviceExtension, + sizeof(PLEX86_EXTENSION)); + + if ( !nt_driver_startup() ) goto fail_startup; + + extension = deviceObject->DeviceExtension; + extension->deviceObject = deviceObject; + } + } + else // create device failed + { + printk("plex86.sys: IoCreateDevice failed\n"); + status = STATUS_UNSUCCESSFUL; + } + + return status; + + fail_startup: + + IoDeleteSymbolicLink( &deviceLinkUnicodeString ); + IoDeleteDevice(deviceObject); + + return STATUS_UNSUCCESSFUL; + + } + + NTSTATUS NTAPI + PLEX86Dispatch( + IN PDEVICE_OBJECT pDeviceObject, + IN PIRP pIORequestPacket ) + + /* + + Routine Description: + This routine is the dispatch handler for the driver. It is responsible + for processing the IRPs. + + Arguments: + + pDeviceObject - Pointer to device object. + + pIORequestPacket - Pointer to the current IRP. (I/O request packet) + created by the I/O mamager as result of request to do + read/write/IOCTL + + + Return Value: + + STATUS_SUCCESS if the IRP was processed successfully, otherwise an error + indicating the reason for failure. + + */ + + { + PPLEX86_EXTENSION extension; + PIO_STACK_LOCATION pIORequestPacketStack; + NTSTATUS status; + + // Initialize the I/O request packet info field. + // This is used to return the number of bytes transfered. + + pIORequestPacket->IoStatus.Information = 0; + + // get the device extension + extension = (PPLEX86_EXTENSION)pDeviceObject->DeviceExtension; + + pIORequestPacketStack = IoGetCurrentIrpStackLocation(pIORequestPacket); + + // Set default return status + status = STATUS_NOT_IMPLEMENTED; + + // Dispatch based on major fcn code. + + switch (pIORequestPacketStack->MajorFunction) + { + case IRP_MJ_CREATE: + printk("plex86.sys: Dispatching IRP_MJ_CREATE (FileObject=0x0)\n", + pIORequestPacketStack->FileObject); + + if ( pIORequestPacketStack->FileObject != NULL ) + { + pIORequestPacketStack->FileObject->FsContext = nt_driver_open(); + + if ( pIORequestPacketStack->FileObject->FsContext != NULL ) + { + status = STATUS_SUCCESS; + } + else + { + status = STATUS_NO_MEMORY; + } + } + else + { + status = STATUS_INVALID_PARAMETER; + } + break; + + case IRP_MJ_CLOSE: + printk("plex86.sys: Dispatching IRP_MJ_CLOSE (FileObject=0x0)\n", + pIORequestPacketStack->FileObject); + + if ( pIORequestPacketStack->FileObject != NULL ) + { + nt_driver_close( pIORequestPacketStack->FileObject->FsContext ); + pIORequestPacketStack->FileObject->FsContext = NULL; + + status = STATUS_SUCCESS; + } + else + { + status = STATUS_INVALID_PARAMETER; + } + break; + + case IRP_MJ_DEVICE_CONTROL: + + if ( pIORequestPacketStack->FileObject != NULL ) + { + int nRetSize; + + if ( nt_driver_dispatch( pIORequestPacketStack->Parameters.DeviceIoControl.IoControlCode, + pIORequestPacket->AssociatedIrp.SystemBuffer, + &nRetSize, + pIORequestPacketStack->FileObject->FsContext ) ) + { + pIORequestPacket->IoStatus.Information = nRetSize; + status = STATUS_SUCCESS; + } + else + { + status = STATUS_UNSUCCESSFUL; + } + } + else + { + status = STATUS_UNSUCCESSFUL; + } + break; + + + default: + break; + } + + // We're done with I/O request. Record the status of the I/O action. + pIORequestPacket->IoStatus.Status = status; + + // Don't boost priority when returning since this took little time. + IoCompleteRequest(pIORequestPacket, IO_NO_INCREMENT ); + + return status; + } + + /////////////////////////////////////////////////////////////////////////////// + + + VOID NTAPI + PLEX86Unload( PDRIVER_OBJECT pDriverObject ) + /* + + Routine Description: + This routine prepares our driver to be unloaded. It is responsible + for freeing all resources allocated by DriverEntry as well as any + allocated while the driver was running. The symbolic link must be + deleted as well. + + Arguments: + + driverObject - Pointer to driver object created by the system. + + Return Value: + + None + */ + + { + PPLEX86_EXTENSION extension; + CM_RESOURCE_LIST NullresourceList; + BOOLEAN resourceConflict; + UNICODE_STRING Win32DeviceName; + + // Find our global data + extension = (PPLEX86_EXTENSION)pDriverObject->DeviceObject->DeviceExtension; + + PLEX86KdPrint (("plex86.sys: Unloading driver\n")); + + RtlInitUnicodeString(&Win32DeviceName, DOS_PLEX86_DEVICE_NAME); + + IoDeleteSymbolicLink(&Win32DeviceName); + + IoDeleteDevice(extension->deviceObject); + } + + // SystemModuleInformation (11) + typedef + struct _SYSTEM_MODULE_ENTRY + { + ULONG Unused; + ULONG Always0; + ULONG ModuleBaseAddress; + ULONG ModuleSize; + ULONG Unknown; + ULONG ModuleEntryIndex; + USHORT ModuleNameLength; /* Length of module name not including the path, this field contains valid value only for NTOSKRNL module*/ + USHORT ModulePathLength; /* Length of 'directory path' part of modulename*/ + CHAR ModuleName [256]; + + } SYSTEM_MODULE_ENTRY, * PSYSTEM_MODULE_ENTRY; + + typedef + struct _SYSTEM_MODULE_INFORMATION + { + ULONG Count; + SYSTEM_MODULE_ENTRY Module [1]; + + } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + + extern NTSTATUS + __stdcall + ZwQuerySystemInformation( + IN ULONG SystemInformationClass, + OUT PVOID SystemInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + /* + Parameters: + ModuleName - module name; for instance, "win32k.sys" + pulModuleSize - Pointer to ULONG that returns module size + + returns: + module base address + */ + + void* __stdcall FindModule + ( + const char* ModuleName, + unsigned long* pulModuleSize + ) + { + NTSTATUS Status = STATUS_SUCCESS; + PSYSTEM_MODULE_INFORMATION pInfo = NULL; + LONG Length = 0; + int Index; + int ModNameLen = strlen( ModuleName ); + PVOID pRet = NULL; + + /* + * Obtain required buffer size + */ + + Status = ZwQuerySystemInformation + ( + 11, + &pInfo, + 0, /* query size */ + ( PULONG )&Length + ); + + if (STATUS_INFO_LENGTH_MISMATCH == Status) + { + /* + * Allocate buffer + */ + pInfo = ExAllocatePool(NonPagedPool, Length); + + if (NULL == pInfo) + { + return NULL; + } + + RtlZeroMemory( pInfo, Length ); + } + else + { + return NULL; + } + + Status = ZwQuerySystemInformation + ( + 11, + pInfo, + Length, + ( PULONG )&Length + ); + + if (!NT_SUCCESS(Status)) + { + return NULL; + } + + for ( Index = 0; !pRet && (Index < (int) pInfo->Count); Index++ ) + { + int nLen = strlen( pInfo->Module[Index].ModuleName ); + + if ( nLen >= ModNameLen ) + { + LPSTR pszName = pInfo->Module[Index].ModuleName + (nLen - ModNameLen); + + if ( !_strnicmp( pszName, ModuleName, 10 ) ) + { + pRet = ( void* )pInfo->Module[Index].ModuleBaseAddress; + + if ( pulModuleSize != NULL ) + { + *pulModuleSize = pInfo->Module[Index].ModuleSize; + } + } + } + } + + ExFreePool( pInfo ); + + return pRet; + } + + /************************************************************************/ + /* Miscellaneous callbacks */ + /************************************************************************/ + + unsigned MON_HOST_DECL + host_idle(void) + { + // NT will preempt threads even in Kernel mode. Presumably + // this should always be FALSE. + + return 0; + } + + void * MON_HOST_DECL + host_alloc(unsigned long size) + { + void* pvRet; + + /* + * XXX - it wants this page-aligned apparently. + */ + + if ( size < PAGE_SIZE ) + size = PAGE_SIZE; + + pvRet = ExAllocatePool( NonPagedPool, size ); + + // printk( "plex86.sys: host_alloc(0x0) returns 0x0 (0x0)\n", + // size, + // pvRet, + // ( void* )( Bit32u )MmGetPhysicalAddress( pvRet ).QuadPart ); + + return pvRet; + } + + void MON_HOST_DECL + host_free(void *ptr) + { + // printk( "plex86.sys: host_free(0x0)\n", ptr ); + + ExFreePool( ptr ); + } + + /* + unsigned MON_HOST_DECL + host_map(Bit32u *page, int max_pages, void *ptr, unsigned size) + { + PMDL pMemMDL; + unsigned nRet = 0; + int nPage; + int nPageCount = ( size / PAGE_SIZE ) + ( ( size % PAGE_SIZE ) ? 1 : 0 ); + + if ( nPageCount > max_pages ) nPageCount = max_pages; + + printk( "plex86.sys: host_map(0x0,0x0) (nPageCount=0)\n", ptr, size, nPageCount ); + + pMemMDL = IoAllocateMdl( ptr, + size, + TRUE, + FALSE, + NULL ); + + if ( pMemMDL != NULL ) + { + PPFN_NUMBER pPfnArray; + + MmBuildMdlForNonPagedPool( pMemMDL ); + + pPfnArray = MmGetMdlPfnArray( pMemMDL ); + + if ( pPfnArray != NULL ) + { + for ( nPage = 0; nPage < nPageCount; nPage++ ) + { + printk( " page[0] = 0x0\n", nPage, pPfnArray[ nPage ] ); + page[ nPage ] = pPfnArray[ nPage ]; + } + + nRet = ( unsigned )nPageCount; + } + + IoFreeMdl( pMemMDL ); + } + + return nRet; + } + */ + + void * MON_HOST_DECL + host_alloc_page(void) + { + void* pvRet = NULL; + + /* We rely on the fact that allocations >= PAGE_SIZE are page aligned */ + pvRet = ExAllocatePool( NonPagedPool, PAGE_SIZE ); + + // printk( "plex86.sys: host_alloc_page() returns 0x0\n", pvRet ); + + return pvRet; + } + + void MON_HOST_DECL + host_free_page(void *ptr) + { + // printk( "plex86.sys: host_free_page(0x0)\n", ptr ); + + ExFreePool( ptr ); + } + + Bit32u MON_HOST_DECL + host_map_page(void *ptr) + { + Bit32u uRet = 0; + + if ( ptr != NULL ) + { + uRet = ( Bit32u )(MmGetPhysicalAddress(ptr).QuadPart) >> PAGE_SHIFT; + } + + // printk( "plex86.sys: host_map_page(0x0) returns 0x0\n", uRet ); + + return uRet; + } + + typedef void* vm_t; + + void __cdecl + doit_up(vm_t *vm) + { + printk(KERN_WARNING "Humm, host had IF=0\n"); + } + + + void __cdecl + doit2(void) + { + printk(KERN_WARNING "doit2\n"); + } + + void __cdecl + host_oh_crap(vm_t *vm) + { + printk(KERN_WARNING "Oh Crap!\n"); + } + + int __stdcall map_memory_to_user + ( + void* pvKernelPtr, + void** ppvUserPtr, + void** ppvMDL, + long lLength + ) + { + printk( "plex86.sys: map_memory_to_user(0x0,0x0,0x0,0)\n", + pvKernelPtr, ppvUserPtr, ppvMDL, lLength ); + + if ( *ppvMDL != NULL ) + { + printk( "plex86.sys: Second mmap of memory!\n" ); + return 0; + } + + *ppvMDL = IoAllocateMdl( pvKernelPtr, + lLength, + TRUE, + FALSE, + NULL ); + + if ( *ppvMDL == NULL ) + { + printk( "plex86.sys: Failed to allocate MDL for memory\n" ); + return 0; + } + + MmBuildMdlForNonPagedPool( ( PMDL )*ppvMDL ); + + // MmProbeAndLockPages( ( PMDL )*ppvMDL, + // UserMode, + // IoWriteAccess ); + + *ppvUserPtr = MmMapLockedPages( ( PMDL )*ppvMDL, + UserMode ); + + if ( !*ppvUserPtr ) + { + printk( "plex86.sys: Failed to map memory!\n" ); + return 0; + } + + printk( "plex86.sys: Mapped kernel memory 0x0 (0 bytes) to user address 0x0\n", + pvKernelPtr, + lLength, + *ppvUserPtr ); + + return 1; + } + + void __stdcall unmap_memory_from_user + ( + void** ppvUserPtr, + void** ppvMDL + ) + { + MmUnmapLockedPages( *ppvUserPtr, + ( PMDL )*ppvMDL ); + *ppvUserPtr = NULL; + + IoFreeMdl( ( PMDL )*ppvMDL ); + *ppvMDL = NULL; + } + + unsigned MON_HOST_DECL + retrieve_phy_pages(Bit32u *page, int max_pages, void *addr, unsigned size) + { + Bit32u start_addr = (Bit32u)addr & ~(PAGE_SIZE-1); + int n_pages; + int i; + + // printk( "plex86.sys: retrieve_phy_pages(0x0,0,0x0,0)\n", + // page, max_pages, addr, size ); + + if (!addr) + { + printk("plex86: retrieve_phy_pages: addr NULL!\n"); + return 0; + } + + if ( (unsigned long)addr & 0xfff) + { + printk("plex86: retrieve_phy_pages: address not aligned!\n"); + return 0; + } + + if ( size > ( unsigned )(max_pages * PAGE_SIZE) ) + { + printk("plex86: retrieve_phy_pages: not enough pages!\n"); + return 0; + } + + n_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + + if (n_pages > max_pages) + { + printk( "plex86.sys: retrieve_phy_pages: page list too small\n" ); + return 0; + } + + for ( i = 0; i < n_pages; i++ ) + { + page[ i ] = ( ( Bit32u )MmGetPhysicalAddress( ( void* )start_addr ).QuadPart >> PAGE_SHIFT ); + // printk( " page[0] = 0x0\n", i, page[i] ); + start_addr += PAGE_SIZE; + } + + return n_pages; + } + + static KIRQL s_nPreviousIRQL; + + void MON_HOST_DECL + host_premon_irql_hack(void) + { + KeRaiseIrql( HIGH_LEVEL, &s_nPreviousIRQL ); + + printk( "plex86.sys: KeRaiseIrql, previous IRQL was 0\n", s_nPreviousIRQL ); + } + + void MON_HOST_DECL + host_postmon_irql_hack(void) + { + KeLowerIrql( s_nPreviousIRQL ); + + printk( "plex86.sys: KeLowerIrql\n" ); + } + *** kernel/host-nt2.c Wed Dec 31 14:00:00 1969 --- kernel/host-nt2.c Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,609 ---- + /* + * plex86: run multiple x86 operating systems concurrently + * Copyright (C) 1999-2000 Kevin P. Lawton + * + * host-nt.c: Windows NT specific VM host driver functionality + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + #include "plex86.h" + + #define IN_HOST_SPACE + #include "monitor.h" + + #include <stdlib.h> + + /************************************************************************/ + /* Declarations */ + /************************************************************************/ + + /* The kernel segment base */ + #define KERNEL_OFFSET 0x80000000 + #define PAGE_SIZE 4096 + + #if !defined( UNREFERENCED_PARAMETER ) + #define UNREFERENCED_PARAMETER(x) x=x; + #endif + + monitor_pages_t monitor_pages; + extern unsigned redir_cnt[256]; + + /* NT kernel debugger output */ + extern unsigned DbgPrint( const char* Format, ... ); + + #define printk DbgPrint + + extern int __stdcall retrieve_monitor_pages(void); + + extern int __stdcall map_memory_to_user + ( + void* pvKernelPtr, + void** ppvUserPtr, + void** ppvMDL, + long lLength + ); + + extern int __stdcall unmap_memory_from_user + ( + void** ppvUserPtr, + void** ppvMDL + ); + + extern void* __stdcall FindModule + ( + const char* ModuleName, + unsigned long* pulModuleSize + ); + + extern unsigned MON_HOST_DECL retrieve_phy_pages + (Bit32u *page, int max_pages, void *addr, unsigned size); + + int __stdcall nt_driver_startup( void ) + { + /* clear uninitialised structures */ + zero_memory( redir_cnt, sizeof(redir_cnt) ); + zero_memory( &monitor_pages, sizeof(monitor_pages) ); + + /* retrieve the monitor physical pages */ + if (!retrieve_monitor_pages()) + { + printk("plex86.sys: retrieve_monitor_pages failed\n"); + return 0; + } + + printk( "plex86.sys: before get_cpu_capabilities\n" ); + + if ( !get_cpu_capabilities() ) + { + printk("plex86.sys: get_cpu_capabilities failed\n"); + return 0; + } + + printk( "plex86.sys: ptype:0, family:0, model:0 stepping:0\n", + cpuid_info.procSignature.fields.procType, + cpuid_info.procSignature.fields.family, + cpuid_info.procSignature.fields.model, + cpuid_info.procSignature.fields.stepping ); + + return 1; + } + + void* __stdcall nt_driver_open( void ) + { + vm_t* vm = ( vm_t* )host_alloc( sizeof(vm_t) ); + + if ( vm != NULL ) + { + zero_memory( vm, sizeof(vm_t) ); + + vm->prescanDepth = PrescanDepthDefault; + vm->mon_state = MON_STATE_UNINITIALIZED; + + printk( "plex86.sys: Allocated a vm_t at 0x0\n", vm ); + } + + return vm; + } + + void __stdcall nt_driver_close( void* pvParam ) + { + vm_t* vm = ( vm_t* )pvParam; + + if ( vm != NULL ) + { + host_free( vm ); + } + } + + int __stdcall nt_driver_dispatch + ( + unsigned uCommand, + void* pvParameter, + int* pnRetSize, + void* pvFileData + ) + { + vm_t* vm = ( vm_t* )pvFileData; + int nRet = 1; + + // printk( "plex86.sys: nt_driver_dispatch(0x0,0x0,0x0,0x0)\n", + // uCommand, pvParameter, pnRetSize, pvFileData ); + + if ( !vm ) + { + printk("plex86.sys: Dispatching ioctl with NULL vm!\n"); + + return 0; + } + + *pnRetSize = 0; + + switch ( uCommand ) + { + case PLEX86_ALLOCVPHYS: + { + guest_cpu_t guest_cpu; + unsigned long arg = *( unsigned long* )pvParameter; + int error; + + printk( "plex86.sys: In PLEX86_ALLOCVPHYS\n" ); + + /* Do not allow duplicate allocation */ + if ( (vm->mon_state != MON_STATE_UNINITIALIZED) || + (vm->pages.guest_n_megs != 0) ) + { + nRet = 0; + break; + } + + /* Check that the amount of memory is reasonable */ + if ( ( arg > PLEX86_MAX_PHY_MEGS ) || + ( arg < 4 ) || + ( ( arg & ~0x3) != arg ) ) + { + nRet = 0; + break; + } + + if ( (error = alloc_vm_pages(vm, arg)) != 0 ) + { + printk( "plex86: alloc_vm_pages failed at 0\n", + error ); + nRet = 0; + break; + } + + /* Mark guest pages as reserved (for mmap()) */ + //reserve_guest_pages( vm ); + + /* Initialize the guests physical memory. */ + if ( init_guest_phy_mem(vm) ) + { + //unreserve_guest_pages(vm); + unalloc_vm_pages(vm); + + nRet = 0; + break; + } + + get_cpu_reset_values(&guest_cpu); + + /* Initialize the monitor */ + printk("cpu.cr0 = 0x0\n", guest_cpu.cr0); + if ( !init_monitor(vm, KERNEL_OFFSET, 0, &guest_cpu) || + !setGuestCPU(vm, 0, &guest_cpu) || + !mapMonitor(vm, guest_cpu.eflags,0) ) + { + // unreserve_guest_pages(vm); + unalloc_vm_pages(vm); + nRet = 0; + break; + } + + break; + } + + case PLEX86_TEARDOWN: + unalloc_vm_pages( vm ); + break; + + case PLEX86_ALLOCINT: + { + // unsigned long arg = *( unsigned long* )pvParameter; + + /* TODO: Is this stuff still used? */ + nRet = 0; + + /* Check that we allocate a valid interrupt */ + // if (arg < 256) + // status = STATUS_SUCCESS; + + /* Allocate the interrupt */ + // BMAP_SET(vm->host_fwd_ints, arg); + break; + } + + case PLEX86_RELEASEINT: + { + // unsigned long arg = *( unsigned long* )pvParameter; + + /* TODO: Is this stuff still used? */ + nRet = 0; + + /* Check that we allocate a valid interrupt */ + // if (arg < 256) + // status = STATUS_SUCCESS; + + /* Allocate the interrupt */ + // BMAP_SET(vm->host_fwd_ints, arg); + break; + } + + case PLEX86_PRESCANDEPTH: + { + unsigned long arg = *( unsigned long* )pvParameter; + + if ( (arg < PrescanDepthMin) || (arg > PrescanDepthMax) ) + { + printk("plex86: Requested prescan depth 0" + " out of range [0..0]\n", arg, PrescanDepthMin, PrescanDepthMax); + nRet = 0; + break; + } + vm->prescanDepth = arg; + break; + } + + /* + * Set or clear the INTR line + */ + + case PLEX86_SETINTR: + { + unsigned long arg = *( unsigned long* )pvParameter; + + ioctlSetIntr(vm, arg); + break; + } + + case PLEX86_MESSAGEQ: + { + vm_messages_t* msg = ( vm_messages_t* )pvParameter; + + printk( "plex86.sys: In PLEX86_MESSAGEQ (0x0)\n", PLEX86_MESSAGEQ ); + + if (vm->mon_state != MON_STATE_RUNNABLE) + { + printk( "plex86.sys: ** Monitor state is not runnable\n" ); + nRet = 0; + break; + } + + printk( "plex86.sys: msg->header.msg_len = 0\n", msg->header.msg_len ); + printk( "plex86.sys: msg->header.msg_type = 0\n", msg->header.msg_type ); + + if ( (msg->header.msg_len + sizeof(msg->header)) > sizeof(vm_messages_t)) + { + printk( "plex86.sys: ** Message is too big\n" ); + nRet = 0; + break; + } + + #if 1 + #warning "deal with LDT 0s and 0.000000s that the NT kernel uses" + /* XXXX */ + // __asm("movl $0, 0.000000e+00ax"); + // __asm("movl 0.000000e+00ax, 0s"); + // __asm("movl 0.000000e+00ax, 0.000000s"); + + if (ioctlMessageQ(vm, msg)) + { + printk("plex86: ioctlMessageQ failed\n"); + nRet = 0; + break; + } + #else + nRet = 0; + #endif + + /* NT will implicitly copy the information back to user space */ + + *pnRetSize = ( int )( sizeof(msg->header) + msg->header.msg_len ); + + break; + } + + + /* Can't really emulate the module unloading on NT */ + case PLEX86_RESET: + break; + + case PLEX86_RESET_CPU: + { + guest_cpu_t* guest_cpu = ( guest_cpu_t* )pvParameter; + + if (vm->mon_state != MON_STATE_RUNNABLE) + { + nRet = 0; + break; + } + + get_cpu_reset_values(guest_cpu); + + if ( !setGuestCPU(vm, 0, guest_cpu) || + !mapMonitor(vm, guest_cpu->eflags,0) ) + { + nRet = 0; + break; + } + + vm->mon_state = MON_STATE_RUNNABLE; + break; + } + + case PLEX86_GET_CPU: + { + guest_cpu_t* guest_cpu = ( guest_cpu_t* )pvParameter; + + if ( (vm->mon_state != MON_STATE_RUNNABLE) && + (vm->mon_state != MON_STATE_PANIC) ) + { + nRet = 0; + break; + } + + get_guest_cpu_state(vm, guest_cpu); + + /* NT will implicitly copy the information back to user space */ + + *pnRetSize = sizeof(guest_cpu_t); + break; + } + + case PLEX86_SET_CPU: + { + guest_cpu_t* guest_cpu = ( guest_cpu_t* )pvParameter; + + printk( "plex86.sys: In PLEX86_SET_CPU (0x0)\n", PLEX86_SET_CPU ); + + if (vm->mon_state != MON_STATE_RUNNABLE) + { + nRet = 0; + break; + } + + printk("cpu.cr0 = 0x0\n", guest_cpu->cr0); + + if ( !setGuestCPU(vm, 0, guest_cpu) || + !mapMonitor(vm, guest_cpu->eflags,0) ) + { + nRet = 0; + break; + } + + vm->mon_state = MON_STATE_RUNNABLE; + break; + } + + case PLEX86_FORCE_INT: + { + unsigned long arg = *( unsigned long* )pvParameter; + + if (vm->mon_state != MON_STATE_RUNNABLE) + { + nRet = 0; + break; + } + + vm->dbg_force_int = 0x100 | arg; + break; + } + + case PLEX86_SET_A20: + { + unsigned long arg = *( unsigned long* )pvParameter; + + if ( !ioctlSetA20E(vm, arg) ) + { + nRet = 0; + break; + } + + break; + } + + case PLEX86_PHYMEM_MOD: + { + /* +++ not very efficient, should mark based on addr range */ + initVCodeCache(vm); + break; + } + + case PLEX86_PRESCANRING3: + { + unsigned long arg = *( unsigned long* )pvParameter; + + if (arg > PrescanRing3On) + { + printk( "plex86.sys: Requested PrescanRing3 val(0) OOB\n", arg ); + nRet = 0; + } + vm->prescanRing3 = arg; + break; + } + case PLEX86_MMAP_GUESTMEM: + { + if ( !vm->host.addr.guest ) + { + printk( "plex86.sys: Attempt to mmap before allocation!\n" ); + nRet = 0; + break; + } + + if ( !map_memory_to_user( vm->host.addr.guest, + &vm->pvGuestMemory, + &vm->mdlGuestMemory, + ( long )vm->pages.guest_n_bytes ) ) + { + printk( "plex86.sys: Failed to map guest memory\n" ); + nRet = 0; + break; + } + + if ( !vm->pvGuestMemory ) + { + printk( "plex86.sys: Failed to map guest memory!\n" ); + nRet = 0; + break; + } + + /* Copy the pointer back to the caller. */ + *( void** )pvParameter = vm->pvGuestMemory; + *pnRetSize = sizeof(void*); + + break; + } + + case PLEX86_UNMAP_GUESTMEM: + { + if ( !vm->mdlGuestMemory ) + { + printk( "plex86.sys: Unmap guest called without prior mmap!\n" ); + nRet = 0; + break; + } + + ( void )unmap_memory_from_user( &vm->pvGuestMemory, &vm->mdlGuestMemory ); + + break; + } + + case PLEX86_MMAP_PRINTMEM: + { + if ( !vm->host.addr.log_buffer ) + { + printk( "plex86.sys: Attempt to mmap before allocation!\n" ); + nRet = 0; + break; + } + + if ( !map_memory_to_user( vm->host.addr.log_buffer, + &vm->pvPrintMemory, + &vm->mdlPrintMemory, + PAGE_SIZE * LOG_BUFF_PAGES ) ) + { + printk( "plex86.sys: Failed to map guest memory\n" ); + nRet = 0; + break; + } + + if ( !vm->pvPrintMemory ) + { + printk( "plex86.sys: Failed to map print memory!\n" ); + nRet = 0; + break; + } + + /* Copy the pointer back to the caller. */ + *( void** )pvParameter = vm->pvPrintMemory; + *pnRetSize = sizeof(void*); + + break; + } + + case PLEX86_UNMAP_PRINTMEM: + { + if ( !vm->mdlPrintMemory ) + { + printk( "plex86.sys: Unmap print called without prior mmap!\n" ); + nRet = 0; + break; + } + + ( void )unmap_memory_from_user( &vm->pvPrintMemory, &vm->mdlPrintMemory ); + + break; + } + + default: + printk( "plex86.sys: unknown ioControlCode\n"); + nRet = 0; + break; + } + + return nRet; + } + + void + hostprint(vm_t *vm, char *fmt, ...) + { + va_list args; + int ret; + char buffer[256]; + + UNREFERENCED_PARAMETER( vm ) + + va_start(args, fmt); + ret = mon_vsnprintf(buffer, 256, fmt, args); + if (ret == -1) { + printk("hostprint: vsnprintf returns error.\n"); + } + else { + printk("\n", buffer); + } + } + + int __stdcall + retrieve_monitor_pages(void) + { + /* + * Retrieve start address and size of this module. + */ + + unsigned long size = 0; + void* start_addr = FindModule( "plex86.sys", &size ); + size_t n_pages = 0; + + printk( "plex86.sys: Module Address = 0x0, size = 0x0, n_pages = 0\n", start_addr, size, n_pages ); + + if ( start_addr != NULL ) + { + n_pages = retrieve_phy_pages(monitor_pages.page, PLEX86_MAX_MONITOR_PAGES, + start_addr, size); + printk("0 monitor pages located\n", n_pages); + + monitor_pages.start_addr = (Bit32u)start_addr; + monitor_pages.n_pages = n_pages; + /* + n_pages = ( size / PAGE_SIZE ) + ( ( size % PAGE_SIZE ) ? 1 : 0 ); + + monitor_pages.start_addr = (Bit32u)start_addr; + monitor_pages.n_pages = host_map( monitor_pages.page, + PLEX86_MAX_MONITOR_PAGES, + start_addr, + size ); + */ + } + + return ( int )n_pages; + } + + unsigned MON_HOST_DECL + host_map(Bit32u *page, int max_pages, void *ptr, unsigned size) + { + return( retrieve_phy_pages(page, max_pages, ptr, size) ); + } + *** kernel/makefile.nt Wed Dec 31 14:00:00 1969 --- kernel/makefile.nt Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,117 ---- + # Generated automatically from Makefile.in by configure. + # plex86: run multiple x86 operating systems concurrently + # Copyright (C) 1999 Kevin P. Lawton + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public + # License as published by the Free Software Foundation; either + # version 2 of the License, or (at your option) any later version. + # + # This library is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # Lesser General Public License for more details. + # + # You should have received a copy of the GNU Lesser General Public + # License along with this library; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + CL = cl + CC = gcc + CFLAGS = -DANAL_CHECKS -Wall -Wstrict-prototypes + LDFLAGS = + KERNEL_TARGET = plex86.sys + + .SUFFIXES: obj + + srcdir = . + + LD = ld + + HOST_O = host-nt.obj host-nt2.o + + # extra kernel CFLAGS and LDFLAGS for each host OS + KCFLAGS_LINUX = -fno-strength-reduce -fomit-frame-pointer \ + -malign-loops=2 -malign-jumps=2 -malign-functions=2 \ + -D__KERNEL__ -I/usr/src/linux/include -DCPU=586 -DMODULE + KLDFLAGS_LINUX = -r + + KCFLAGS_BEOS = + KLDFLAGS_BEOS = -nostdlib /boot/develop/lib/x86/_KERNEL_ + + KCFLAGS_NT = + KLDFLAGS_NT = -r + + KLDFLAGS = $(KLDFLAGS_NT) + + ALL_CFLAGS = $(CFLAGS) $(KCFLAGS_NT) -I$(srcdir)/include -I$(srcdir)/.. -I.. + + + .c.o: + $(CC) -c $(ALL_CFLAGS) $< + .S.o: + $(CC) -c $(ALL_CFLAGS) -D__ASSEMBLY__ $< + + + $(KERNEL_TARGET): $(HOST_O) host-all.o host-monitor.o \ + nexus.o nexus-flag.o nexus-mode.o nexus-prescan.o nexus-print.o nexus-segment.o \ + mon-fault.o mon-prescan.o mon-phymem.o mon-panic.o \ + mon-paging.o mon-system.o mon-mode.o \ + emulation/emu.a + link -STACK:262144,4096 \ + -MERGE:_PAGE=PAGE \ + -MERGE:_TEXT=.text \ + -SECTION:INIT,d \ + -OPT:REF \ + -OPT:ICF \ + -IGNORE:4001,4037,4039,4044,4065,4070,4078,4087,4089,4198 \ + -INCREMENTAL:NO \ + -FULLBUILD \ + -FORCE:MULTIPLE \ + -NOCOMMENT \ + /release \ + -NODEFAULTLIB \ + -version:5.00 \ + -osversion:5.00 \ + -optidata \ + -driver \ + -align:0x20 \ + -subsystem:native,5.00 \ + -base:0x10000 \ + -entry:DriverEntry@8 \ + -out:$@ \ + ntoskrnl.lib \ + ntdll.lib \ + hal.lib \ + wmilib.lib \ + $^ + + host-nt.obj: host-nt.c + cl /W4 /c /G5 /Gz /Oigs /I .. -I include /D_X86_ host-nt.c + + #$(KERNEL_TARGET): $(HOST_O) host-all.o monitor.o nexus.o fault.o \ + # prescan.o monprint.o phymem.o monpanic.o \ + # vpaging.o system.o vsegment.o vflag.o vsegment_nexus.o \ + # emulation/emu.o + # $(MAKE) -C emulation $(MDEFINES) + # $(LD) $(KLDFLAGS) $^ -o $@ + + emulation/emu.a: + $(MAKE) -f makefile.nt -C emulation $(MDEFINES) + + clean: + $(MAKE) -C emulation clean + /bin/rm -f *.o *.s $(KERNEL_TARGET) + + dist-clean: clean + $(MAKE) -C emulation dist-clean + /bin/rm -f Makefile + + beos-install: $(KERNEL_TARGET) + cp -f $(KERNEL_TARGET) /boot/home/config/add-ons/kernel/drivers/bin + mkdir -p /boot/home/config/add-ons/kernel/drivers/dev/misc + ln -sf ../../bin/$(KERNEL_TARGET) /boot/home/config/add-ons/kernel/drivers/dev/misc/$(KERNEL_TARGET) + + Makefile: Makefile.in ../config.status + cd ..; CONFIG_FILES=kernel/Makefile CONFIG_HEADERS= $(SHELL) config.status *** kernel/emulation/makefile.nt Wed Dec 31 14:00:00 1969 --- kernel/emulation/makefile.nt Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,73 ---- + # Generated automatically from Makefile.in by configure. + # plex86: run multiple x86 operating systems concurrently + # Copyright (C) 1999-2000 Kevin P. Lawton + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public + # License as published by the Free Software Foundation; either + # version 2 of the License, or (at your option) any later version. + # + # This library is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # Lesser General Public License for more details. + # + # You should have received a copy of the GNU Lesser General Public + # License along with this library; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + CC = gcc + CFLAGS = -O2 -Wall -Wstrict-prototypes + LDFLAGS = + EMU_TARGET = emu.a + + srcdir = . + + LD = ld + + # extra kernel CFLAGS and LDFLAGS for each host OS + KCFLAGS_LINUX = -fno-strength-reduce -fomit-frame-pointer \ + -malign-loops=2 -malign-jumps=2 -malign-functions=2 \ + -DEMULATION + KLDFLAGS_LINUX = -r + + KCFLAGS_BEOS = + KLDFLAGS_BEOS = -nostdlib /boot/develop/lib/x86/_KERNEL_ + + KCFLAGS_NT = -DEMULATION + KLDFLAGS_NT = + KLDFLAGS = $(KLDFLAGS_NT) + + ALL_CFLAGS = $(CFLAGS) $(KCFLAGS_NT) -I../include -I../.. + + + .c.o: + $(CC) -c $(ALL_CFLAGS) -DIN_MONITOR_SPACE $< + .S.o: + $(CC) -c $(ALL_CFLAGS) -D__ASSEMBLY__ $< + + + $(EMU_TARGET): \ + emulation.o fetchdecode.o io_pro.o \ + exception.o protect_ctrl.o ctrl_xfer32.o access.o \ + stack_pro.o segment_pro.o paging.o \ + segment_ctrl.o ctrl_xfer_pro.o stack.o flag.o \ + ctrl_xfer16.o data_xfer16.o data_xfer32.o regs.o \ + logical16.o logical32.o vm8086.o soft_int.o tasking.o \ + data_xfer8.o shift32.o io_pro.o \ + proc_ctrl.o arith32.o arith16.o arith8.o logical8.o \ + mult32.o string.o ctrl_xfer8.o io.o shift8.o mult8.o \ + shift16.o mult16.o bcd.o bit.o fpu.o + -del $@ + ar rv $@ $^ + ranlib $@ + + clean: + /bin/rm -f *.o *.so *.s $(KERNEL_TARGET) + + dist-clean: clean + /bin/rm -f Makefile + + Makefile: Makefile.in ../../config.status + cd ../..; CONFIG_FILES=kernel/emulation/Makefile CONFIG_HEADERS= $(SHELL) config.status *** user/makefile.nt Wed Dec 31 14:00:00 1969 --- user/makefile.nt Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,82 ---- + # Generated automatically from Makefile.in by configure. + # plex86: run multiple x86 operating systems concurrently + # Copyright (C) 1999-2000 The plex86 developers team + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public + # License as published by the Free Software Foundation; either + # version 2 of the License, or (at your option) any later version. + # + # This library is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # Lesser General Public License for more details. + # + # You should have received a copy of the GNU Lesser General Public + # License along with this library; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + SHELL = /bin/sh + + + + CC = gcc + CFLAGS = -g -Wall -Wstrict-prototypes + LDFLAGS = + + srcdir = . + + BOCHSDIR = /home/kpl/bochs/bochs-2000_0325a + BOCHSLIBS = \ + $(BOCHSDIR)/main.o \ + $(BOCHSDIR)/load32bitOShack.o \ + $(BOCHSDIR)/state_file.o \ + $(BOCHSDIR)/pc_system.o \ + $(BOCHSDIR)/iodev/libiodev.a \ + $(BOCHSDIR)/cpu/libcpu.a \ + $(BOCHSDIR)/memory/libmemory.a \ + $(BOCHSDIR)/gui/libgui.a \ + $(BOCHSDIR)/debug/libdebug.a \ + $(BOCHSDIR)/disasm/libdisasm.a \ + $(BOCHSDIR)/fpu/libfpu.a \ + -L/usr/X11R6/lib -lSM -lICE -lX11 + COSIM_O = cosim.o + + BOCHSLIBS = + COSIM_O = + + + ALL: plex86.exe plex86.dll + $(MAKE) -C plugins -f makefile.nt $(MDEFINES) + + .c.o: + $(CC) -I.. -I$(srcdir)/.. -I$(srcdir) $(CFLAGS) -c $< + + plex86.exe: plex86.o libplex86.a user_win32.o + $(CC) -g -o plex86.exe plex86.o libplex86.a -lwsock32 -lgdi32 + + libplex86.a: user_win32.o decode.o plugin.o $(COSIM_O) + dllwrap -o plex86.dll --def plex86.def --output-lib libplex86.a \ + user_win32.o decode.o plugin.o \ + $(COSIM_O) \ + $(BOCHSLIBS) -lwsock32 + + #libplex86.a: plex86.dll + # dlltool --dllname=plex86.dll --output-lib=libplex86.a + + plugins/bochs/plugin-bochs.a: + $(MAKE) -C plugins -f makefile.nt $(MDEFINES) + + resetmod: resetmod.o + $(CC) -o resetmod resetmod.o + + clean: + $(MAKE) -C plugins clean + /bin/rm -f *.o plex86 resetmod core bochs.out + + dist-clean: clean + $(MAKE) -C plugins dist-clean + /bin/rm -f Makefile + + Makefile: Makefile.in ../config.status + cd ..; CONFIG_FILES=user/Makefile CONFIG_HEADERS= $(SHELL) config.status *** user/plex86.def Wed Dec 31 14:00:00 1969 --- user/plex86.def Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,91 ---- + EXPORTS + AddrHasModRM @1 DATA + EffBase16 @2 DATA + EffBase32 @3 DATA + EffIndex16 @4 DATA + EffIndex32 @5 DATA + EscAuxMap @6 DATA + EscMainMap @7 DATA + GroupMap @8 DATA + InsNamesATT @9 DATA + InsNamesIntel @10 DATA + InstallDriver @11 + LoadDeviceDriver @12 + MapControl @13 DATA + MapDebug @14 DATA + MapMMX @15 DATA + MapReg16 @16 DATA + MapReg32 @17 DATA + MapReg8 @18 DATA + MapSeg @19 DATA + MapTest @20 DATA + MapXMMX @21 DATA + OneByteMap @22 DATA + OpenDevice @23 + RegNamesATT @24 DATA + RegNamesIntel @25 DATA + RemoveDriver @26 + ReportError @27 + StartDriver @28 + StopDriver @29 + TwoByteMap @30 DATA + UnloadDeviceDriver @31 + atexit @32 + callback_command_list @33 DATA + dump_vga @34 + get_vm_conf @35 + hDriver @36 DATA + i386_decode @37 DATA + i386_decode_text @38 DATA + i386_decode_text_att @39 + i386_decode_text_intel @40 + linux_hack @41 + memMapFunct @42 DATA + plugin_abort @43 + plugin_acknowledge_intr @44 DATA + plugin_alloc_inp @45 + plugin_alloc_intr @46 + plugin_alloc_outp @47 + plugin_announce_iac_handler @48 + plugin_call_elapsed @49 DATA + plugin_emulate_inport @50 DATA + plugin_emulate_int @51 DATA + plugin_emulate_outport @52 DATA + plugin_fini_all @53 DATA + plugin_free_inp @54 + plugin_free_intr @55 + plugin_free_outp @56 + plugin_get_A20E @57 + plugin_handle_periodic @58 DATA + plugin_load @59 + plugin_register_elapsed @60 + plugin_register_mem_map_IO @61 + plugin_register_periodic @62 + plugin_set_A20E @63 + plugin_set_intr @64 + plugin_startup @65 + plugin_unload @66 + plugins @67 DATA + printBuffer @68 DATA + user_time_usec @69 DATA + vm_abort @70 + vm_alloc_intr @71 + vm_conf @72 DATA + vm_debug_exception @73 + vm_event_loop @74 + vm_fini @75 + vm_get_cpu @76 + vm_init @77 + vm_init_memory @78 + vm_init_prescan_depth @79 + vm_init_prescan_ring3 @80 + vm_kickstart @81 + vm_load_rom @82 + vm_open @83 + vm_read_physical @84 + vm_register_callback @85 + vm_release_intr @86 + vm_set_cpu @87 + vm_set_intr @88 + vm_write_physical @89 + pluginCallbacks @90 DATA *** user/user_win32.c Wed Dec 31 14:00:00 1969 --- user/user_win32.c Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,1289 ---- + /* + * plex86: run multiple x86 operating systems concurrently + * Copyright (C) 1999-2000 The plex86 developers team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + #include <windows.h> + + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + #include <process.h> + #include <sys/time.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <io.h> + #include <fcntl.h> + + //#include <sys/ioctl.h> + //#include <unistd.h> + //#include <sys/mman.h> + + #include <errno.h> + + #include "plex86.h" + #include "user.h" + #include "plugin.h" + #include "decode.h" + + #define ICOUNT_INFINITE -1 + + //#define RunMethod RunGuestNMethodBreakpoint // OK solo with tick hacks + #define RunMethod RunGuestNMethodEmulate // OK solo with tick hacks + //#define RunMethod RunGuestNMethodExecute + + /************************************************************************/ + /* Structures / Variables */ + /************************************************************************/ + + static char *ptr = NULL; /* Pointer to the guest virtual phys mem */ + char *printBuffer = NULL; /* mmap to monitor print buffer */ + + HANDLE hDriver = NULL; /* Handle to \Devices\Plex86 */ + + static unsigned char int_usage[256]; /* Interrupt usage count table */ + + void dump_vga(void); + static void vm_timer_handler(int i); + Bit64u user_time_usec = 0; + static unsigned a20_val = 1; + static HANDLE timer_thread_shutdown = NULL; + static unsigned timer_thread_handle = 0; + + callback_command_t *callback_command_list; + config_info_t vm_conf; + + static void vm_timer_thread( void* ); + + config_info_t* get_vm_conf( void ) + { + return &vm_conf; + } + + /************************************************************************/ + /* Initialization and abort code */ + /************************************************************************/ + + void ReportError( const char* pszContext, DWORD dwError ) + { + char szMsg[ 80 ]; + int nLen; + int nIdx; + + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError ? dwError : GetLastError(), + 0UL, + szMsg, + sizeof(szMsg), + NULL ); + + nLen = strlen( szMsg ); + + if ( nLen > 2 ) + { + for ( nIdx = nLen - 1; nIdx > 0; nIdx-- ) + { + if ( ( szMsg[ nIdx ] != '\r' ) && ( szMsg[ nIdx ] != '\n' ) ) + { + szMsg[ nIdx + 1 ] = '\0'; + break; + } + } + } + + fprintf( stderr, + ": ''\n", pszContext, szMsg ); + } + + BOOL InstallDriver( IN SC_HANDLE hSCManager, + IN LPCTSTR pszDriverName, + IN LPCTSTR pszServiceExe ) + { + SC_HANDLE hService; + + // + // NOTE: This creates an entry for a standalone driver. If this + // is modified for use with a driver that requires a Tag, + // Group, and/or Dependencies, it may be necessary to + // query the registry for existing driver information + // (in order to determine a unique Tag, etc.). + // + + hService = CreateService( hSCManager, // SCManager database + pszDriverName, // name of service + pszDriverName, // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_KERNEL_DRIVER, // service type + SERVICE_DEMAND_START, // start type + SERVICE_ERROR_NORMAL, // error control type + pszServiceExe, // service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // no dependencies + NULL, // LocalSystem account + NULL // no password + ); + + if ( hService == NULL ) + return FALSE; + + CloseServiceHandle( hService ); + + return TRUE; + } + + + BOOL StartDriver( IN SC_HANDLE hSCManager, + IN LPCTSTR pszDriverName ) + { + SC_HANDLE hService; + BOOL ret; + + hService = OpenService( hSCManager, + pszDriverName, + SERVICE_ALL_ACCESS ); + + if ( hService == NULL ) + return FALSE; + + ret = StartService( hService, 0, NULL ); + + CloseServiceHandle( hService ); + + return ret; + } + + BOOL OpenDevice( IN LPCTSTR pszDriverName, + HANDLE* phDevice ) + { + TCHAR szDeviceName[64]; + HANDLE hDevice; + + if( ( GetVersion() & 0xFF ) >= 5 ) + { + // + // We reference the global name so that the application can + // be executed in Terminal Services sessions on Win2K + // + wsprintf( szDeviceName, TEXT("\\\\.\\Global\\"), pszDriverName ); + + } + else + { + wsprintf( szDeviceName, TEXT("\\\\.\\"), pszDriverName ); + } + + hDevice = CreateFile( szDeviceName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if ( hDevice == INVALID_HANDLE_VALUE ) + return FALSE; + + // If user wants handle, give it to them. Otherwise, just close it. + + if ( phDevice ) + *phDevice = hDevice; + else + CloseHandle( hDevice ); + + return TRUE; + } + + BOOL StopDriver( IN SC_HANDLE hSCManager, + IN LPCTSTR pszDriverName ) + { + SC_HANDLE hService; + BOOL ret; + SERVICE_STATUS serviceStatus; + + hService = OpenService( hSCManager, pszDriverName, SERVICE_ALL_ACCESS ); + if ( hService == NULL ) + return FALSE; + + ret = ControlService( hService, SERVICE_CONTROL_STOP, &serviceStatus ); + + CloseServiceHandle( hService ); + + return ret; + } + + BOOL RemoveDriver( IN SC_HANDLE hSCManager, + IN LPCTSTR pszDriverName ) + { + SC_HANDLE hService; + BOOL ret; + + hService = OpenService( hSCManager, + pszDriverName, + SERVICE_ALL_ACCESS + ); + + if ( hService == NULL ) + return FALSE; + + ret = DeleteService( hService ); + + CloseServiceHandle( hService ); + + return ret; + } + + BOOL UnloadDeviceDriver( LPCTSTR pszName ) + { + SC_HANDLE hSCManager; + + hSCManager = OpenSCManager( NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + + StopDriver( hSCManager, pszName ); + RemoveDriver( hSCManager, pszName ); + + CloseServiceHandle( hSCManager ); + + return TRUE; + } + + BOOL LoadDeviceDriver( LPCTSTR pszName, + LPCTSTR pszPath, + HANDLE* phDevice, + PDWORD pdwError ) + { + SC_HANDLE hSCManager; + BOOL okay; + + hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + + // Remove old instances + RemoveDriver( hSCManager, pszName ); + + // Ignore success of installation: it may already be installed. + InstallDriver( hSCManager, pszName, pszPath ); + + // Ignore success of start: it may already be started. + StartDriver( hSCManager, pszName ); + + // Do make sure we can open it. + okay = OpenDevice( pszName, phDevice ); + *pdwError = GetLastError(); + CloseServiceHandle( hSCManager ); + + return okay; + } + + void + vm_kickstart (void) + { + /* open a new VM */ + + vm_init(); + + + /* load guest code into the virtual physical memory and initialize guest context */ + + memset (int_usage, 0, 256); + + + /* initialize all plugins */ + + fprintf (stderr, "Initializing plugins\n"); + /*plugin_init_all (); */ + + #if !COSIMULATE + timer_thread_shutdown = CreateEvent( NULL, FALSE, FALSE, NULL ); + + _beginthread( vm_timer_thread, 0, timer_thread_shutdown ); + + /* _beginthreadex( NULL, + 0, + vm_timer_thread, + timer_thread_shutdown, + 0, + &timer_thread_handle ); */ + #endif + } + + void + vm_timer_thread( void* pShutdown ) + { + DWORD dwLast = GetTickCount(); + DWORD dwNow = dwLast; + int nExit = 0; + + while ( !nExit ) + { + switch ( WaitForSingleObject( ( HANDLE )pShutdown, 500000 ) ) + { + case WAIT_OBJECT_0: + nExit = 1; + break; + + case WAIT_TIMEOUT: + dwNow = GetTickCount(); + user_time_usec += ( dwNow - dwLast ); + dwLast = dwNow; + break; + + default: + /* Presumably an error condition */ + nExit = 1; + break; + } + } + + CloseHandle( ( HANDLE )pShutdown ); + } + + void + vm_timer_handler(int i) + { + #warning "fix: need exclusive access to variable in async handler" + user_time_usec += 500000; + } + + void + vm_set_cpu(guest_cpu_t *guest_cpu) + { + DWORD dwOutBytes; + + if ( !DeviceIoControl( hDriver, + PLEX86_SET_CPU, + guest_cpu, + sizeof(guest_cpu), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_SET_CPU)",0UL); + exit (1); + } + } + + + void + vm_abort(void) + { + static int was_waiting = 0; + + dump_vga(); + + if (! was_waiting && vm_conf.exit_wait > 0) { + struct timeval tv; + + was_waiting = 1; + tv.tv_sec = vm_conf.exit_wait; + tv.tv_usec = 0; + + printf("Delaying exit by 0 seconds\n", (int)tv.tv_sec); + while (1) { + select(0, NULL, NULL, NULL, &tv); + if (errno == EINTR && tv.tv_sec > 0) + continue; + break; + } + } + + /* deinitialize all plugins */ + + fprintf (stderr, "Shutting down plugins\n"); + plugin_fini_all (); + + + + /* shut down the virtual machine */ + + vm_fini (); + + + + /* we're done!! */ + + #if COSIMULATE + { + void bx_dbg_exit(int); + bx_dbg_exit(1); + } + #endif + exit (0); + } + + void + dump_vga(void) + { + unsigned col, line; + unsigned char c; + unsigned char buffer[81]; + unsigned useful; + + fprintf(stderr, "============ begin VGA text buffer dump ===============\n"); + for (line=0; line<25; line++) { + useful = 0; + for (col=0; col<80; col++) { + c = ptr[0xb8000 + (line*80 + col)*2]; + if ( (c>=32) && (c<=126) && (c!=37) ) { + buffer[col] = c; + useful = 1; + } + else + buffer[col] = '.'; + } + buffer[80] = 0; + if (useful) + fprintf(stderr, "\n", buffer); + } + fprintf(stderr, "============ end VGA text buffer dump ===============\n"); + + #warning "remove this debug code sometime" + { + Bit32u v; + v = * (Bit32u *) &ptr[0x105000]; + fprintf(stderr, "[0x105000] = 0x0\n", v); + } + } + + + /************************************************************************/ + /* VM initialization and deinitialization code */ + /************************************************************************/ + + void + vm_open(void) + { + DWORD dwError; + + /* + * To start with we'll just load the Monitor at every invocation + * to make debugging easier. In time we'll just rely on the monitor + * already being loaded. + */ + + if ( !LoadDeviceDriver( "plex86", "d:\\build\\plex86\\kernel\\plex86.sys", &hDriver, &dwError ) ) + { + ReportError( "Failed to load plex86.sys", dwError ); + exit(1); + } + + atexit( vm_fini ); + } + + void + vm_init_prescan_depth(unsigned depth) + { + DWORD dwOutBytes; + + /* Request any tweaks to the VM environment: */ + if (vm_conf.prescanDepth) + { + fprintf (stderr, "Setting prescan depth to 0\n", vm_conf.prescanDepth); + + /* TODO: Is this at all correct? */ + if ( !DeviceIoControl( hDriver, + PLEX86_PRESCANDEPTH, + &vm_conf.prescanDepth, + sizeof(int), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_PRESCANDEPTH)",0UL); + exit (1); + } + } + } + + + void + vm_init_prescan_ring3(unsigned request) + { + DWORD dwOutBytes; + + /* Request any tweaks to the VM environment: */ + fprintf (stderr, "Setting prescan ring3 to 0\n", vm_conf.prescanRing3); + + /* TODO: Is this at all correct? */ + if ( !DeviceIoControl( hDriver, + PLEX86_PRESCANRING3, + &vm_conf.prescanRing3, + sizeof(int), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_PRESCANRING3)",0UL); + exit (1); + } + } + + void + vm_init_memory(unsigned nmegs) + { + DWORD dwOutBytes; + + /* allocate memory from the host OS for the virtual physical memory */ + + fprintf (stderr, "Allocating 0MB of physical memory in VM\n", nmegs); + + if ( !DeviceIoControl( hDriver, + PLEX86_ALLOCVPHYS, + &nmegs, + sizeof(nmegs), + &ptr, + sizeof(ptr), + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_ALLOCVPHYS)",0UL); + exit (1); + } + + MessageBox( NULL, "After AllocVPhys", "plex86", MB_OK ); + + /* map guest virtual physical memory into user address space and zero it */ + + fprintf (stderr, "Mapping virtualized physical memory into monitor\n"); + + if ( !DeviceIoControl( hDriver, + PLEX86_MMAP_GUESTMEM, + NULL, + 0, + &ptr, + sizeof(ptr), + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_MMAP_GUESTMEM)",0UL); + exit (1); + } + + fprintf( stderr, "-- ptr seems to be 0x0 (0)\n", ptr, dwOutBytes ); + + MessageBox( NULL, "After mmap_guestmem", "plex86", MB_OK ); + + fprintf (stderr, "Zeroing virtualized physical memory\n"); + memset (ptr, 0, nmegs * 1024 * 1024); + + MessageBox( NULL, "After memset", "plex86", MB_OK ); + + if ( !DeviceIoControl( hDriver, + PLEX86_MMAP_PRINTMEM, + NULL, + 0, + &printBuffer, + sizeof(printBuffer), + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_MMAP_PRINTMEM)",0UL); + exit (1); + } + + MessageBox( NULL, "After mmap_printmem", "plex86", MB_OK ); + + if ( !printBuffer ) + { + ReportError("mmap of monitor print buffer",0UL); + exit (1); + } + } + + void + vm_init(void) + { + } + + void + vm_fini (void) + { + fprintf( stderr, "-- vm_fini()\n" ); + + if ( hDriver != NULL ) + { + DWORD dwOutBytes; + + if ( printBuffer != NULL ) + { + /* Unmap the print buffer */ + if ( !DeviceIoControl( hDriver, + PLEX86_UNMAP_PRINTMEM, + NULL, + 0, + NULL, + 0, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_UNMAP_PRINTMEM)",0UL); + } + + printBuffer = NULL; + } + + if ( ptr != NULL ) + { + /* Unmap the guest memory */ + if ( !DeviceIoControl( hDriver, + PLEX86_UNMAP_GUESTMEM, + NULL, + 0, + NULL, + 0, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_UNMAP_GUESTMEM)",0UL); + } + + ptr = NULL; + } + + /* tell kernel module to clean up the VM */ + + fprintf (stderr, "Tearing down VM\n"); + if ( !DeviceIoControl( hDriver, + PLEX86_TEARDOWN, + NULL, + 0UL, + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_TEARDOWN)",0UL); + } + + /* close the connection to the kernel module */ + + fprintf (stderr, "Closing VM\n"); + + CloseHandle( hDriver ); + hDriver = NULL; + + if ( !UnloadDeviceDriver( "plex86" ) ) + { + fprintf( stderr, "** Failed to unload device driver\n" ); + } + } + } + + /************************************************************************/ + /* The main event loop */ + /************************************************************************/ + + void + vm_event_loop (void) + { + DWORD dwOutBytes; + vm_messages_t user_msgs; + run_guest_n_t *run_guest_n_p; + + /* Build message to run guest */ + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(run_guest_n_t); + run_guest_n_p = (run_guest_n_t *) user_msgs.msg; + run_guest_n_p->icount = ICOUNT_INDEFINITE; + run_guest_n_p->method = RunMethod; + + for (;;) + { + fprintf( stderr, "-- user_msgs.header.msg_len = 0\n", user_msgs.header.msg_len ); + fprintf( stderr, "-- user_msgs.header.msg_type = 0\n", user_msgs.header.msg_type ); + + if ( !DeviceIoControl( hDriver, + PLEX86_MESSAGEQ, + &user_msgs, + sizeof(user_msgs.header) + user_msgs.header.msg_len, + &user_msgs, + sizeof(user_msgs), + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_MESSAGEQ)",0UL); + exit (1); + } + + switch (user_msgs.header.msg_type) + { + case VMMessageNone: + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(icount_t); + *(icount_t *) user_msgs.msg = ICOUNT_INFINITE; + break; + + case VMMessagePanic: + fprintf(stderr, "Fatal monitor error caused Panic\n"); + vm_debug_exception(); + vm_abort(); + break; + + case VMMessagePrintBuf: + { + fprintf(stderr, "::\n", printBuffer); + /* No response required */ + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(run_guest_n_t); + run_guest_n_p->icount = ICOUNT_INDEFINITE; + run_guest_n_p->method = RunMethod; + break; + } + + case VMMessageIOInRequest: + { + IO_msg_t *io_msg = (IO_msg_t *) user_msgs.msg; + + /* Zero out data, since it's potentially bigger in size than + * the IO operation we will request + */ + io_msg->data = 0; + + plugin_emulate_inport(io_msg->port, io_msg->len, 1, &io_msg->data); + /* Change message type; most data stays the same */ + user_msgs.header.msg_type = VMMessageIOInResponse; + break; + } + + case VMMessageIOOutRequest: + { + IO_msg_t *io_msg = (IO_msg_t *) user_msgs.msg; + plugin_emulate_outport(io_msg->port, io_msg->len, 1, &io_msg->data); + /* No response required */ + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(run_guest_n_t); + run_guest_n_p->icount = ICOUNT_INDEFINITE; + run_guest_n_p->method = RunMethod; + break; + } + + case VMMessageMemMapIOReadRequest: + { + memMapIO_msg_t *msg = (memMapIO_msg_t *) user_msgs.msg; + + /* Zero out data, since it's potentially bigger in size than + * the IO operation we will request + */ + msg->data = 0; + + if (memMapFunct) { + memMapFunct(msg->addr, msg->len, IO_IN, &msg->data); + } + else { + fprintf(stderr, "MemMapIOWriteRequest: not handled.\n"); + vm_abort(); + } + /* Change message type; most data stays the same */ + user_msgs.header.msg_type = VMMessageMemMapIOReadResponse; + break; + } + + case VMMessageMemMapIOWriteRequest: + { + memMapIO_msg_t *msg = (memMapIO_msg_t *) user_msgs.msg; + if (memMapFunct) { + memMapFunct(msg->addr, msg->len, IO_OUT, &msg->data); + } + else { + fprintf(stderr, "MemMapIOWriteRequest: not handled.\n"); + vm_abort(); + } + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(run_guest_n_t); + run_guest_n_p->icount = ICOUNT_INDEFINITE; + run_guest_n_p->method = RunMethod; + break; + } + + case VMMessageIACRequest: + { + IAC_msg_t *iac_msg = (IAC_msg_t *) user_msgs.msg; + iac_msg->vector = plugin_acknowledge_intr(); + + user_msgs.header.msg_type = VMMessageIACResponse; + user_msgs.header.msg_len = sizeof(IAC_msg_t); + break; + } + + case VMMessageIntRequest: + { + INT_msg_t *int_msg = (INT_msg_t *) user_msgs.msg; + int_msg->reflect = plugin_emulate_int (int_msg->vector); + + user_msgs.header.msg_type = VMMessageIntResponse; + break; + } + + case VMMessageTimeElapsed: + { + void do_timer(Bit64u elapsed); + time_elapsed_t *time_elapsed = (time_elapsed_t *) user_msgs.msg; + plugin_call_elapsed(time_elapsed->elapsed); + + /* No response required */ + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(icount_t); + *(icount_t *) user_msgs.msg = ICOUNT_INFINITE; + break; + } + + case VMMessageDisasm: + vm_debug_exception(); + user_msgs.header.msg_type = VMMessageRunGuestN; + user_msgs.header.msg_len = sizeof(icount_t); + *(icount_t *) user_msgs.msg = ICOUNT_INFINITE; + fprintf(stderr, "> "); + getchar(); + break; + + + default: + fprintf(stderr, "VMMessage type 0 not handled yet\n", + user_msgs.header.msg_type); + vm_abort(); + break; + } + + plugin_handle_periodic(); + } + } + + + + + /************************************************************************/ + /* Interrupt stuff */ + /************************************************************************/ + + void + vm_set_intr (int intr) + { + DWORD dwOutBytes; + + if ( !DeviceIoControl( hDriver, + PLEX86_SETINTR, + &intr, + sizeof(int), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_SETINTR)",0UL); + vm_abort(); + } + } + + int + vm_alloc_intr (int intr) + { + DWORD dwOutBytes; + + if (intr < 0 || intr > 255) + return 1; + + if ( !DeviceIoControl( hDriver, + PLEX86_ALLOCINT, + &intr, + sizeof(int), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + return 1; + + int_usage[intr]++; + return 0; + } + + int + vm_release_intr (int intr) + { + DWORD dwOutBytes; + + if (intr < 0 || intr > 255) + return 1; + + if (--int_usage[intr]) + return 0; + + if ( !DeviceIoControl( hDriver, + PLEX86_RELEASEINT, + &intr, + sizeof(int), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + return 1; + + return 0; + } + + + /************************************************************************/ + /* Guest register access */ + /************************************************************************/ + + void + vm_get_cpu(guest_cpu_t *cpu) + { + DWORD dwOutBytes; + + if ( !DeviceIoControl( hDriver, + PLEX86_GET_CPU, + cpu, + sizeof(*cpu), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_GET_CPU)",0UL); + exit(1); + } + } + + /************************************************************************/ + /* Guest memory access */ + /************************************************************************/ + + int + vm_read_physical (Bit32u address, unsigned length, void *data) + { + if ( address+length >= vm_conf.max_memory*1024*1024 ) + return 1; + + memcpy (data, ptr+address, length); + return 0; + } + + int + vm_write_physical (Bit32u address, unsigned length, void *data) + { + DWORD dwOutBytes; + + if ( address+length >= vm_conf.max_memory*1024*1024 ) + return 1; + + memcpy(((char *)ptr)+address, data, length); + + if ( !DeviceIoControl( hDriver, + PLEX86_PHYMEM_MOD, + NULL, + 0UL, + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_PHYMEM_MOD)",0UL); + exit(1); + } + + return 0; + } + + + /************************************************************************/ + /* Debug event handler */ + /************************************************************************/ + + int + vm_debug_exception(void) + { + guest_cpu_t cpu; + + struct i386_context ctx; + struct i386_decode instr; + int i, len = 8; + char prefix[256], text[256]; + Bit8u *seg_base_ptr; + + + #if COSIMULATE + bx_print_last_sync_icount(); + #endif + + /* get guest context */ + + vm_get_cpu(&cpu); + + #define LowDWord(d) ( ((Bit32u*) (&(d)))[0] ) + #define HighDWord(d) ( ((Bit32u*) (&(d)))[1] ) + + /* Dump state of CPU */ + fprintf(stderr, "eax:0x0\n", (unsigned) cpu.eax); + fprintf(stderr, "ebx:0x0\n", (unsigned) cpu.ebx); + fprintf(stderr, "ecx:0x0\n", (unsigned) cpu.ecx); + fprintf(stderr, "edx:0x0\n", (unsigned) cpu.edx); + + fprintf(stderr, "ebp:0x0\n", (unsigned) cpu.ebp); + fprintf(stderr, "esi:0x0\n", (unsigned) cpu.esi); + fprintf(stderr, "edi:0x0\n", (unsigned) cpu.edi); + fprintf(stderr, "esp:0x0\n", (unsigned) cpu.esp); + + fprintf(stderr, "eflags:0x0\n", (unsigned) cpu.eflags); + fprintf(stderr, "eip:0x0\n", (unsigned) cpu.eip); + + fprintf(stderr, "cs:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.cs.sel.raw, LowDWord(cpu.cs.des), + (unsigned) HighDWord(cpu.cs.des), (unsigned) cpu.cs.valid); + + fprintf(stderr, "ss:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.ss.sel.raw, (unsigned) LowDWord(cpu.ss.des), + (unsigned) HighDWord(cpu.ss.des), (unsigned) cpu.ss.valid); + + fprintf(stderr, "ds:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.ds.sel.raw, (unsigned) LowDWord(cpu.ds.des), + (unsigned) HighDWord(cpu.ds.des), (unsigned) cpu.ds.valid); + + fprintf(stderr, "es:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.es.sel.raw, (unsigned) LowDWord(cpu.es.des), + (unsigned) HighDWord(cpu.es.des), (unsigned) cpu.es.valid); + + fprintf(stderr, "fs:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.fs.sel.raw, (unsigned) LowDWord(cpu.fs.des), + (unsigned) HighDWord(cpu.fs.des), (unsigned) cpu.fs.valid); + + fprintf(stderr, "gs:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.gs.sel.raw, (unsigned) LowDWord(cpu.gs.des), + (unsigned) HighDWord(cpu.gs.des), (unsigned) cpu.gs.valid); + + fprintf(stderr, "ldtr:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.ldtr.sel.raw, (unsigned) LowDWord(cpu.ldtr.des), + (unsigned) HighDWord(cpu.ldtr.des), (unsigned) cpu.ldtr.valid); + + fprintf(stderr, "tr:s=0x0, dl=0x0, dh=0x0, valid=0\n", + (unsigned) cpu.tr.sel.raw, (unsigned) LowDWord(cpu.tr.des), + (unsigned) HighDWord(cpu.tr.des), (unsigned) cpu.tr.valid); + + fprintf(stderr, "gdtr:base=0x0, limit=0x0\n", + (unsigned) cpu.gdtr.base, (unsigned) cpu.gdtr.limit); + + fprintf(stderr, "idtr:base=0x0, limit=0x0\n", + (unsigned) cpu.idtr.base, (unsigned) cpu.idtr.limit); + + fprintf(stderr, "dr0:0x0\n", (unsigned) cpu.dr0); + fprintf(stderr, "dr1:0x0\n", (unsigned) cpu.dr1); + fprintf(stderr, "dr2:0x0\n", (unsigned) cpu.dr2); + fprintf(stderr, "dr3:0x0\n", (unsigned) cpu.dr3); + fprintf(stderr, "dr6:0x0\n", (unsigned) cpu.dr6); + fprintf(stderr, "dr7:0x0\n", (unsigned) cpu.dr7); + + fprintf(stderr, "tr3:0x0\n", (unsigned) cpu.tr3); + fprintf(stderr, "tr4:0x0\n", (unsigned) cpu.tr4); + fprintf(stderr, "tr5:0x0\n", (unsigned) cpu.tr5); + fprintf(stderr, "tr6:0x0\n", (unsigned) cpu.tr6); + fprintf(stderr, "tr7:0x0\n", (unsigned) cpu.tr7); + + fprintf(stderr, "cr0:0x0\n", (unsigned) cpu.cr0); + fprintf(stderr, "cr1:0x0\n", (unsigned) cpu.cr1); + fprintf(stderr, "cr2:0x0\n", (unsigned) cpu.cr2); + fprintf(stderr, "cr3:0x0\n", (unsigned) cpu.cr3); + fprintf(stderr, "cr4:0x0\n", (unsigned) cpu.cr4); + + fprintf(stderr, "inhibit_mask:0\n", cpu.inhibit_mask); + + + /* dump the guest context */ + + memset (&ctx, 0, sizeof (ctx)); + memset (&instr, 0, sizeof (instr)); + + if (!cpu.cs.valid) { + fprintf(stderr, "vm_debug_exception: CS.valid=0\n"); + return 0; + } + if (cpu.cr0 & 1) { + if (cpu.eflags & 0x20000) + ctx.mode = VM86; + else if (cpu.cs.des.d_b) + ctx.mode = CODE32; + else + ctx.mode = CODE16; + } + else { /* Real Mode */ + ctx.mode = VM86; + } + seg_base_ptr = ptr + BaseOfDescriptor(cpu.cs.des); + ctx.base = seg_base_ptr; + ctx.segment = cpu.cs.sel.raw; + ctx.offset = cpu.eip; + + + if (!i386_decode (&ctx, &instr) || !i386_decode_text (&ctx, &instr, text, vm_conf.syntax)) + strcpy (text, "???"); + else + len = instr.length; + + sprintf (prefix, "0000.00000000 ", cpu.cs.sel.raw, cpu.eip); + + for (i = 0; i < len && i < 12; i++) + sprintf (prefix + strlen (prefix), "00", + ((unsigned char *) seg_base_ptr)[cpu.eip + i]); + for (; i < 12; i++) + strcat (prefix, " "); + + + fprintf (stderr, "Stack dump:\n"); + #if 0 + for (i = 0; i < 4; i++) + fprintf (stderr, " 00000000: 00000000 00000000 00000000 00000000\n", + context.esp + 16 * i, + *(unsigned long *) (ptr + context.esp + 16 * i), + *(unsigned long *) (ptr + context.esp + 16 * i + 4), + *(unsigned long *) (ptr + context.esp + 16 * i + 8), + *(unsigned long *) (ptr + context.esp + 16 * i + 12)); + fprintf (stderr, "\n"); + #endif + + fprintf (stderr, "Current instruction:\n"); + fprintf (stderr, " \n", prefix, text); + fprintf (stderr, "\n"); + + return 1; + } + + void + vm_register_callback(const char *command, void (*f)(unsigned char *)) + { + callback_command_t *entry; + + entry = malloc( sizeof(callback_command_t) ); + if (!entry) { + fprintf(stderr, "vm_register_callback: malloc failed\n"); + exit(1); + } + entry->next = callback_command_list; + callback_command_list = entry; + entry->command = command; + entry->f = f; + } + + + unsigned + vm_load_rom(const char *path, Bit32u address) + { + struct stat stat_buf; + int fileno; + unsigned char *image; + int read; + + fileno = _open(path, _O_RDONLY | _O_BINARY); + if (fileno < 0) { + fprintf(stderr, "rom: open : \n", path, strerror(errno)); + return 1; + } + if (fstat(fileno, &stat_buf) != 0) { + fprintf(stderr, "rom: fstat : \n", path, strerror(errno)); + return 1; + } + + fprintf(stderr, "ROM: loading image '' @ 0x0 (0 bytes)\n", + path, address, (unsigned) stat_buf.st_size); + + if ((image = (void *) malloc (stat_buf.st_size)) == NULL) { + perror("rom: malloc"); + return 1; + } + if ( ( read = _read(fileno, image, stat_buf.st_size) ) != stat_buf.st_size) { + perror ("rom: read"); + return 1; + } + close(fileno); + + if (vm_write_physical(address, stat_buf.st_size, image)) { + fprintf (stderr, "rom: trying to load beyond available VM memory.\n"); + return 1; + } + + free(image); + + return 0; + } + + unsigned + linux_hack(void) + { + Bit32u data; + + /* +++ Enable A20 line */ + /*BX_SET_ENABLE_A20( 1 ); */ + + /* Setup PICs the way Linux likes it */ + data = 0x11; plugin_emulate_outport( 0x20, 1, 1, &data); + data = 0x11; plugin_emulate_outport( 0xA0, 1, 1, &data); + data = 0x20; plugin_emulate_outport( 0x21, 1, 1, &data); + data = 0x28; plugin_emulate_outport( 0xA1, 1, 1, &data); + data = 0x04; plugin_emulate_outport( 0x21, 1, 1, &data); + data = 0x02; plugin_emulate_outport( 0xA1, 1, 1, &data); + data = 0x01; plugin_emulate_outport( 0x21, 1, 1, &data); + data = 0x01; plugin_emulate_outport( 0xA1, 1, 1, &data); + data = 0xFF; plugin_emulate_outport( 0x21, 1, 1, &data); + data = 0xFB; plugin_emulate_outport( 0xA1, 1, 1, &data); + + /* Disable interrupts and NMIs */ + /*BX_CPU_THIS_PTR eflags.if_ = 0; */ + data = 0x80; plugin_emulate_outport( 0x70, 1, 1, &data); + + /* Enter protected mode */ + /*BX_CPU_THIS_PTR cr0.pe = 1; */ + + /* Set up initial GDT */ + /*BX_CPU_THIS_PTR gdtr.limit = 0x400; */ + /*BX_CPU_THIS_PTR gdtr.base = 0x00090400; */ + + /* Jump to protected mode entry point */ + /*BX_CPU_THIS_PTR jump_protected( NULL, 0x10, 0x00100000 ); */ + + return 0; + } + + unsigned + plugin_get_A20E(void) + { + return a20_val > 0; + } + + void + plugin_set_A20E(unsigned val) + { + DWORD dwOutBytes; + + a20_val = val; + + if ( !DeviceIoControl( hDriver, + PLEX86_SET_A20, + &val, + sizeof(val), + NULL, + 0UL, + &dwOutBytes, + NULL ) ) + { + ReportError("DeviceIoControl(PLEX86_SET_A20)",0UL); + vm_abort(); + } + } *** user/plugins/makefile.nt Wed Dec 31 14:00:00 1969 --- user/plugins/makefile.nt Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,38 ---- + # Generated automatically from Makefile.in by configure. + # plex86: run multiple x86 operating systems concurrently + # Copyright (C) 1999-2000 Kevin P. Lawton + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public + # License as published by the Free Software Foundation; either + # version 2 of the License, or (at your option) any later version. + # + # This library is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # Lesser General Public License for more details. + # + # You should have received a copy of the GNU Lesser General Public + # License along with this library; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + srcdir = . + + all: + $(MAKE) -C bochs -f makefile.nt $(MDEFINES) + # $(MAKE) -C ice -f makefile.nt $(MDEFINES) + # $(MAKE) -C loader -f makefile.nt $(MDEFINES) + # $(MAKE) -C misc -f makefile.nt $(MDEFINES) + + clean: + $(MAKE) -C bochs -f makefile.nt clean + # $(MAKE) -C ice -f makefile.nt clean + # $(MAKE) -C loader -f makefile.nt clean + # $(MAKE) -C misc -f makefile.nt clean + + dist-clean: + $(MAKE) -C bochs -f makefile.nt dist-clean + # $(MAKE) -C ice -f makefile.nt dist-clean + # $(MAKE) -C loader -f makefile.nt dist-clean + # $(MAKE) -C misc -f makefile.nt dist-clean + *** user/plugins/bochs/bochs.def Wed Dec 31 14:00:00 1969 --- user/plugins/bochs/bochs.def Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,4 ---- + EXPORTS + + plugin_init @1 + plugin_fini @2 \ No newline at end of file *** user/plugins/bochs/Makefile.nt Wed Dec 31 14:00:00 1969 --- user/plugins/bochs/Makefile.nt Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,89 ---- + # Generated automatically from Makefile.in by configure. + # plex86: run multiple x86 operating systems concurrently + # Copyright (C) 1999-2000 The plex86 developers team + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public + # License as published by the Free Software Foundation; either + # version 2 of the License, or (at your option) any later version. + # + # This library is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # Lesser General Public License for more details. + # + # You should have received a copy of the GNU Lesser General Public + # License along with this library; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + .SUFFIXES: .cc + + SHELL = /bin/sh + + + + CC = gcc + RANLIB = ranlib + CFLAGS = -g -O2 -Wall -Wstrict-prototypes -fnative-struct + LDFLAGS = + CXX = c++ + CXXFLAGS = -g -O2 -Wall -Wstrict-prototypes -fnative-struct + + srcdir = . + + X_LIBS = + X_PRE_LIBS = + GUI_LINK_OPTS_X = $(X_LIBS) $(X_PRE_LIBS) -lX11 + GUI_LINK_OPTS_BEOS = -lbe + GUI_LINK_OPTS_WIN32 = -luser32 -lgdi32 -lwinmm -lcomdlg32 -lcomctl32 + GUI_LINK_OPTS_WIN32_VCPP = user32.lib gdi32.lib winmm.lib \ + comdlg32.lib comctl32.lib wsock32.lib + GUI_LINK_OPTS_NOGUI = + GUI_LINK_OPTS_SDL = `sdl-config --libs` + GUI_LINK_OPTS = $(GUI_LINK_OPTS_WIN32) + + ALL: bochs.dll + + .c.o: + $(CC) -I../../.. -I$(srcdir)/../../.. -I$(srcdir)/../.. -I$(srcdir) $(CFLAGS) -c $< + .cc.o: + $(CXX) -I../../.. -I$(srcdir)/../../.. -I$(srcdir)/../.. -I$(srcdir) $(CXXFLAGS) -c $< + + bochs.dll: io.o pc_system.o state_file.o iodev/libiodev.a gui/libgui.a + # gcc -o bochs.dll -mdll -Wl,-shared,--export-all-symbols \ + # -lwsock32 -luser32 -lkernel32 \ + # io.o pc_system.o state_file.o iodev/libiodev.a \ + # gui/libgui.a ../../libplex86.a + dllwrap -o bochs.dll --def bochs.def \ + io.o pc_system.o state_file.o \ + iodev/libiodev.a gui/libgui.a ../../libplex86.a \ + -lwsock32 -lgdi32 + # d:/gcc-2.95.2/i386-mingw32/lib/libgdi32.a + + plugin-bochs.a: io.o pc_system.o state_file.o iodev/libiodev.a gui/libgui.a + -del $@ + ar rv $@ io.o pc_system.o state_file.o iodev/libiodev.a gui/libgui.a + $(RANLIB) $@ + + iodev/libiodev.a: + cd iodev && \ + $(MAKE) -f makefile.nt $(MDEFINES) libiodev.a + echo done + + gui/libgui.a: + cd gui && \ + $(MAKE) -f makefile.nt $(MDEFINES) libgui.a + echo done + + clean: + $(MAKE) -C iodev -f makefile.nt clean + $(MAKE) -C gui -f makefile.nt clean + -del *.o plugin-bochs.a core + + dist-clean: clean + $(MAKE) -C iodev dist-clean + $(MAKE) -C gui dist-clean + /bin/rm -f Makefile + + Makefile: Makefile.in ../../../config.status + cd ../../../; CONFIG_FILES=user/plugins/bochs/Makefile CONFIG_HEADERS= $(SHELL) config.status *** user/plugins/bochs/iodev/makefile.nt Wed Dec 31 14:00:00 1969 --- user/plugins/bochs/iodev/makefile.nt Fri Feb 22 21:50:04 2002 *************** *** 0 **** --- 1,90 ---- + # Generated automatically from Makefile.in by configure. + # Makefile for the iodev component of bochs + + # Copyright (C) 1994-2000 Kevin P. Lawton + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public + # License as published by the Free Software Foundation; either + # version 2 of the License, or (at your option) any later version. + # + # This library is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # Lesser General Public License for more details. + # + # You should have received a copy of the GNU Lesser General Public + # License along with this library; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + + .SUFFIXES: .cc + + + CXX = c++ + CXXFLAGS = -g -O2 -Wall -Wstrict-prototypes -fnative-struct + + LDFLAGS = + LIBS = + RANLIB = ranlib + + srcdir = . + + VIDEO_OBJS_VGA = vga.o + VIDEO_OBJS_HGA = hga.o + VIDEO_OBJS = $(VIDEO_OBJS_VGA) + + BX_INCDIRS = -I../../../.. -I$(srcdir)/../../../.. -I$(srcdir)/../../.. -I$(srcdir)/.. -I$(srcdir)/../instrument/ + LOCAL_CXXFLAGS = $(MCH_CFLAGS) + + SB16_DUMMY_OBJS = sb16.o + SB16_LINUX_OBJS = sb16.o soundlnx.o + SB16_WIN_OBJS = sb16.o soundwin.o + + + + BX_HW_IODEV_OBJS = \ + devices.o \ + pic.o \ + pit.o \ + unmapped.o \ + cmos.o \ + dma.o \ + floppy.o \ + harddrv.o \ + keyboard.o \ + parallel.o \ + serial.o \ + $(SB16_WIN_OBJS ) \ + $(VIDEO_OBJS) + + + BX_IODEV_OBJS = $(BX_HW_IODEV_OBJS) + + BX_OBJS = $(BX_IODEV_OBJS) + + BX_INCLUDES = iodev.h + + .cc.o: + $(CXX) -I../../../.. -I$(srcdir)/../../../.. -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(BX_INCDIRS) $< -o $@ + + + + libiodev.a: $(BX_OBJS) + -del libiodev.a + ar rv $@ $(BX_IODEV_OBJS) + ranlib libiodev.a + + $(BX_OBJS): $(BX_INCLUDES) + + + clean: + -del *.o + -del *.a + + dist-clean: clean + del Makefile + + Makefile: Makefile.in ../../../../config.status + cd ../../../../; CONFIG_FILES=user/plugins/bochs/iodev/Makefile CONFIG_HEADERS= $(SHELL) config.status *** descriptor.h 22 Feb 2002 20:20:42 -0000 1.1.1.1 --- descriptor.h 22 Feb 2002 20:55:20 -0000 *************** *** 118,120 **** --- 118,121 ---- #define RPL3 3 #endif /* __DESCRIPTOR_H__ */ + *** plex86.h 22 Feb 2002 20:37:28 -0000 1.1.1.2 --- plex86.h 22 Feb 2002 20:55:23 -0000 *************** *** 57,62 **** --- 57,66 ---- #define ICOUNT_INDEFINITE ((icount_t) 0) #define ICOUNT_CONTINUE (((icount_t) 0) - 1) + typedef struct + { + int nVal1; + } Test1; typedef struct { selector_t sel; *************** *** 93,101 **** - - - /* ========================================================== */ /* Messages which are passed between the user program (u) and */ /* the monitor (m) of the VM. */ --- 97,102 ---- *************** *** 254,307 **** * ioctl() names */ ! #if defined(__linux__) || defined(__NetBSD__) || defined(__FreeBSD__) ! #ifdef __linux__ ! #include <asm/ioctl.h> ! #else ! #include <sys/ioccom.h> #endif ! #define PLEX86_ALLOCVPHYS _IO('k', 2) ! #define PLEX86_ALLOCINT _IO('k', 3) ! #define PLEX86_RELEASEINT _IO('k', 4) ! #define PLEX86_RESET _IO('k', 5) ! #define PLEX86_MESSAGEQ _IO('k', 6) ! #define PLEX86_TEARDOWN _IO('k', 7) ! #define PLEX86_SETINTR _IO('k', 8) ! #define PLEX86_PRESCANDEPTH _IO('k', 9) ! #define PLEX86_SET_CPU _IOW('k', 12, guest_cpu_t) ! #define PLEX86_RESET_CPU _IO('k', 13) ! #define PLEX86_GET_CPU _IOR('k', 14, guest_cpu_t) ! #define PLEX86_FORCE_INT _IO('k', 15) ! #define PLEX86_SET_A20 _IO('k', 16) ! #define PLEX86_PHYMEM_MOD _IO('k', 17) ! #define PLEX86_PRESCANRING3 _IO('k', 18) ! #define PLEX86_GENERIC _IO('k', 19) ! #define PLEX86_REGTIMER _IO('k', 20) ! #define PLEX86_ACTTIMER _IO('k', 21) ! #define PLEX86_DEACTTIMER _IO('k', 22) ! #define PLEX86_REGIO _IO('k', 23) ! #define PLEX86_IRQ _IO('k', 24) #else ! #define PLEX86_ALLOCVPHYS 0x6b02 ! #define PLEX86_ALLOCINT 0x6b03 ! #define PLEX86_RELEASEINT 0x6b04 ! #define PLEX86_RESET 0x6b05 ! #define PLEX86_MESSAGEQ 0x6b06 ! #define PLEX86_TEARDOWN 0x6b07 ! #define PLEX86_SETINTR 0x6b08 ! #define PLEX86_PRESCANDEPTH 0x6b09 ! #define PLEX86_SET_CPU 0x6b0c ! #define PLEX86_RESET_CPU 0x6b0d ! #define PLEX86_GET_CPU 0x6b0e ! #define PLEX86_FORCE_INT 0x6b0f ! #define PLEX86_SET_A20 0x6b10 ! #define PLEX86_PHYMEM_MOD 0x6b11 ! #define PLEX86_PRESCANRING3 0x6b12 ! #define PLEX86_REGTIMER 0x6b13 ! #define PLEX86_ACTTIMER 0x6b14 ! #define PLEX86_DEACTTIMER 0x6b15 ! #define PLEX86_REGIO 0x6b16 ! #define PLEX86_IRQ 0x6b17 #endif --- 255,335 ---- * ioctl() names */ ! #if defined( _WIN32 ) ! ! /* Plex86 device type - in the user defined range */ ! #define PLEX86_DEVICE_TYPE 0x00008000 ! ! /* Plex86 function index */ ! #define PLEX86_IOCTL_INDEX 0x900 ! ! #if !defined( FILE_ANY_ACCESS ) ! #define FILE_ANY_ACCESS 0 ! #define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) ! #define FILE_READ_ACCESS ( 0x0001 ) ! #define FILE_WRITE_ACCESS ( 0x0002 ) #endif ! ! #if !defined( METHOD_BUFFERED ) ! #define METHOD_BUFFERED 0 ! #define METHOD_IN_DIRECT 1 ! #define METHOD_OUT_DIRECT 2 ! #define METHOD_NEITHER 3 ! #endif ! ! /* Equivalent to the CTL_CODE macro from NT DDK */ ! #define PLEX86_IOCTL_CODE( FunctionIdx ) ( \ ! ( ( ( Bit32u )PLEX86_DEVICE_TYPE) << 16) | \ ! ( FILE_ANY_ACCESS << 14) | \ ! ( (PLEX86_IOCTL_INDEX + FunctionIdx ) << 2 ) | \ ! METHOD_BUFFERED ) ! ! #define PLEX86_IOCTL_CODE_RD( FunctionIdx, Length ) \ ! PLEX86_IOCTL_CODE( FunctionIdx ) ! #define PLEX86_IOCTL_CODE_WR( FunctionIdx, Length ) \ ! PLEX86_IOCTL_CODE( FunctionIdx ) ! ! #elif defined(__linux__) || defined(__NetBSD__) ! #ifdef __linux__ ! #include <asm/ioctl.h> ! #else ! #include <sys/ioccom.h> ! #endif ! ! #define PLEX86_IOCTL_CODE( FunctionIdx ) \ ! _IO('k', FunctionIdx + 2) ! #define PLEX86_IOCTL_CODE_RD( FunctionIdx, Length ) \ ! _IOR('k', FunctionIdx + 2, Length) ! #define PLEX86_IOCTL_CODE_WR( FunctionIdx, Length ) \ ! _IOW('k', FunctionIdx + 2, Length) #else ! ! #define PLEX86_IOCTL_CODE(x) ( 0x6b02 + x ) ! ! #endif ! ! #define PLEX86_ALLOCVPHYS PLEX86_IOCTL_CODE(0) ! #define PLEX86_ALLOCINT PLEX86_IOCTL_CODE(1) ! #define PLEX86_RELEASEINT PLEX86_IOCTL_CODE(2) ! #define PLEX86_RESET PLEX86_IOCTL_CODE(3) ! #define PLEX86_MESSAGEQ PLEX86_IOCTL_CODE(4) ! #define PLEX86_TEARDOWN PLEX86_IOCTL_CODE(5) ! #define PLEX86_SETINTR PLEX86_IOCTL_CODE(6) ! #define PLEX86_PRESCANDEPTH PLEX86_IOCTL_CODE(7) ! #define PLEX86_SET_CPU PLEX86_IOCTL_CODE_WR(8,sizeof(guest_cpu_t)) ! #define PLEX86_RESET_CPU PLEX86_IOCTL_CODE(9) ! #define PLEX86_GET_CPU PLEX86_IOCTL_CODE_RD(10,sizeof(guest_cpu_t)) ! #define PLEX86_FORCE_INT PLEX86_IOCTL_CODE(11) ! #define PLEX86_SET_A20 PLEX86_IOCTL_CODE(12) ! #define PLEX86_PHYMEM_MOD PLEX86_IOCTL_CODE(13) ! #define PLEX86_PRESCANRING3 PLEX86_IOCTL_CODE(14) ! ! #if defined( _WIN32 ) ! // NT specific IOCTLs for mmap functionality ! #define PLEX86_MMAP_GUESTMEM PLEX86_IOCTL_CODE(20) ! #define PLEX86_UNMAP_GUESTMEM PLEX86_IOCTL_CODE(21) ! #define PLEX86_MMAP_PRINTMEM PLEX86_IOCTL_CODE(22) ! #define PLEX86_UNMAP_PRINTMEM PLEX86_IOCTL_CODE(23) #endif *** kernel/host-all.c 22 Feb 2002 20:20:44 -0000 1.1.1.1 --- kernel/host-all.c 22 Feb 2002 20:55:26 -0000 *************** *** 28,33 **** --- 28,37 ---- cpuid_info_t cpuid_info; + #if defined( WIN32 ) + extern unsigned DbgPrint( const char* Format, ... ); + #endif + void ioctlSetIntr(vm_t *vm, unsigned long intr) *************** *** 498,503 **** --- 502,510 ---- where = 15; goto error; } + + DbgPrint( "** Allocated Nexus page (0x0)\n", ad->nexus ); + if ( !(pg->nexus = host_map_page(ad->nexus)) ) { where = 16; goto error; *** kernel/host-monitor.c 22 Feb 2002 20:20:44 -0000 1.1.1.1 --- kernel/host-monitor.c 22 Feb 2002 20:55:29 -0000 *************** *** 31,36 **** --- 31,40 ---- /* Declarations */ /************************************************************************/ + #if defined( WIN32 ) + extern unsigned DbgPrint( const char* Format, ... ); + #endif + unsigned redir_cnt[256]; static int init_idt_slot(vm_t *vm, unsigned vec, int type); *************** *** 58,64 **** ((laddr) - (monitor_pages.start_addr & ~0xfff)) ! static selector_t nullSelector = { raw: 0 }; --- 62,68 ---- ((laddr) - (monitor_pages.start_addr & ~0xfff)) ! static selector_t nullSelector = { 0 }; *************** *** 133,139 **** goto error; copy_memory(vm->host.addr.nexus, &__nexus_start, nexus_size); - /* Init the convenience pointers. */ /* Pointer to host2mon routine inside nexus page */ --- 137,142 ---- *************** *** 204,209 **** --- 207,214 ---- laddr = 0; base = MON_BASE_FROM_LADDR(laddr); + DbgPrint( "-- Before mapping, laddr=0x0,base=0x0\n", laddr, base ); + map_mon_pages(vm, monitor_pages.page, monitor_pages.n_pages, &laddr, pageTable); #if ANAL_CHECKS *************** *** 211,216 **** --- 216,225 ---- #endif vm->guest.addr.nexus = (nexus_t *) (laddr - base); + + DbgPrint( " After mapping monitor pages, laddr=0x0\n", laddr ); + DbgPrint( " vm->guest.addr.nexus=0x0,vm->host.addr.nexus=0x0\n", vm->guest.addr.nexus,vm->host.addr.nexus ); + map_mon_pages(vm, &vm->pages.nexus, 1, &laddr, pageTable); vm->guest.addr.guest_context = (guest_context_t *) ( (Bit32u)vm->guest.addr.nexus + PAGESIZE - *************** *** 220,225 **** --- 229,238 ---- map_blank_page(vm, &laddr, pageTable); #endif vm->host.addr.nexus->vm = (void *) (laddr - base); + + DbgPrint( " After mapping nexus, laddr=0x0\n", laddr ); + DbgPrint( " vm->host.addr.nexus->vm=0x0\n", vm->host.addr.nexus->vm ); + map_mon_pages(vm, vm->pages.vm, BYTES2PAGES(sizeof(*vm)), &laddr, pageTable); *************** *** 348,354 **** /* Pointer to mon2host routine inside nexus page */ vm->guest.__mon2host = (void (*)(void)) MON_NEXUS_OFFSET(vm, __mon2host); - /* * ===================== * Transition Page Table --- 361,366 ---- *************** *** 374,383 **** --- 386,403 ---- */ /* Get full linear address of nexus code page, as seen in host space. */ + #if 0 laddr = (Bit32u)vm->host.addr.nexus + kernel_offset; + #else + laddr = host_map_page( vm->host.addr.nexus ) * 4096; + #endif + pdi = laddr >> 22; pti = (laddr >> 12) & 0x3ff; + DbgPrint( "-- vm->host.addr.nexus = 0x0\n", vm->host.addr.nexus ); + DbgPrint( "-- laddr = 0x0, pdi = 0x0, pti = 0x0\n", laddr, pdi, pti ); + /* * We need to be able to access the PDE in the monitor page directory * that corresponds to this linear address from both host and monitor *************** *** 447,452 **** --- 467,474 ---- vm->host.addr.nexus->mon_stack_info.offset = vm->host.addr.tss->esp0 - (sizeof(guest_context_t) + 40); + vm->host.addr.nexus->mikey_hack = MON_NEXUS_OFFSET(vm, __mon_cs); + DbgPrint( "-- mikey_hack = 0x0\n", vm->host.addr.nexus->mikey_hack ); /* * Setup the IDT for the monitor/guest environment *************** *** 797,803 **** pti = (*laddr_p >> 12) & 0x3ff; for (i = 0; i < n; i++, pti++) { ! if (pti > 1024) break; /* This should not happen! */ /* Fill in the PTE flags */ --- 819,825 ---- pti = (*laddr_p >> 12) & 0x3ff; for (i = 0; i < n; i++, pti++) { ! if (pti >= 1024) break; /* This should not happen! */ /* Fill in the PTE flags */ *************** *** 828,834 **** unsigned pti; pti = (*laddr_p >> 12) & 0x3ff; ! if (pti > 1024) return; /* This should not happen! */ /* Fill in the PTE flags */ --- 850,856 ---- unsigned pti; pti = (*laddr_p >> 12) & 0x3ff; ! if (pti >= 1024) return; /* This should not happen! */ /* Fill in the PTE flags */ *************** *** 871,876 **** --- 893,904 ---- { unsigned long eflags; + DbgPrint( "** Before __host2mon() ( 0x0)\n", vm->host.__host2mon ); + + DbgPrint( "** mon_cr0 = 0x0\n", vm->host.addr.nexus->mon_cr0 ); + DbgPrint( "** mon_cr3 = 0x0\n", vm->host.addr.nexus->mon_cr3 ); + DbgPrint( "** mon_cr4 = 0x0\n", vm->host.addr.nexus->mon_cr4 ); + vm_save_flags(eflags); vm_restore_flags(eflags & ~0x00004300); /* clear NT/IF/TF */ #if ANAL_CHECKS *************** *** 882,890 **** --- 910,954 ---- } #endif + #if 1 + { + Bit32u uActual = vm->host.addr.nexus->mikey_hack; + Bit16u uSelector = vm->host.addr.nexus->mon_stack_info.selector; + Bit32u uBase = BaseOfDescriptor( vm->addr->gdt[ uSelector >> 3 ] ); + Bit32u uLinear = uBase + uActual; + pageEntry_t* ptPDE = &vm->addr->page_dir[ uLinear >> 22 ]; + Bit32u uPTI = ( uLinear << 10 ) >> 22; + pageEntry_t* ptPTE = &vm->addr->nexus_page_tbl->pte[ uPTI ]; + + DbgPrint( "++ Paging checks before host2mon() ++\n" ); + DbgPrint( " uActual = 0x0\n", uActual ); + DbgPrint( " uSelector = 0x0, uBase = 0x0\n", uSelector, uBase ); + DbgPrint( " uLinear = 0x0\n", uLinear ); + DbgPrint( " ptPDE = 0x0\n", ptPDE ); + DbgPrint( " ptPDE->fields.base = 0x0\n", ptPDE->fields.base ); + DbgPrint( " ptPDE->fields.P = 0\n", ptPDE->fields.P ? 1 : 0 ); + DbgPrint( " vm->pages.nexus_page_tbl = 0x0\n", vm->pages.nexus_page_tbl ); + DbgPrint( " vm->pages.transition_PT = 0x0\n", vm->pages.transition_PT ); + DbgPrint( " uPTI = 0x0\n", uPTI ); + DbgPrint( " ptPTE = 0x0\n", ptPTE ); + DbgPrint( " ptPTE->fields.base = 0x0\n", ptPTE->fields.base ); + DbgPrint( " ptPTE->fields.P = 0\n", ptPTE->fields.P ? 1 : 0 ); + DbgPrint( " ptPTE->fields.RW = 0\n", ptPTE->fields.RW ? 1 : 0 ); + DbgPrint( " ptPTE->fields.US = 0\n", ptPTE->fields.US ? 1 : 0 ); + DbgPrint( " vm->pages.nexus = 0x0\n", vm->pages.nexus ); + DbgPrint( "-------------------------------------\n" ); + } + #endif + /* Call assembly routine to effect transition. */ vm->addr = &((vm_t *)vm->host.addr.nexus->vm)->guest.addr; + + // NT_PREMON_IRQL_HACK(); + vm->host.__host2mon(); + + // NT_POSTMON_IRQL_HACK(); + vm->addr = &vm->host.addr; /* First check for an asynchronous event (interrupt redirection) */ *************** *** 900,905 **** --- 964,980 ---- else { vm_restore_flags(eflags); + + DbgPrint( "** After __host2mon()\n" ); + DbgPrint( "** host_cr0 = 0x0\n", vm->host.addr.nexus->host_cr0 ); + DbgPrint( "** host_cr3 = 0x0\n", vm->host.addr.nexus->host_cr3 ); + DbgPrint( "** host_cr4 = 0x0\n", vm->host.addr.nexus->host_cr4 ); + DbgPrint( "** new_ss = 0x0\n", vm->host.addr.nexus->new_ss ); + DbgPrint( "** old_ss = 0x0\n", vm->host.addr.nexus->old_ss ); + DbgPrint( "** old_ds = 0x0\n", vm->host.addr.nexus->old_ds ); + DbgPrint( "** old_cs = 0x0\n", vm->host.addr.nexus->old_cs ); + + DbgPrint( "-- vm->mon_request = 0x0\n", vm->mon_request ); /* Perform action requested by monitor */ switch ( vm->mon_request ) *** kernel/mon-fault.c 22 Feb 2002 20:20:44 -0000 1.1.1.1 --- kernel/mon-fault.c 22 Feb 2002 20:55:32 -0000 *************** *** 25,31 **** #include "monitor.h" - /* The monitor stack frame. When an exception or interrupt occurrs * during the execution of either guest or monitor code, the following * values are pushed. --- 25,30 ---- *************** *** 98,105 **** * (due to virtualization conditions or natural fault generation) or * from the monitor (currently only due to bugs in the monitor). */ ! ".globl __handle_fault \n\t" ! "__handle_fault: \n\t" " pushal \n\t" /* Save general registers */ " pushl 0.000000e+00s \n\t" /* Save segment registers */ " pushl 0s \n\t" --- 97,109 ---- * (due to virtualization conditions or natural fault generation) or * from the monitor (currently only due to bugs in the monitor). */ ! #if defined( WIN32 ) ! ".globl ___handle_fault \n" /* Start function ___handle_fault() */ ! "___handle_fault: \n" ! #else ! ".globl __handle_fault \n" /* Start function __handle_fault() */ ! "__handle_fault: \n" ! #endif " pushal \n\t" /* Save general registers */ " pushl 0.000000e+00s \n\t" /* Save segment registers */ " pushl 0s \n\t" *************** *** 121,130 **** --- 125,144 ---- " movl 0.000000e+00ax, 0s \n" " movl 0.000000e+00ax, 0.000000e+00s \n" " cld \n" /* gcc-compiled code needs this */ + #if defined( WIN32 ) + " call _handle_fault \n" /* Call the C monitor fault handler */ + ".globl ___ret_to_guest \n" /* Fault handled, work back to guest */ + "___ret_to_guest: \n" + #else " call handle_fault \n" /* Call the C monitor fault handler */ ".globl __ret_to_guest \n" /* Fault handled, work back to guest */ "__ret_to_guest: \n" + #endif + #if defined( WIN32 ) + " call _sbe \n" /* Prepare for return to guest */ + #else " call sbe \n" /* Prepare for return to guest */ + #endif " cmpl $0x1, 0.000000e+00ax \n" /* What mode is guest monitored in? */ " jb __ret_to_v86 \n" /* case 0: guest monitored in v86 mode */ " jnz __ret_to_pmss16 \n" /* case 2: guest monitored in PM w/ small SS */ *************** *** 158,171 **** --- 172,193 ---- " movl 0.000000e+00sp, 0.000000e+00bx \n\t" /* Get nexus page address */ " andl $0xfffff000, 0.000000e+00bx \n\t" " movl $__SSNormal, 0.000000e+00dx \n\t" /* Create a pointer to SSNormal */ + #if defined( WIN32 ) + " subl $___nexus_start, 0.000000e+00dx \n\t" + #else " subl $__nexus_start, 0.000000e+00dx \n\t" + #endif " ss; movl (0.000000e+00bx,0.000000e+00dx), 0.000000e+00cx \n\t" /* Get SSNormal */ " movl s, 0.000000e+00ax \n\t" /* Get current SS */ " cmpw x, %ax \n\t" /* Compare SS with SSNormal */ " je __mon_SS_ESP_restored \n\t" /* If same, then no restore needed */ " movl $__espUpperNormal, 0.000000e+00dx \n\t" /* Get pointer to espUpperNormal */ + #if defined( WIN32 ) + " subl $___nexus_start, 0.000000e+00dx \n\t" + #else " subl $__nexus_start, 0.000000e+00dx \n\t" + #endif " ss; movl (0.000000e+00bx,0.000000e+00dx), 0.000000e+00ax \n\t" /* Get espUpperNormal */ " andl $0x0000ffff, 0.000000e+00sp \n\t" /* Clear upper ESP bits */ " orl 0.000000e+00ax, 0.000000e+00sp \n\t" /* Restore upper ESP bits */ *************** *** 176,182 **** --- 198,208 ---- " movl 0.000000e+00ax, 0s \n\t" " movl 0.000000e+00ax, 0.000000e+00s \n\t" " cld \n\t" /* gcc-compiled code needs this */ + #if defined( WIN32 ) + " call _handle_mon_fault \n\t" /* Call C code for real work */ + #else " call handle_mon_fault \n\t" /* Call C code for real work */ + #endif " jmp __ret_to_monitor \n\t" /* Event handled, back to monitor */ /* (Currently never gets here) */ *************** *** 195,204 **** --- 221,238 ---- " movl 0.000000e+00sp, 0.000000e+00bx \n\t" /* Get nexus page addr */ " andl $0xfffff000, 0.000000e+00bx \n\t" " movl $__espUpper16BitSSHack, 0.000000e+00dx \n\t" /* Get ptr to nexus field */ + #if defined( WIN32 ) + " subl $___nexus_start, 0.000000e+00dx \n\t" + #else " subl $__nexus_start, 0.000000e+00dx \n\t" + #endif " movl (0.000000e+00bx,0.000000e+00dx), 0.000000e+00ax \n\t" /* Access nexus field */ " movl $__SS16BitSSHack, 0.000000e+00dx \n\t" /* Get ptr to nexus field */ + #if defined( WIN32 ) + " subl $___nexus_start, 0.000000e+00dx \n\t" + #else " subl $__nexus_start, 0.000000e+00dx \n\t" + #endif " movl (0.000000e+00bx,0.000000e+00dx), 0.000000e+00cx \n\t" /* Access nexus field */ " andl $0x0000ffff, 0.000000e+00sp \n\t" /* Clear upper ESP bits */ " orl 0.000000e+00ax, 0.000000e+00sp \n\t" /* Use alternate ESP upper bits */ *************** *** 237,244 **** --- 271,283 ---- /* * Hardware interrupt handler stub */ + #if defined WIN32 + ".globl ___handle_int \n" /* Return to monitor code */ + "___handle_int: \n" + #else ".globl __handle_int \n" /* Return to monitor code */ "__handle_int: \n" + #endif " pushal \n" /* Save guest general registers */ " pushl 0.000000e+00s \n" /* Save guest segment registers */ " pushl 0s \n" *************** *** 249,258 **** --- 288,305 ---- " movl 0.000000e+00ax, 0s \n" " movl 0.000000e+00ax, 0.000000e+00s \n" " cld \n" /* gcc-compiled code needs this */ + #if defined( WIN32 ) + " call _handle_int \n" /* monitor interrupt handler */ + #else " call handle_int \n" /* monitor interrupt handler */ + #endif " cmpl $0x1, 0.000000e+00ax \n" /* Was interrupt generated from monitor code? */ " je __ret_to_monitor\n" /* Yes, so return to monitor code */ + #if defined( WIN32 ) + " jmp ___ret_to_guest \n" /* No, so return to guest code */ + #else " jmp __ret_to_guest \n" /* No, so return to guest code */ + #endif ); *** kernel/nexus-mode.c 22 Feb 2002 20:20:44 -0000 1.1.1.1 --- kernel/nexus-mode.c 22 Feb 2002 20:55:34 -0000 *************** *** 27,32 **** --- 27,36 ---- #include "monitor.h" + #if defined( WIN32 ) + extern unsigned DbgPrint( const char* Format, ... ); + #endif + const selector_t nullSelector = { raw: 0 }; const descriptor_t nullDescriptor = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, *************** *** 110,115 **** --- 114,121 ---- vm->addr->guest_context->fs = vm->guest_cpu.selector[SRegFS].raw; vm->addr->guest_context->gs = vm->guest_cpu.selector[SRegGS].raw; + DbgPrint( "GetMonMode() returns MonModeVM\n" ); + /* Monitor selectors. Since the guest is being monitored in * V86 mode, no guest descriptors are used. Simply use the * first GDT slots */ *************** *** 135,140 **** --- 141,149 ---- vm->addr->gdt[4+sreg] = nullDescriptor; } } + + DbgPrint( "GetGuestMode() returns GuestModeRM\n" ); + #warning "where are the selector set?" /* Monitor selectors. Because of legacy PM values in descriptor *************** *** 150,155 **** --- 159,166 ---- else { /* ModModePMR3 */ + DbgPrint( "Mode is ModModePMR3\n" ); + #warning "unify with similar code in mon-fault.c" if (!vm->vOpcodeMap) { unsigned monseg, mon_sel[4]; *************** *** 295,304 **** --- 306,318 ---- /* Search for unused PDE for nexus PT (fixed for now) */ laddr = 0x70000000; + vm->mon_pde_mask = laddr & 0xffc00000; vm->mon_pdi = vm->mon_pde_mask >> 22; base = MON_BASE_FROM_LADDR(laddr); + DbgPrint( "-- base = 0x0\n", base ); + /* Map nexus into monitor/guest address space */ vm->addr->page_dir[laddr >> 22] = vm->host.nexus_pde; *************** *** 311,316 **** --- 325,338 ---- base + (Bit32u) vm->guest.addr.tss, sizeof(tss_t)-1, D_BG, 0, D_AVL0, D_PRESENT, D_DPL0, D_TSS) + + DbgPrint( "-- vm->addr->gdt[ 1 ].base = 0x0\n", BaseOfDescriptor(vm->addr->gdt[ 1 ]) ); + DbgPrint( "-- vm->addr->gdt[ 1 ].limit = 0x0\n", LimitOfDataDescriptor(vm->addr->gdt[ 1 ]) ); + DbgPrint( "-- vm->addr->gdt[ 2 ].base = 0x0\n", BaseOfDescriptor(vm->addr->gdt[ 2 ]) ); + DbgPrint( "-- vm->addr->gdt[ 2 ].limit = 0x0\n", LimitOfDataDescriptor(vm->addr->gdt[ 2 ]) ); + DbgPrint( "-- vm->addr->gdt[ 3 ].base = 0x0\n", BaseOfDescriptor(vm->addr->gdt[ 3 ]) ); + DbgPrint( "-- vm->addr->gdt[ 3 ].limit = 0x0\n", LimitOfDataDescriptor(vm->addr->gdt[ 3 ]) ); + /* SS hack for returning to 16bit stacks */ vm->addr->gdt[mon_ss_hack>>3] = vm->addr->gdt[mon_ss >> 3]; vm->addr->nexus->SSNormal = mon_ss; *************** *** 327,332 **** --- 349,356 ---- vm->addr->nexus->mon_idt_info.base = base + (Bit32u) vm->guest.addr.idt; vm->addr->nexus->mon_idt_info.limit = 0xffff; /* MON_IDT_SIZE; +++ */ + DbgPrint( "-- vm->addr->nexus->mon_gdt_info.base = 0x0\n", vm->addr->nexus->mon_gdt_info.base ); + /* We don't have a monitor LDT for now */ vm->addr->nexus->mon_ldt_sel = 0; *************** *** 347,357 **** vm->addr->nexus->mon_jmp_info.selector = mon_cs; vm->addr->nexus->mon_stack_info.selector = mon_ss; /* Monitor PDBR */ #warning "Monitor CRx hacks" ! vm->addr->nexus->mon_cr0 = 0x80000033; vm->addr->nexus->mon_cr3 = vm->pages.page_dir << 12; ! vm->addr->nexus->mon_cr4 = 0x00000004; /* TSD=1 */ /* Monitor code/data segment base */ vm->addr->nexus->mon_base = base; --- 371,396 ---- vm->addr->nexus->mon_jmp_info.selector = mon_cs; vm->addr->nexus->mon_stack_info.selector = mon_ss; + DbgPrint( "** mon_stack_info = 0x0:0x0\n", + vm->host.addr.nexus->mon_stack_info.selector, + vm->host.addr.nexus->mon_stack_info.offset ); + DbgPrint( "** mon_jmp_info = 0x0:0x0 (0)\n", + vm->host.addr.nexus->mon_jmp_info.selector, + vm->host.addr.nexus->mon_jmp_info.offset, + mon_cs ); + DbgPrint( "** host_stack_info = 0x0:0x0\n", + vm->host.addr.nexus->host_stack_info.selector, + vm->host.addr.nexus->host_stack_info.offset ); + /* Monitor PDBR */ #warning "Monitor CRx hacks" ! // vm->addr->nexus->mon_cr0 = 0x80000033; ! vm->addr->nexus->mon_cr0 = 0x8001003b; vm->addr->nexus->mon_cr3 = vm->pages.page_dir << 12; ! // vm->addr->nexus->mon_cr4 = 0x00000004; /* TSD=1 */ ! vm->addr->nexus->mon_cr4 = 0x00000091; /* TSD=1 */ ! ! DbgPrint( "++ vm->addr->nexus->mon_cr3=0x0\n", vm->addr->nexus->mon_cr3 ); /* Monitor code/data segment base */ vm->addr->nexus->mon_base = base; *** kernel/nexus.S 22 Feb 2002 20:37:37 -0000 1.1.1.2 --- kernel/nexus.S 22 Feb 2002 20:55:37 -0000 *************** *** 37,45 **** */ .globl __nexus_start __nexus_start: ! __vm: ;.skip 4, 0 __host_gdt_info: ;.skip 6, 0 --- 37,49 ---- */ + #if defined( WIN32 ) + .globl ___nexus_start + ___nexus_start: + #else .globl __nexus_start __nexus_start: ! #endif __vm: ;.skip 4, 0 __host_gdt_info: ;.skip 6, 0 *************** *** 70,75 **** --- 74,85 ---- __transition_pde_p_mon: ;.skip 4, 0 __transition_laddr: ;.skip 4, 0 + #if defined( WIN32 ) + #define OFFSET_OF(field) [field - ___nexus_start] + #else + #define OFFSET_OF(field) [field - __nexus_start] + #endif + .globl __espUpperNormal .globl __espUpper16BitSSHack .globl __SS16BitSSHack *************** *** 79,87 **** __SS16BitSSHack: ;.skip 4, 0 __SSNormal: ;.skip 4, 0 ! ! ! #define OFFSET_OF(field) [field - __nexus_start] /* These are the offsets of the structures above, from the */ /* beginning of this section. */ --- 89,99 ---- __SS16BitSSHack: ;.skip 4, 0 __SSNormal: ;.skip 4, 0 ! __mikey_hack: ;.skip 4, 0 ! __new_ss: ;.skip 2, 0 ! __old_ss: ;.skip 2, 0 ! __old_ds: ;.skip 2, 0 ! __old_cs: ;.skip 2, 0 /* These are the offsets of the structures above, from the */ /* beginning of this section. */ *************** *** 112,117 **** --- 124,134 ---- #define TRANSITION_PDE_P_MON OFFSET_OF(__transition_pde_p_mon) #define TRANSITION_LADDR OFFSET_OF(__transition_laddr) + #define MIKEY_HACK OFFSET_OF(__mikey_hack) + #define NEW_SS OFFSET_OF(__new_ss) + #define OLD_SS OFFSET_OF(__old_ss) + #define OLD_DS OFFSET_OF(__old_ds) + #define OLD_CS OFFSET_OF(__old_cs) /* To make this code page and data accesses to the fields above */ /* relocatable, I use the following conventions. I load EBX with */ *************** *** 122,129 **** --- 139,152 ---- /* ================================================================== */ + #if defined( WIN32 ) + .globl ___host2mon /* Start function __host2mon() */ + ___host2mon: + #else .globl __host2mon /* Start function __host2mon() */ __host2mon: + #endif + /* Save host context first, so it can be restored later */ pushfl /* Save host flags */ pushal /* Save host general regs */ *************** *** 132,137 **** --- 155,161 ---- pushl 0.000000s pushl 0s + /* Put EIP of beginning of this section in EBX to be used to */ /* access data. */ call null_call *************** *** 192,203 **** lidt (MON_IDT_INFO)(0.000000e+00bx) lldt (MON_LDT_SEL)(0.000000e+00bx) /* Switch to monitor stack and CS */ /* and jump to the monitor-side nexus page */ lss (MON_STACK_INFO)(0.000000e+00bx), 0.000000e+00sp ! ljmp (MON_JMP_INFO)(0.000000e+00bx) .globl __mon_cs __mon_cs: /* Reset DS:EBX to point to the monitor-side nexus page */ movw s, %ax --- 216,238 ---- lidt (MON_IDT_INFO)(0.000000e+00bx) lldt (MON_LDT_SEL)(0.000000e+00bx) + movw s, (OLD_SS)(0.000000e+00bx) + movw 0s, (OLD_DS)(0.000000e+00bx) + movw s, (OLD_CS)(0.000000e+00bx) + /* Switch to monitor stack and CS */ /* and jump to the monitor-side nexus page */ + movw s, 0x lss (MON_STACK_INFO)(0.000000e+00bx), 0.000000e+00sp ! ! ljmp *(MON_JMP_INFO)(0.000000e+00bx) ! #if defined( WIN32 ) ! .globl ___mon_cs ! ___mon_cs: ! #else .globl __mon_cs __mon_cs: + #endif /* Reset DS:EBX to point to the monitor-side nexus page */ movw s, %ax *************** *** 231,243 **** --- 266,284 ---- popl 0.000000s popal /* Restore mon general registers */ popfl /* Restore mon eflags */ + ret /* Resume execution in monitor exception handler code. */ /* ================================================================== */ + #if defined( WIN32 ) + .globl ___mon2host /* Start function ___mon2host() */ + ___mon2host: + #else .globl __mon2host /* Start function __mon2host() */ __mon2host: + #endif pushfl /* Save mon flags */ pushal /* Save mon general registers */ pushl 0.000000s *************** *** 294,300 **** /* Restore host stack and CS */ lss (HOST_STACK_INFO)(0.000000e+00bx), 0.000000e+00sp ! ljmp (HOST_JMP_INFO)(0.000000e+00bx) __host_cs: /* Clear busy bit of the host TSS and switch to it */ --- 335,341 ---- /* Restore host stack and CS */ lss (HOST_STACK_INFO)(0.000000e+00bx), 0.000000e+00sp ! ljmp *(HOST_JMP_INFO)(0.000000e+00bx) __host_cs: /* Clear busy bit of the host TSS and switch to it */ *************** *** 323,327 **** --- 364,373 ---- popfl ret + #if defined( WIN32 ) + .globl ___nexus_end + ___nexus_end: + #else .globl __nexus_end __nexus_end: + #endif \ No newline at end of file *** kernel/include/monitor.h 22 Feb 2002 20:37:43 -0000 1.1.1.2 --- kernel/include/monitor.h 22 Feb 2002 20:55:39 -0000 *************** *** 153,158 **** --- 153,165 ---- Bit32u espUpper16BitSSHack; Bit32u SS16BitSSHack; Bit32u SSNormal; + + Bit32u mikey_hack; + Bit16u new_ss; + Bit16u old_ss; + Bit16u old_ds; + Bit16u old_cs; + } __attribute__ ((packed)) nexus_t; *************** *** 726,731 **** --- 733,746 ---- vm_addr_t addr; /* addresses of data structures in guest space */ void (*__mon2host)(void); /* monitor to host entry point */ } guest; + + #if defined( _WIN32 ) + void* mdlGuestMemory; + void* pvGuestMemory; + void* mdlPrintMemory; + void* pvPrintMemory; + #endif + } vm_t; *************** *** 948,960 **** int ioctlSetA20E(vm_t *, unsigned long val); int ioctlMessageQ(vm_t *, vm_messages_t *user_msgs); ! unsigned host_idle(void); ! void *host_alloc(unsigned long size); ! void host_free(void *ptr); ! unsigned host_map(Bit32u *page, int max_pages, void *ptr, unsigned size); ! void *host_alloc_page(void); ! void host_free_page(void *ptr); ! Bit32u host_map_page(void *ptr); void hostprint(char *fmt, ...); unsigned hostModuleInit(void); void hostDeviceOpenInit(vm_t *); --- 963,990 ---- int ioctlSetA20E(vm_t *, unsigned long val); int ioctlMessageQ(vm_t *, vm_messages_t *user_msgs); ! #if defined( _WIN32 ) ! #define MON_HOST_DECL __stdcall ! ! #define NT_PREMON_IRQL_HACK() host_premon_irql_hack() ! #define NT_POSTMON_IRQL_HACK() host_postmon_irql_hack() ! void MON_HOST_DECL host_premon_irql_hack(void); ! void MON_HOST_DECL host_postmon_irql_hack(void); ! #else ! #define MON_HOST_DECL ! ! #define NT_PREMON_IRQL_HACK() ! #define NT_POSTMON_IRQL_HACK() ! #endif ! ! unsigned MON_HOST_DECL host_idle(void); ! void* MON_HOST_DECL host_alloc(unsigned long size); ! void MON_HOST_DECL host_free(void *ptr); ! unsigned MON_HOST_DECL host_map(Bit32u *page, int max_pages, void *ptr, unsigned size); ! void* MON_HOST_DECL host_alloc_page(void); ! void MON_HOST_DECL host_free_page(void *ptr); ! Bit32u MON_HOST_DECL host_map_page(void *ptr); ! void hostprint(char *fmt, ...); unsigned hostModuleInit(void); void hostDeviceOpenInit(vm_t *); *** user/plex86.c 22 Feb 2002 20:37:45 -0000 1.1.1.2 --- user/plex86.c 22 Feb 2002 20:55:41 -0000 *************** *** 24,31 **** #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> ! #include <unistd.h> ! #include <libgen.h> #include "plex86.h" #include "user.h" --- 24,34 ---- #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> ! ! #if !defined( WIN32 ) ! #include <unistd.h> ! #include <libgen.h> ! #endif #include "plex86.h" #include "user.h" *************** *** 36,44 **** /************************************************************************/ /* Declarations */ /************************************************************************/ ! static void abort_handler (int i); callback_command_t *callback_command_list; static char *eat_token(char *s, char c); static char *eat_whitespace(char *s); --- 39,50 ---- /************************************************************************/ /* Declarations */ /************************************************************************/ ! #if !defined( WIN32 ) static void abort_handler (int i); callback_command_t *callback_command_list; + config_info_t vm_conf; + #endif + static char *eat_token(char *s, char c); static char *eat_whitespace(char *s); *************** *** 56,62 **** /* Global data */ - config_info_t vm_conf; static char conf_fname[256]; static char line[256]; static int lineno; --- 62,67 ---- *************** *** 74,84 **** --- 79,95 ---- main (int argc, char *argv[]) { int i; + #if !defined( WIN32 ) struct sigaction sg_act; + #endif /* Store name of executable for printing messages */ + #if defined( _WIN32 ) + argv0 = strdup( argv[0] ); + #else argv0 = strdup( basename(argv[0]) ); + #endif /* some inits */ *************** *** 236,241 **** --- 247,253 ---- + #if !defined( WIN32 ) /* setup to catch SIGINT, SIGABRT and SIGQUIT signals so we can clean up */ memset (&sg_act, 0, sizeof (sg_act)); *************** *** 245,250 **** --- 257,263 ---- sigaction (SIGABRT, &sg_act, NULL); sigaction (SIGQUIT, &sg_act, NULL); + #endif /* kickstart the VM */ *************** *** 478,483 **** --- 491,500 ---- callback_command_t *command = callback_command_list; unsigned found = 0; while (command) { + + printf( "-- command->command = ''\n", command->command ); + printf( "-- current = ''\n", current ); + if ( !strncmp(current, command->command, strlen(command->command)) ) { found = 1; *************** *** 580,585 **** --- 597,603 ---- /* Signal handlers */ /************************************************************************/ + #if !defined( WIN32 ) void abort_handler (int i) { *************** *** 603,608 **** --- 621,628 ---- vm_abort (); return; } + + #endif void usage(void) *** user/plugin.c 22 Feb 2002 20:37:45 -0000 1.1.1.2 --- user/plugin.c 22 Feb 2002 20:55:44 -0000 *************** *** 17,29 **** * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <sys/types.h> #include <sys/ioctl.h> ! #include <unistd.h> #include <string.h> #include "plex86.h" --- 17,39 ---- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #if defined( WIN32 ) + #include <windows.h> + #endif + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <sys/types.h> #include <sys/ioctl.h> ! ! #if defined( WIN32 ) ! #include <io.h> ! #else ! #include <unistd.h> ! #endif ! #include <string.h> #include "plex86.h" *************** *** 147,152 **** --- 157,205 ---- plugin->args = args; plugin->initialized = 0; + #if defined( WIN32 ) + plugin->handle = LoadLibrary( name ); + + if ( !plugin->handle ) + { + char szError[ 80 ]; + + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + 0UL, + szError, + sizeof(szError), + NULL ); + + fprintf( stderr, + "** Failed to load '', ''\n", + name, + szError ); + exit(1); + } + + plugin->init = GetProcAddress( plugin->handle, PLUGIN_INIT ); + + if ( !plugin->init ) + { + fprintf( stderr, + "** Plugin '' has no plugin_init export\n", + name ); + exit(1); + } + + plugin->fini = GetProcAddress( plugin->handle, PLUGIN_FINI ); + + if ( !plugin->fini ) + { + fprintf( stderr, + "** Plugin '' has no plugin_fini export\n", + name ); + exit(1); + } + + #else plugin->handle = dlopen (name, RTLD_LAZY); if (!plugin->handle) { *************** *** 168,173 **** --- 221,228 ---- exit (1); } + #endif + /* Insert plugin at the _end_ of the plugin linked list. */ plugin->next = NULL; *************** *** 284,290 **** --- 339,349 ---- for (i=0; i<256; i++) plugin_free_intr (plugin, i); + #if defined( WIN32 ) + FreeLibrary(plugin->handle); + #else dlclose (plugin->handle); + #endif free (plugin->name); free (plugin->args); *** user/plugin.h 22 Feb 2002 20:37:45 -0000 1.1.1.2 --- user/plugin.h 22 Feb 2002 20:55:47 -0000 *************** *** 24,31 **** extern "C" { #endif ! ! #include <dlfcn.h> #define PLUGIN_INIT "plugin_init" #define PLUGIN_FINI "plugin_fini" --- 24,32 ---- extern "C" { #endif ! #if !defined( WIN32 ) ! #include <dlfcn.h> ! #endif #define PLUGIN_INIT "plugin_init" #define PLUGIN_FINI "plugin_fini" *************** *** 294,300 **** --- 295,305 ---- void (*wcCommit)(int fd); } pluginCallbacks_t; + #if defined( WIN32 ) + extern pluginCallbacks_t __declspec(dllimport) pluginCallbacks; + #else extern pluginCallbacks_t pluginCallbacks; + #endif #define pluginRegisterWriteCache(LS, R, W, C) \ ({ \ *** user/user.h 22 Feb 2002 20:37:46 -0000 1.1.1.2 --- user/user.h 22 Feb 2002 20:55:50 -0000 *************** *** 49,57 **** struct callback_command_tag *next; } callback_command_t; extern callback_command_t *callback_command_list; - extern config_info_t vm_conf; extern unsigned vm_mem_updated; --- 49,61 ---- struct callback_command_tag *next; } callback_command_t; + #if defined( _WIN32 ) + callback_command_t __declspec(dllimport) *callback_command_list; + extern config_info_t __declspec(dllimport) vm_conf; + #else extern callback_command_t *callback_command_list; extern config_info_t vm_conf; + #endif extern unsigned vm_mem_updated; *** user/plugins/bochs/io.cc 22 Feb 2002 20:37:46 -0000 1.1.1.2 --- user/plugins/bochs/io.cc 22 Feb 2002 20:55:52 -0000 *************** *** 20,37 **** #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> - #include <sys/ioctl.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <sys/time.h> #include <signal.h> #include <errno.h> #include "bochs.h" - #include "elf.h" #include "decode.h" bx_options_t bx_options; --- 20,38 ---- #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> + #if !defined( WIN32 ) + #include <sys/ioctl.h> #include <sys/mman.h> + #endif #include <sys/time.h> #include <signal.h> #include <errno.h> #include "bochs.h" #include "decode.h" bx_options_t bx_options; *** user/plugins/bochs/pc_system.cc 22 Feb 2002 20:20:45 -0000 1.1.1.1 --- user/plugins/bochs/pc_system.cc 22 Feb 2002 20:55:55 -0000 *************** *** 22,31 **** #include "bochs.h" #ifdef WIN32 ! #ifndef __MINGW32__ // #include <winsock2.h> // +++ #include <winsock.h> ! #endif #endif #if BX_SHOW_IPS --- 22,31 ---- #include "bochs.h" #ifdef WIN32 ! //#ifndef __MINGW32__ // #include <winsock2.h> // +++ #include <winsock.h> ! //#endif #endif #if BX_SHOW_IPS *************** *** 98,104 **** #endif counter = 0; ! counter_timer_index = register_timer_ticks(this, bx_pc_system_c::counter_timer_handler, COUNTER_INTERVAL, 1, 1); } void --- 98,104 ---- #endif counter = 0; ! counter_timer_index = register_timer_ticks(this, (bx_timer_handler_t)bx_pc_system_c::counter_timer_handler, COUNTER_INTERVAL, 1, 1); } void *************** *** 389,395 **** } int ! bx_pc_system_c::register_timer( void *this_ptr, void (*funct)(void *), Bit32u useconds, Boolean continuous, Boolean active) { Bit64u instructions; --- 389,395 ---- } int ! bx_pc_system_c::register_timer( void *this_ptr, bx_timer_handler_t funct, Bit32u useconds, Boolean continuous, Boolean active) { Bit64u instructions; *** user/plugins/bochs/iodev/harddrv.h 22 Feb 2002 20:37:47 -0000 1.1.1.2 --- user/plugins/bochs/iodev/harddrv.h 22 Feb 2002 20:55:56 -0000 *************** *** 34,39 **** --- 34,43 ---- class LOWLEVEL_CDROM; + #if !defined( ssize_t ) + typedef size_t ssize_t; + #endif + class device_image_t { public: *** user/plugins/bochs/iodev/serial.cc 22 Feb 2002 20:37:50 -0000 1.1.1.2 --- user/plugins/bochs/iodev/serial.cc 22 Feb 2002 20:55:58 -0000 *************** *** 40,51 **** #endif #ifdef WIN32 - #ifndef __MINGW32__ - // +++ - //#include <winsock2.h> #include <winsock.h> #endif - #endif #ifdef __FreeBSD__ --- 40,47 ---- *************** *** 151,161 **** BX_SER_THIS s[i].tx_interrupt = 0; BX_SER_THIS s[i].tx_timer_index = ! pluginRegisterTimer(this, tx_timer_handler, 0, 0,0); // one-shot, inactive BX_SER_THIS s[i].rx_timer_index = ! pluginRegisterTimer(this, rx_timer_handler, 0, 0,0); // one-shot, inactive BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE; --- 147,157 ---- BX_SER_THIS s[i].tx_interrupt = 0; BX_SER_THIS s[i].tx_timer_index = ! pluginRegisterTimer(this, (bx_timer_handler_t)tx_timer_handler, 0, 0,0); // one-shot, inactive BX_SER_THIS s[i].rx_timer_index = ! pluginRegisterTimer(this, (bx_timer_handler_t)rx_timer_handler, 0, 0,0); // one-shot, inactive BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE;