X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fvm8086.c;h=839a640bef450c06f85f439440a54b31a93f9c96;hb=7009aab6b04807e085c7e218965e1e8000a2bbbe;hp=ef449d45db3603cb2897e1bb5d6e7c6b85f5c411;hpb=de86ddb7cb10ee403732f9207aba756f267ef3de;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/vm8086.c b/Kernel/arch/x86/vm8086.c index ef449d45..839a640b 100644 --- a/Kernel/arch/x86/vm8086.c +++ b/Kernel/arch/x86/vm8086.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include // === CONSTANTS === #define VM8086_MAGIC_CS 0xFFFF @@ -28,9 +30,6 @@ enum eVM8086_Opcodes #define VM8086_BLOCKSIZE 128 #define VM8086_BLOCKCOUNT ((0x9F000-0x10000)/VM8086_BLOCKSIZE) -// === IMPORTS === - int Proc_Clone(Uint *Err, Uint Flags); - // === TYPES === struct sVM8086_InternalData { @@ -49,6 +48,8 @@ void VM8086_GPF(tRegs *Regs); // === GLOBALS === MODULE_DEFINE(0, 0x100, VM8086, VM8086_Install, NULL, NULL); tMutex glVM8086_Process; +tSemaphore gVM8086_TaskComplete; +tSemaphore gVM8086_TasksToDo; tPID gVM8086_WorkerPID; tTID gVM8086_CallingThread; tVM8086 volatile * volatile gpVM8086_State = (void*)-1; // Set to -1 to avoid race conditions @@ -58,12 +59,15 @@ Uint32 gaVM8086_MemBitmap[VM8086_BLOCKCOUNT/32]; int VM8086_Install(char **Arguments) { tPID pid; + + Semaphore_Init(&gVM8086_TasksToDo, 0, 10, "VM8086", "TasksToDo"); // Lock to avoid race conditions Mutex_Acquire( &glVM8086_Process ); // Create BIOS Call process - pid = Proc_Clone(NULL, CLONE_VM); + pid = Proc_Clone(CLONE_VM); + Log_Debug("VM8086", "pid = %i", pid); if(pid == -1) { Log_Error("VM8086", "Unable to clone kernel into VM8086 worker"); @@ -74,14 +78,15 @@ int VM8086_Install(char **Arguments) Uint * volatile stacksetup; // Initialising Stack Uint16 * volatile rmstack; // Real Mode Stack int i; - + + Log_Debug("VM8086", "Initialising worker"); + // Set Image Name Threads_SetName("VM8086"); - + // Map ROM Area for(i=0xA0;i<0x100;i++) { MM_Map( i * 0x1000, i * 0x1000 ); - //MM_SetFlags( i * 0x1000, MM_PFLAG_RO, MM_PFLAG_RO ); // Set Read Only } MM_Map( 0, 0 ); // IVT / BDA // Map (but allow allocation) of 0x1000 - 0x9F000 @@ -89,7 +94,8 @@ int VM8086_Install(char **Arguments) for(i=1;i<0x9F;i++) { MM_Map( i * 0x1000, i * 0x1000 ); MM_DerefPhys( i * 0x1000 ); // Above - MM_DerefPhys( i * 0x1000 ); // Phys setup + while(MM_GetRefCount(i*0x1000)) + MM_DerefPhys( i * 0x1000 ); // Phys setup } MM_Map( 0x9F000, 0x9F000 ); // Stack / EBDA // System Stack / Stub @@ -143,9 +149,10 @@ int VM8086_Install(char **Arguments) } gVM8086_WorkerPID = pid; - Log_Log("VM8086", "gVM8086_WorkerPID = %i", pid); - while( gpVM8086_State != NULL ) - Threads_Yield(); // Yield to allow the child to initialise + + // It's released when the GPF fires + Mutex_Acquire( &glVM8086_Process ); + Mutex_Release( &glVM8086_Process ); // Worker killed itself if( gVM8086_WorkerPID != pid ) { @@ -159,18 +166,18 @@ void VM8086_GPF(tRegs *Regs) { Uint8 opcode; - //Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip); +// Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip); if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS && Threads_GetPID() == gVM8086_WorkerPID) { if( gpVM8086_State == (void*)-1 ) { - Log_Log("VM8086", "Worker thread ready and waiting"); +// Log_Log("VM8086", "Worker thread ready and waiting"); gpVM8086_State = NULL; Mutex_Release( &glVM8086_Process ); // Release lock obtained in VM8086_Install } - //Log_Log("VM8086", "gpVM8086_State = %p, gVM8086_CallingThread = %i", - // gpVM8086_State, gVM8086_CallingThread); +// Log_Log("VM8086", "gpVM8086_State = %p, gVM8086_CallingThread = %i", +// gpVM8086_State, gVM8086_CallingThread); if( gpVM8086_State ) { gpVM8086_State->AX = Regs->eax; gpVM8086_State->CX = Regs->ecx; gpVM8086_State->DX = Regs->edx; gpVM8086_State->BX = Regs->ebx; @@ -179,24 +186,20 @@ void VM8086_GPF(tRegs *Regs) gpVM8086_State->DS = Regs->ds; gpVM8086_State->ES = Regs->es; gpVM8086_State = NULL; // Wake the caller - Threads_WakeTID(gVM8086_CallingThread); + Semaphore_Signal(&gVM8086_TaskComplete, 1); } //Log_Log("VM8086", "Waiting for something to do"); __asm__ __volatile__ ("sti"); - // Wait for a new task - while(!gpVM8086_State) { - Threads_Sleep(); - //Log_Log("VM8086", "gpVM8086_State = %p", gpVM8086_State); - } + Semaphore_Wait(&gVM8086_TasksToDo, 1); //Log_Log("VM8086", "We have a task (%p)", gpVM8086_State); - Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS; - Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP; - Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->CS; - Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->IP; - Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->DS; - Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->ES; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->CS; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->IP; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->DS; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->ES; // Set Registers Regs->eip = 0x11; Regs->cs = 0xFFFF; @@ -221,8 +224,9 @@ void VM8086_GPF(tRegs *Regs) #endif break; case VM8086_OP_POPF: //POPF - Regs->eflags &= 0xFFFF0002; - Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) & 0xFFFD; // Changing IF is not allowed + // Changing IF is not allowed + Regs->eflags &= 0xFFFF0202; + Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; #if TRACE_EMU Log_Debug("VM8086", "Emulated POPF"); @@ -235,8 +239,8 @@ void VM8086_GPF(tRegs *Regs) id = *(Uint8*)( Regs->cs*16 +(Regs->eip&0xFFFF)); Regs->eip ++; - Regs->esp -= 2; *(Uint16*volatile)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs; - Regs->esp -= 2; *(Uint16*volatile)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip; + Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs; + Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip; Regs->cs = *(Uint16*)(4*id + 2); Regs->eip = *(Uint16*)(4*id); @@ -419,14 +423,16 @@ void VM8086_Int(tVM8086 *State, Uint8 Interrupt) { State->IP = *(Uint16*)(KERNEL_BASE+4*Interrupt); State->CS = *(Uint16*)(KERNEL_BASE+4*Interrupt+2); + +// Log_Debug("VM8086", "Software interrupt %i to %04x:%04x", Interrupt, State->CS, State->IP); Mutex_Acquire( &glVM8086_Process ); gpVM8086_State = State; gVM8086_CallingThread = Threads_GetTID(); - Threads_WakeTID( gVM8086_WorkerPID ); - Threads_Sleep(); - while( gpVM8086_State != NULL ) Threads_Sleep(); + Semaphore_Signal(&gVM8086_TasksToDo, 1); + + Semaphore_Wait(&gVM8086_TaskComplete, 1); Mutex_Release( &glVM8086_Process ); }