diff --git a/sdk/firmware/bochsrc_amd64.cfg b/sdk/firmware/bochsrc_amd64.cfg index 03fea9c..a857ce7 100644 --- a/sdk/firmware/bochsrc_amd64.cfg +++ b/sdk/firmware/bochsrc_amd64.cfg @@ -2,7 +2,7 @@ plugin_ctrl: usb_xhci=false, serial=true, e1000=false, extfpuirq=true, parallel=true, usb_uhci=false, biosdev=true, unmapped=true, gameport=true, ne2k=false, speaker=true, iodebug=false, pcipnic=false, usb_ohci=false config_interface: textconfig display_library: x -memory: host=64, guest=64 +memory: host=64, guest=2048 romimage: file="../sdk/firmware/ovmf_pure_amd64.fd", address=0x00000000, options=none vgaromimage: file="../sdk/firmware/vgabios.bin" boot: floppy @@ -27,7 +27,7 @@ optramimage3: file=none optramimage4: file=none pci: enabled=1, chipset=i440fx, slot1=cirrus, slot2=none, slot3=none, slot4=none, slot5=none vga: extension=cirrus, update_freq=5, realtime=1, ddc=builtin -cpu: count=1:1:1, ips=400000000, quantum=16, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpu: count=2:2:1, ips=400000000, quantum=16, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " cpuid: mmx=true, apic=xapic, simd=sse4_2, sse4a=false, misaligned_sse=false, sep=true cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, x86_64=true @@ -45,7 +45,7 @@ error: action=report panic: action=ask keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none mouse: type=ps2, enabled=false, toggle=ctrl+mbutton -com1: enabled=true, mode=null +com1: enabled=true, mode=file, dev=dbgport.txt com2: enabled=false com3: enabled=false com4: enabled=false diff --git a/sdk/firmware/bochsrc_i686.cfg b/sdk/firmware/bochsrc_i686.cfg index 49ea10f..fd5cbe2 100644 --- a/sdk/firmware/bochsrc_i686.cfg +++ b/sdk/firmware/bochsrc_i686.cfg @@ -2,7 +2,7 @@ plugin_ctrl: usb_xhci=false, serial=true, e1000=false, extfpuirq=true, parallel=true, usb_uhci=false, biosdev=true, unmapped=true, gameport=true, ne2k=false, speaker=true, iodebug=false, pcipnic=false, usb_ohci=false config_interface: textconfig display_library: x -memory: host=64, guest=64 +memory: host=64, guest=2048 romimage: file="../sdk/firmware/ovmf_pure_i686.fd", address=0x00000000, options=none vgaromimage: file="../sdk/firmware/vgabios.bin" boot: floppy @@ -27,7 +27,7 @@ optramimage3: file=none optramimage4: file=none pci: enabled=1, chipset=i440fx, slot1=cirrus, slot2=none, slot3=none, slot4=none, slot5=none vga: extension=cirrus, update_freq=5, realtime=1, ddc=builtin -cpu: count=1:1:1, ips=400000000, quantum=16, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpu: count=2:2:1, ips=400000000, quantum=16, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " cpuid: mmx=true, apic=xapic, simd=sse4_2, sse4a=false, misaligned_sse=false, sep=true cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, x86_64=true @@ -45,7 +45,7 @@ error: action=report panic: action=ask keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none mouse: type=ps2, enabled=false, toggle=ctrl+mbutton -com1: enabled=true, mode=null +com1: enabled=true, mode=file, dev=dbgport.txt com2: enabled=false com3: enabled=false com4: enabled=false diff --git a/sdk/xtdk/amd64/hltypes.h b/sdk/xtdk/amd64/hltypes.h index 4c57ae2..92fd90f 100644 --- a/sdk/xtdk/amd64/hltypes.h +++ b/sdk/xtdk/amd64/hltypes.h @@ -51,6 +51,12 @@ #define APIC_DM_INIT 0x00000500 #define APIC_DM_STARTUP 0x00000600 #define APIC_DM_EXTINT 0x00000700 +#define APIC_DM_ASSERT 0x00004000 +#define APIC_DM_LEVEL 0x00008000 +#define APIC_DM_BROADCAST 0x00080000 + +/* APIC delivery status */ +#define APIC_DELIVERY_PENDING 0x00001000 /* APIC trigger modes */ #define APIC_TGM_EDGE 0 diff --git a/sdk/xtdk/i686/hltypes.h b/sdk/xtdk/i686/hltypes.h index 440976b..defdfc6 100644 --- a/sdk/xtdk/i686/hltypes.h +++ b/sdk/xtdk/i686/hltypes.h @@ -56,6 +56,12 @@ #define APIC_DM_INIT 0x00000500 #define APIC_DM_STARTUP 0x00000600 #define APIC_DM_EXTINT 0x00000700 +#define APIC_DM_ASSERT 0x00004000 +#define APIC_DM_LEVEL 0x00008000 +#define APIC_DM_BROADCAST 0x00080000 + +/* APIC delivery status */ +#define APIC_DELIVERY_PENDING 0x00001000 /* APIC trigger modes */ #define APIC_TGM_EDGE 0 diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index d6a2f57..26282a9 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -22,6 +22,7 @@ list(APPEND LIBXTOS_SOURCE # Specify list of kernel source code files list(APPEND XTOSKRNL_SOURCE + ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/archsmp.S ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/archsup.S ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/cpufunc.c ${XTOSKRNL_SOURCE_DIR}/ar/${ARCH}/globals.c diff --git a/xtoskrnl/ar/amd64/archsmp.S b/xtoskrnl/ar/amd64/archsmp.S new file mode 100644 index 0000000..ac50bf1 --- /dev/null +++ b/xtoskrnl/ar/amd64/archsmp.S @@ -0,0 +1,85 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/ar/amd64/archsmp.S + * DESCRIPTION: AP bootstrap code for AMD64 architecture + * DEVELOPERS: Aiken Harris + */ + +#include + +.altmacro +.text + + +.global ArBootstrapPageMap + +.global ArStartApplicationProcessor +ArStartApplicationProcessor: + /* 16-bit code (real mode) */ + .code16 + + /* Turn off interrupts and clear direction flag */ + cli + cld + + /* Load temporary GDT */ + lgdt (ArpApTemporaryGdtSize - ArStartApplicationProcessor + 0x1000) + + /* Enable bit 0 in CR0 to enable Protected Mode */ + movl %cr0, %eax + orl $0x1, %eax + movl %eax, %cr0 + + /* Long jump into 32bits */ + ljmpl $0x8, $(ApplicationProcessor32 - ArStartApplicationProcessor + 0x1000) + + /* 32-bit code (protected mode) */ + .code32 +ApplicationProcessor32: + + /* Fix segment registers */ + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss + + /* Enable LM and NX in the EFER. */ + mov $0xC0000080, %ecx + rdmsr + or $0x900, %eax + wrmsr + + /* Enable PAE and PSE */ + mov %cr4, %eax + or $0x668, %eax + mov %eax, %cr4 + + /* Install page map in CR3 */ + mov (ArBootstrapPageMap - ArStartApplicationProcessor + 0x1000), %eax + mov %eax, %cr3 + + /* Enable paging */ + mov %cr0, %eax + or $0x80010000, %eax + mov %eax, %cr0 + + /* Long jump into 64bits */ + ljmpl $0x8, $(ApplicationProcessor64 - ArStartApplicationProcessor + 0x1000) + + /* 64-bit code (long mode) */ + .code64 +ApplicationProcessor64: + + /* HALT CPU in long mode */ + hlt + +.align 8 +ArpApTemporaryGdtDesc: .quad 0x0000000000000000, 0x00CF9A000000FFFF, 0x00CF92000000FFFF, 0x00AF9A000000FFFF +ArpApTemporaryGdtSize: .short ArpApTemporaryGdtSize - ArpApTemporaryGdtDesc - 1 +ArpApTemporaryGdtBase: .long ArpApTemporaryGdtDesc - ArStartApplicationProcessor + 0x1000 +ArBootstrapPageMap: .quad 0x0000000000000000 + +ArStartApplicationProcessorEnd: diff --git a/xtoskrnl/ar/i686/archsmp.S b/xtoskrnl/ar/i686/archsmp.S new file mode 100644 index 0000000..3f1f56f --- /dev/null +++ b/xtoskrnl/ar/i686/archsmp.S @@ -0,0 +1,25 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/ar/i686/archsmp.S + * DESCRIPTION: AP bootstrap code for i686 architecture + * DEVELOPERS: Aiken Harris + */ + +#include + +.altmacro +.text + + +.global ArStartApplicationProcessor +ArStartApplicationProcessor: + /* 16-bit code (real mode) */ + .code16 + + cli + cld + hlt + + /* 32-bit code (protected mode) */ + .code32 diff --git a/xtoskrnl/hl/init.c b/xtoskrnl/hl/init.c index 6119f9a..6d526c3 100644 --- a/xtoskrnl/hl/init.c +++ b/xtoskrnl/hl/init.c @@ -36,6 +36,9 @@ HlInitializeSystem(VOID) return Status; } + /* Start all application processors */ + HlStartAllProcessors(); + /* Return success */ return STATUS_SUCCESS; } diff --git a/xtoskrnl/hl/x86/cpu.c b/xtoskrnl/hl/x86/cpu.c index 65f321f..986f779 100644 --- a/xtoskrnl/hl/x86/cpu.c +++ b/xtoskrnl/hl/x86/cpu.c @@ -45,3 +45,121 @@ HlInitializeProcessor(VOID) /* Set the APIC running level */ HlSetRunLevel(KeGetCurrentProcessorBlock()->RunLevel); } + +XTAPI +XTSTATUS +HlStartProcessor(IN ULONG CpuId, + IN PHYSICAL_ADDRESS EntryPoint) +{ + UCHAR Attempt; + + /* Wait until command register is clear */ + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + + /* Trigger INIT IPI and wait for delivery bit to be cleared */ + HlpSendIpi(CpuId, APIC_DM_INIT | APIC_DM_LEVEL | APIC_DM_ASSERT); + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + + /* Deassert INIT IPI to take CPU out of reset and wait for delivery bit to be cleared */ + HlpSendIpi(CpuId, APIC_DM_INIT | APIC_DM_LEVEL); + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + + /* Two attempts to send STARTUP IPI */ + for(Attempt = 0; Attempt < 2; Attempt++) + { + /* Trigger STARTUP IPI and wait for delivery bit to be cleared */ + HlpSendIpi(CpuId, APIC_DM_STARTUP | (EntryPoint.LowPart >> 12)); + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + } + + /* Memory barrier */ + ArMemoryBarrier(); + + /* Return success */ + return STATUS_SUCCESS; +} + +extern ULONG_PTR ArBootstrapPageMap; + +XTAPI +XTSTATUS +HlStartAllProcessors(VOID) +{ + PHYSICAL_ADDRESS ApPhysicalAddress; + PVOID ApVirtualAddress; + BOOLEAN Interrupts; + XTSTATUS Status; + USHORT Cpu; + +/* Temp bootstrap code size */ +#define AP_SPINUP_PAGE_COUNT 5 + + /* Check if at least one AP is present */ + if(HlpSystemInfo.CpuCount > 1) + { + /* Save page map address in the bootstrap code */ + ArBootstrapPageMap = ArReadControlRegister(3); + + /* Allocate 5 pages for AP bootstrap code and ensure it is low memory */ + Status = MmAllocateHardwareMemory(AP_SPINUP_PAGE_COUNT, FALSE, &ApPhysicalAddress); + if(Status != STATUS_SUCCESS || ApPhysicalAddress.QuadPart > (0x100000 - AP_SPINUP_PAGE_COUNT * MM_PAGE_SIZE)) + { + /* Not enough free pages at low memory available, return error */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Map AP bootstrap code */ + Status = MmMapHardwareMemory(ApPhysicalAddress, AP_SPINUP_PAGE_COUNT, TRUE, &ApVirtualAddress); + if(Status != STATUS_SUCCESS) + { + /* Failed to map AP bootstrap code, return error */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Copy AP bootstrap code into low memory */ + RtlCopyMemory(ApVirtualAddress, &ArStartApplicationProcessor, AP_SPINUP_PAGE_COUNT * MM_PAGE_SIZE); + + /* Iterate over all CPUs and start them */ + for(Cpu = 0; Cpu < HlpSystemInfo.CpuCount; Cpu++) + { + /* Check if this CPU is the BSP */ + if(HlpSystemInfo.CpuInfo[Cpu].ApicId == HlpGetCpuApicId()) + { + /* This is the BSP, set proper flag and mark as started */ + HlpSystemInfo.CpuInfo[Cpu].Bsp = TRUE; + HlpSystemInfo.CpuInfo[Cpu].Started = TRUE; + + /* Continue with next CPU */ + continue; + } + + /* Temp debugging */ + DebugPrint(L"Starting CPU #%lu (ACPI ID: %u, APIC ID: %u)\n", Cpu, HlpSystemInfo.CpuInfo[Cpu].AcpiId, HlpSystemInfo.CpuInfo[Cpu].ApicId); + + /* Check if interrupts are enabled and disable them */ + Interrupts = ArInterruptsEnabled(); + ArClearInterruptFlag(); + + /* Start the AP */ + Status = HlStartProcessor(HlpSystemInfo.CpuInfo[Cpu].ApicId, ApPhysicalAddress); + if(Status == STATUS_SUCCESS) + { + /* Mark AP as started */ + HlpSystemInfo.CpuInfo[Cpu].Started = TRUE; + } + + /* Check if interrupts were originally enabled */ + if(Interrupts) + { + /* Re-enable interrupts */ + ArSetInterruptFlag(); + } + } + + /* Unmap AP bootstrap code */ + MmUnmapHardwareMemory(ApVirtualAddress, AP_SPINUP_PAGE_COUNT, TRUE); + } + + /* Return success */ + return STATUS_SUCCESS; +} diff --git a/xtoskrnl/includes/amd64/ari.h b/xtoskrnl/includes/amd64/ari.h index 1b63daa..7e9a1b2 100644 --- a/xtoskrnl/includes/amd64/ari.h +++ b/xtoskrnl/includes/amd64/ari.h @@ -117,6 +117,10 @@ XTCDECL VOID ArSetInterruptFlag(VOID); +XTCDECL +VOID +ArStartApplicationProcessor(); + XTCDECL VOID ArStoreGlobalDescriptorTable(OUT PVOID Destination); diff --git a/xtoskrnl/includes/hli.h b/xtoskrnl/includes/hli.h index b32c9a3..bca7e06 100644 --- a/xtoskrnl/includes/hli.h +++ b/xtoskrnl/includes/hli.h @@ -82,6 +82,15 @@ XTFASTCALL VOID HlSetRunLevel(IN KRUNLEVEL RunLevel); +XTAPI +XTSTATUS +HlStartAllProcessors(VOID); + +XTAPI +XTSTATUS +HlStartProcessor(IN ULONG CpuId, + IN PHYSICAL_ADDRESS ApEntryPoint); + XTAPI VOID HlpCacheAcpiTable(IN PACPI_DESCRIPTION_HEADER AcpiTable); diff --git a/xtoskrnl/includes/i686/ari.h b/xtoskrnl/includes/i686/ari.h index 377e7f3..5009b76 100644 --- a/xtoskrnl/includes/i686/ari.h +++ b/xtoskrnl/includes/i686/ari.h @@ -113,6 +113,10 @@ XTCDECL VOID ArSetInterruptFlag(VOID); +XTCDECL +VOID +ArStartApplicationProcessor(); + XTCDECL VOID ArStoreGlobalDescriptorTable(OUT PVOID Destination);