WIP: Bring SMP support #11

Closed
harraiken wants to merge 8 commits from harraiken/exectos:master into master
12 changed files with 267 additions and 6 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 <harraiken91@gmail.com>
*/
#include <amd64/asmsup.h>
.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:

View File

@@ -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 <harraiken91@gmail.com>
*/
#include <i686/asmsup.h>
.altmacro
.text
.global ArStartApplicationProcessor
ArStartApplicationProcessor:
/* 16-bit code (real mode) */
.code16
cli
cld
hlt
/* 32-bit code (protected mode) */
.code32

View File

@@ -36,6 +36,9 @@ HlInitializeSystem(VOID)
return Status;
}
/* Start all application processors */
HlStartAllProcessors();
/* Return success */
return STATUS_SUCCESS;
}

View File

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

View File

@@ -117,6 +117,10 @@ XTCDECL
VOID
ArSetInterruptFlag(VOID);
XTCDECL
VOID
ArStartApplicationProcessor();
XTCDECL
VOID
ArStoreGlobalDescriptorTable(OUT PVOID Destination);

View File

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

View File

@@ -113,6 +113,10 @@ XTCDECL
VOID
ArSetInterruptFlag(VOID);
XTCDECL
VOID
ArStartApplicationProcessor();
XTCDECL
VOID
ArStoreGlobalDescriptorTable(OUT PVOID Destination);