diff --git a/reactos/hal/halx86/generic/amd64/systimer.S b/reactos/hal/halx86/generic/amd64/systimer.S new file mode 100644 index 00000000000..1cb3b6e02a3 --- /dev/null +++ b/reactos/hal/halx86/generic/amd64/systimer.S @@ -0,0 +1,92 @@ +/* + * FILE: hal/halx86/generic/timer.S + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: System Timer Interrupt and Management + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +/* GLOBALS *******************************************************************/ + +.data + +.global MsgUnimplemented +MsgUnimplemented: +.asciz "WARNING: %s at %s:%d is UNIMPLEMENTED!\n" + + +/* FUNCTIONS *****************************************************************/ + +.text +.code64 + +PUBLIC HalpCalibrateStallExecution@0 +HalpCalibrateStallExecution@0: + + +PUBLIC HalpProfileInterrupt +HalpProfileInterrupt: + + +PUBLIC KeStallExecutionProcessor +KeStallExecutionProcessor: + + /* Get the number of microseconds required */ + jecxz Done + + /* Multiply by the stall factor */ + mov eax, gs:[KPCR_STALL_SCALE_FACTOR] + mul ecx + + /* Align to 16 bytes */ + .align 16 + + /* Jump to subtraction loop */ + jmp SubtractLoop + + /* Align to 16 bytes */ + .align 16 + + /* Subtract one count */ +SubtractLoop: + sub eax, 1 + jnz SubtractLoop + +Done: + /* Return */ + ret 4 + + +PUBLIC HalpQuery8254Counter +HalpQuery8254Counter: + + /* Save EFLAGS and disable interrupts */ + pushfq + cli + + /* Set timer data */ + mov al, 0 + out 0x43, al + jmp $+2 + + /* Read current timer */ + in al, 0x40 + jmp $+2 + movzx ecx, al + in al, 0x40 + mov ch, al + + /* Return it and restore interrupt state */ + mov eax, ecx + popfq + ret + +PUBLIC HalpClockInterrupt +HalpClockInterrupt: + UNIMPLEMENTED _HalpClockInterrupt + iret + diff --git a/reactos/hal/halx86/generic/amd64/x86bios.c b/reactos/hal/halx86/generic/amd64/x86bios.c new file mode 100644 index 00000000000..3b43bf1d95f --- /dev/null +++ b/reactos/hal/halx86/generic/amd64/x86bios.c @@ -0,0 +1,289 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL, See COPYING in the top level directory + * FILE: hal/halx86/generic/amd64/x86bios.c + * PURPOSE: + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +//#define NDEBUG +#include + +#include "x86emu.h" + +/* This page serves as fallback for pages used by Mm */ +#define DEFAULT_PAGE 0x21 + +/* GLOBALS *******************************************************************/ + +BOOLEAN x86BiosIsInitialized; +LONG x86BiosBufferIsAllocated = 0; +PUCHAR x86BiosMemoryMapping; + + +VOID +NTAPI +DbgDumpPage(PUCHAR MemBuffer, USHORT Segment) +{ + ULONG x, y, Offset; + + for (y = 0; y < 0x100; y++) + { + for (x = 0; x < 0x10; x++) + { + Offset = Segment * 16 + y * 16 + x; + DbgPrint("%02x ", MemBuffer[Offset]); + } + DbgPrint("\n"); + } +} + +VOID +NTAPI +HalInitializeBios(ULONG Unknown, PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PPFN_NUMBER PfnArray; + PFN_NUMBER Pfn, Last; + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY ListEntry; + PMDL Mdl; + + /* Allocate an MDL for 1MB */ + Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL); + if (!Mdl) + { + ASSERT(FALSE); + } + + /* Get pointer to the pfn array */ + PfnArray = MmGetMdlPfnArray(Mdl); + + /* Fill the array with low memory PFNs */ + for (Pfn = 0; Pfn < 0x100; Pfn++) + { + PfnArray[Pfn] = Pfn; + } + + /* Loop the memory descriptors */ + for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink; + ListEntry != &LoaderBlock->MemoryDescriptorListHead; + ListEntry = ListEntry->Flink) + { + /* Get the memory descriptor */ + Descriptor = CONTAINING_RECORD(ListEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + /* Check if the memory is in the low range */ + if (Descriptor->BasePage < 0x100) + { + /* Check if the memory type is firmware */ + if (Descriptor->MemoryType != LoaderFirmwarePermanent && + Descriptor->MemoryType != LoaderSpecialMemory) + { + /* It's something else, so don't use it! */ + Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100); + for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++) + { + /* Set each page to the default page */ + PfnArray[Pfn] = DEFAULT_PAGE; + } + } + } + } + + Mdl->MdlFlags = MDL_PAGES_LOCKED; + + /* Map the MDL to system space */ + x86BiosMemoryMapping = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority); + ASSERT(x86BiosMemoryMapping); + + DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8)); + //DbgDumpPage(x86BiosMemoryMapping, 0xc351); + + x86BiosIsInitialized = TRUE; + + HalpBiosDisplayReset(); +} + +NTSTATUS +NTAPI +x86BiosAllocateBuffer( + ULONG *Size, + USHORT *Segment, + USHORT *Offset) +{ + /* Check if the system is initialized and the buffer is large enough */ + if (!x86BiosIsInitialized || *Size > PAGE_SIZE) + { + /* Something was wrong, fail! */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Check if the buffer is already allocated */ + if (InterlockedBitTestAndSet(&x86BiosBufferIsAllocated, 0)) + { + /* Buffer was already allocated, fail */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* The buffer is sufficient, return hardcoded address and size */ + *Size = PAGE_SIZE; + *Segment = 0x2000; + *Offset = 0; + + return STATUS_SUCCESS;; +} + +NTSTATUS +NTAPI +x86BiosFreeBuffer( + USHORT Segment, + USHORT Offset) +{ + /* Check if the system is initialized and if the address matches */ + if (!x86BiosIsInitialized || Segment != 0x2000 || Offset != 0) + { + /* Something was wrong, fail */ + return STATUS_INVALID_PARAMETER; + } + + /* Check if the buffer was allocated */ + if (!InterlockedBitTestAndReset(&x86BiosBufferIsAllocated, 0)) + { + /* It was not, fail */ + return STATUS_INVALID_PARAMETER; + } + + /* Buffer is freed, nothing more to do */ + return STATUS_SUCCESS;; +} + +NTSTATUS +NTAPI +x86BiosReadMemory( + USHORT Segment, + USHORT Offset, + PVOID Buffer, + ULONG Size) +{ + ULONG_PTR Address; + + /* Calculate the physical address */ + Address = (Segment << 4) + Offset; + + /* Check if it's valid */ + if (!x86BiosIsInitialized || Address + Size > 0x100000) + { + /* Invalid */ + return STATUS_INVALID_PARAMETER; + } + + /* Copy the memory to the buffer */ + RtlCopyMemory(Buffer, x86BiosMemoryMapping + Address, Size); + + /* Return success */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +x86BiosWriteMemory( + USHORT Segment, + USHORT Offset, + PVOID Buffer, + ULONG Size) +{ + ULONG_PTR Address; + + /* Calculate the physical address */ + Address = (Segment << 4) + Offset; + + /* Check if it's valid */ + if (!x86BiosIsInitialized || Address + Size > 0x100000) + { + /* Invalid */ + return STATUS_INVALID_PARAMETER; + } + + /* Copy the memory from the buffer */ + RtlCopyMemory(x86BiosMemoryMapping + Address, Buffer, Size); + + /* Return success */ + return STATUS_SUCCESS; +} + +BOOLEAN +NTAPI +x86BiosCall( + ULONG InterruptNumber, + X86_BIOS_REGISTERS *Registers) +{ + X86_VM_STATE VmState; + struct + { + USHORT Ip; + USHORT SegCs; + } *InterrupTable; + + /* Zero the VmState */ + RtlZeroMemory(&VmState, sizeof(VmState)); + + /* Copy the registers */ + VmState.BiosRegisters = *Registers; + + /* Set the physical memory buffer */ + VmState.MemBuffer = x86BiosMemoryMapping; + + /* Set Eflags */ + VmState.Registers.Eflags.Long = 0; // FIXME + + /* Setup stack */ + VmState.Registers.SegSs = 0; // FIXME + VmState.Registers.Sp = 0x2000 - 2; // FIXME + + /* Initialize IP from the interrupt vector table */ + InterrupTable = (PVOID)x86BiosMemoryMapping; + VmState.Registers.SegCs = InterrupTable[InterruptNumber].SegCs; + VmState.Registers.Eip = InterrupTable[InterruptNumber].Ip; + + /* Make the function return on IRET */ + VmState.Flags.ReturnOnIret = 1; + + /* Call the x86 emulator */ + x86Emulator(&VmState); + + /* Copy registers back to caller */ + *Registers = VmState.BiosRegisters; + + return TRUE; +} + +BOOLEAN +NTAPI +HalpBiosDisplayReset(VOID) +{ + X86_BIOS_REGISTERS Registers; + ULONG OldEflags; + + /* Save flags and disable interrupts */ + OldEflags = __readeflags(); + _disable(); + + /* Set AH = 0 (Set video mode), AL = 0x12 (640x480x16 vga) */ + Registers.Eax = 0x12; + + /* Call INT 0x10 */ + x86BiosCall(0x10, &Registers); + + // FIXME: check result + + /* Restore previous flags */ + __writeeflags(OldEflags); + + return TRUE; +} + diff --git a/reactos/hal/halx86/halamd64.rbuild b/reactos/hal/halx86/halamd64.rbuild index 8b137891791..4a09aa2c838 100644 --- a/reactos/hal/halx86/halamd64.rbuild +++ b/reactos/hal/halx86/halamd64.rbuild @@ -1 +1,27 @@ + + + + + + + include + include + + + + + hal_generic + hal_generic_up + ntoskrnl + + + + halinit_mp.c + halmp.rc + + + + + + diff --git a/reactos/hal/halx86/mp/amd64/mps.S b/reactos/hal/halx86/mp/amd64/mps.S new file mode 100644 index 00000000000..35436520ae6 --- /dev/null +++ b/reactos/hal/halx86/mp/amd64/mps.S @@ -0,0 +1,96 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/amd64/generic/mps.S + * PURPOSE: Intel MultiProcessor specification support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +#define BEFORE \ + cld; \ + push rax; \ + push rbx; \ + push rcx; \ + push rdx; \ + push rsi; \ + push rdi; \ + push fs; \ + push gs; \ + +#define AFTER \ + pop gs; \ + pop fs; \ + pop rdi; \ + pop rsi; \ + pop rdx; \ + pop rcx; \ + pop rbx; \ + pop rax; \ + +#ifdef CONFIG_SMP +PUBLIC MpsIpiInterrupt +MpsIpiInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call MpsIpiHandler + + /* Return to the caller */ + AFTER + iret +#endif + +PUBLIC MpsErrorInterrupt +MpsErrorInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call MpsErrorHandler + + /* Return to the caller */ + AFTER + iret + + +PUBLIC MpsSpuriousInterrupt +MpsSpuriousInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call MpsSpuriousHandler + + /* Return to the caller */ + AFTER + iret + +PUBLIC MpsTimerInterrupt +MpsTimerInterrupt: + /* Save registers */ + BEFORE + + mov ebx, 0xef + mov eax, 0xceafbeef + push rax + push rsp + push rbx + call MpsTimerHandler + pop rax + pop rax + pop rax + + /* Return to the caller */ + AFTER + iret + + +/* EOF */