WIP: Bring SMP support #11
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
85
xtoskrnl/ar/amd64/archsmp.S
Normal file
85
xtoskrnl/ar/amd64/archsmp.S
Normal 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:
|
25
xtoskrnl/ar/i686/archsmp.S
Normal file
25
xtoskrnl/ar/i686/archsmp.S
Normal 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
|
@@ -36,6 +36,9 @@ HlInitializeSystem(VOID)
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Start all application processors */
|
||||
HlStartAllProcessors();
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -117,6 +117,10 @@ XTCDECL
|
||||
VOID
|
||||
ArSetInterruptFlag(VOID);
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
ArStartApplicationProcessor();
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
ArStoreGlobalDescriptorTable(OUT PVOID Destination);
|
||||
|
@@ -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);
|
||||
|
@@ -113,6 +113,10 @@ XTCDECL
|
||||
VOID
|
||||
ArSetInterruptFlag(VOID);
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
ArStartApplicationProcessor();
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
ArStoreGlobalDescriptorTable(OUT PVOID Destination);
|
||||
|
Reference in New Issue
Block a user