From c17edbe7e2d6b53a79bb02b0a0aa8c785c666365 Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Sun, 26 Apr 2026 11:50:01 -0400 Subject: [PATCH 1/5] x2APIC commit --- src/init/cpu.asm | 91 ++++++++++++++++++++++++++++++++++++++++++------ src/init/smp.asm | 66 ++++++++++++++++++++++++++++------- 2 files changed, 133 insertions(+), 24 deletions(-) diff --git a/src/init/cpu.asm b/src/init/cpu.asm index aa9ab82..4559bcb 100644 --- a/src/init/cpu.asm +++ b/src/init/cpu.asm @@ -135,15 +135,17 @@ avx512_supported: xsetbv ; Save XCR0 register avx512_not_supported: -; Enable and Configure Local APIC -; mov ecx, IA32_APIC_BASE -; rdmsr -; bts eax, 11 ; APIC Global Enable -; cmp byte [p_x2APIC], 1 -; jne skip_x2APIC_enable -; bts eax, 10 ; Enable x2APIC mode -;skip_x2APIC_enable: -; wrmsr +; Enable APIC + mov ecx, IA32_APIC_BASE + rdmsr + bts eax, 11 ; APIC Global Enable + cmp byte [p_x2APIC], 1 + jne skip_x2APIC_enable + bts eax, 10 ; Enable x2APIC mode +skip_x2APIC_enable: + wrmsr + +; Configure APIC mov ecx, APIC_TPR mov eax, 0x00000020 call apic_write ; Disable softint delivery @@ -153,12 +155,15 @@ avx512_not_supported: mov ecx, APIC_LVT_PERF mov eax, 0x00010000 call apic_write ; Disable performance counter interrupts + cmp byte [p_x2APIC], 1 + je skip_APIC ; Next 2 registers are APIC only mov ecx, APIC_LDR xor eax, eax call apic_write ; Set Logical Destination Register mov ecx, APIC_DFR not eax ; Set EAX to 0xFFFFFFFF; Bits 31-28 set for Flat Mode call apic_write ; Set Destination Format Register +skip_APIC: mov ecx, APIC_LVT_LINT0 mov eax, 0x00008700 ; Bit 15 (1 = Level), Bits 10:8 for Ext call apic_write ; Enable normal external interrupts @@ -186,26 +191,58 @@ avx512_not_supported: ; ----------------------------------------------------------------------------- ; apic_read -- Read from a register in the APIC ; IN: ECX = Register to read -; OUT: EAX = Register value +; OUT: RAX = Register value ; All other registers preserved apic_read: + cmp byte [p_x2APIC], 1 + je apic_read_x2 + +apic_read_x: mov rax, [p_LocalAPICAddress] mov eax, [rax + rcx] ret + +apic_read_x2: + push rdx + push rcx + shr ecx, 4 ; Convert xAPIC register to x2APIC + add ecx, 0x800 ; Add MSR base offset + rdmsr ; Read to EDX:EAX + shl rdx, 32 ; Shift to upper 32 bits + or rax, rdx ; Combine into RAX + pop rcx + pop rdx + ret ; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- ; apic_write -- Write to a register in the APIC ; IN: ECX = Register to write -; EAX = Value to write +; RAX = Value to write ; OUT: All registers preserved apic_write: + cmp byte [p_x2APIC], 1 + je apic_write_x2 + +apic_write_x: push rcx add rcx, [p_LocalAPICAddress] mov [rcx], eax pop rcx ret + +apic_write_x2: + push rdx + push rcx + shr ecx, 4 ; Convert xAPIC register to x2APIC + add ecx, 0x800 ; Add MSR base offset + mov rdx, rax ; Copy RAX to RDX + shr rdx, 32 ; Shift upper 32 bits to lower 32 + wrmsr ; Write as EDX:EAX + pop rcx + pop rdx + ret ; ----------------------------------------------------------------------------- @@ -227,6 +264,7 @@ APIC_TMR equ 0x180 ; Trigger Mode Register (Starting Address) APIC_IRR equ 0x200 ; Interrupt Request Register (Starting Address) APIC_ESR equ 0x280 ; Error Status Register ; 0x290 - 0x2E0 are Reserved +APIC_ICR equ 0x300 ; Interrupt Command Register APIC_ICRL equ 0x300 ; Interrupt Command Register (low 32 bits) APIC_ICRH equ 0x310 ; Interrupt Command Register (high 32 bits) APIC_LVT_TMR equ 0x320 ; LVT Timer Register @@ -253,6 +291,37 @@ IA32_MTRR_PHYSMASK1 equ 0x203 IA32_PAT equ 0x277 IA32_MTRR_DEF_TYPE equ 0x2FF +; x2APIC MSR List +; 0x000 - 0x001 are Reserved +x2APIC_ID equ 0x002 ; ID Register +x2APIC_VER equ 0x003 ; Version Register +; 0x004 - 0x007 are Reserved +x2APIC_TPR equ 0x008 ; Task Priority Register - Bits 31:8 are Reserved. +; 0x009 is Reserved +x2APIC_PPR equ 0x00A ; Processor Priority Register +x2APIC_EOI equ 0x00B ; End Of Interrupt - Write 0 Only +; 0x00C is Reserved +x2APIC_LDR equ 0x00D ; Logical Destination Register - Read Only +; 0x00E is Reserved +x2APIC_SPURIOUS equ 0x00F ; Spurious Interrupt Vector Register +x2APIC_ISR equ 0x010 ; In-Service Register (Starting Address) - Read Only +x2APIC_TMR equ 0x018 ; Trigger Mode Register (Starting Address) - Read Only +x2APIC_IRR equ 0x020 ; Interrupt Request Register (Starting Address) - Read Only +x2APIC_ESR equ 0x028 ; Error Status Register +; 0x029 - 0x02E are Reserved +x2APIC_ICRL equ 0x030 ; Interrupt Command Register +x2APIC_LVT_TMR equ 0x032 ; LVT Timer Register +x2APIC_LVT_TSR equ 0x033 ; LVT Thermal Sensor Register +x2APIC_LVT_PERF equ 0x034 ; LVT Performance Monitoring Counters Register +x2APIC_LVT_LINT0 equ 0x035 ; LVT LINT0 Register +x2APIC_LVT_LINT1 equ 0x036 ; LVT LINT1 Register +x2APIC_LVT_ERR equ 0x037 ; LVT Error Register +x2APIC_TMRINITCNT equ 0x038 ; Initial Count Register (for Timer) +x2APIC_TMRCURRCNT equ 0x039 ; Current Count Register (for Timer) - Read Only +; 0x03A - 0x03D are Reserved +x2APIC_TMRDIV equ 0x03E ; Divide Configuration Register (for Timer) +x2APIC_SELF_IPI equ 0x03F ; Self IPI - Write Only +; 0x040 - 0x3FF are Reserved ; ============================================================================= ; EOF diff --git a/src/init/smp.asm b/src/init/smp.asm index 843539b..f2da210 100644 --- a/src/init/smp.asm +++ b/src/init/smp.asm @@ -31,16 +31,35 @@ smp_send_INIT: cmp al, dl ; Is it the BSP? je smp_send_INIT_skipcore + cmp byte [p_x2APIC], 1 + je smp_send_INIT_x2APIC + +smp_send_INIT_APIC: ; Send 'INIT' IPI to APIC ID in AL - mov rdi, [p_LocalAPICAddress] + push rcx shl eax, 24 - mov dword [rdi+0x310], eax ; Interrupt Command Register (ICR); bits 63-32 + mov ecx, APIC_ICRH ; Interrupt Command Register (ICR); bits 63-32 + call apic_write mov eax, 0x00004500 - mov dword [rdi+0x300], eax ; Interrupt Command Register (ICR); bits 31-0 + mov ecx, APIC_ICRL ; Interrupt Command Register (ICR); bits 31-0 + call apic_write smp_send_INIT_verify: - mov eax, [rdi+0x300] ; Interrupt Command Register (ICR); bits 31-0 + call apic_read bt eax, 12 ; Verify that the command completed jc smp_send_INIT_verify + pop rcx + jmp smp_send_INIT_APIC_done + +smp_send_INIT_x2APIC: + ; Send 'INIT' IPI to APIC ID in AL + push rcx + mov ecx, APIC_ICR ; Interrupt Command Register (ICR); bits 63-0 + shl rax, 32 + mov ax, 0x4500 + call apic_write + pop rcx + +smp_send_INIT_APIC_done: smp_send_INIT_skipcore: dec cl @@ -63,16 +82,35 @@ smp_send_SIPI: cmp al, dl ; Is it the BSP? je smp_send_SIPI_skipcore + cmp byte [p_x2APIC], 1 + je smp_send_SIPI_x2APIC + +smp_send_SIPI_APIC: ; Send 'Startup' IPI to destination using vector 0x08 to specify entry-point is at the memory-address 0x00008000 - mov rdi, [p_LocalAPICAddress] + push rcx shl eax, 24 - mov dword [rdi+0x310], eax ; Interrupt Command Register (ICR); bits 63-32 + mov ecx, APIC_ICRH ; Interrupt Command Register (ICR); bits 63-32 + call apic_write mov eax, 0x00004608 ; Vector 0x08 - mov dword [rdi+0x300], eax ; Interrupt Command Register (ICR); bits 31-0 + mov ecx, APIC_ICRL ; Interrupt Command Register (ICR); bits 31-0 + call apic_write smp_send_SIPI_verify: - mov eax, [rdi+0x300] ; Interrupt Command Register (ICR); bits 31-0 + call apic_read bt eax, 12 ; Verify that the command completed jc smp_send_SIPI_verify + pop rcx + jmp smp_send_SIPI_APIC_done + +smp_send_SIPI_x2APIC: + ; Send 'Startup' IPI to destination using vector 0x08 to specify entry-point is at the memory-address 0x00008000 + push rcx + mov ecx, APIC_ICR ; Interrupt Command Register (ICR); bits 63-0 + shl rax, 32 + mov ax, 0x4608 ; Vector 0x08 + call apic_write + pop rcx + +smp_send_SIPI_APIC_done: smp_send_SIPI_skipcore: dec cl @@ -86,11 +124,13 @@ smp_send_SIPI_done: noMP: ; Gather and store the APIC ID of the BSP - xor eax, eax - mov rsi, [p_LocalAPICAddress] - add rsi, 0x20 ; Add the offset for the APIC ID location - lodsd ; APIC ID is stored in bits 31:24 - shr rax, 24 ; AL now holds the CPU's APIC ID (0 - 255) + mov ecx, APIC_ID + call apic_read +; xor eax, eax +; mov rsi, [p_LocalAPICAddress] +; add rsi, 0x20 ; Add the offset for the APIC ID location +; lodsd ; APIC ID is stored in bits 31:24 +; shr rax, 24 ; AL now holds the CPU's APIC ID (0 - 255) mov [p_BSP], eax ; Store the BSP APIC ID ; Calculate base speed of CPU From 5073e88ac82b51bd774d3b143de714b4a5de5920 Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Sun, 26 Apr 2026 15:09:02 -0400 Subject: [PATCH 2/5] Add comment on x2APIC_BASE --- src/init/cpu.asm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/init/cpu.asm b/src/init/cpu.asm index 4559bcb..414295a 100644 --- a/src/init/cpu.asm +++ b/src/init/cpu.asm @@ -292,6 +292,7 @@ IA32_PAT equ 0x277 IA32_MTRR_DEF_TYPE equ 0x2FF ; x2APIC MSR List +x2APIC_BASE equ 0x800 ; 0x000 - 0x001 are Reserved x2APIC_ID equ 0x002 ; ID Register x2APIC_VER equ 0x003 ; Version Register From 676435f6476218a69beaef745cf5e0d75c631c83 Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Mon, 27 Apr 2026 18:30:17 -0400 Subject: [PATCH 3/5] x2APIC updates - Store ACPI APIC enties as 32-bit values - SMP - read APIC IDs as 32-bit values - SMP_AP - enable x2APIC prior to init_cpu as we need a stack. --- src/init/acpi.asm | 3 ++- src/init/smp.asm | 37 ++++++++++++++++++++----------------- src/init/smp_ap.asm | 20 +++++++++++++++++++- src/pure64.asm | 8 ++++---- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/init/acpi.asm b/src/init/acpi.asm index 460fe71..301957d 100644 --- a/src/init/acpi.asm +++ b/src/init/acpi.asm @@ -231,7 +231,7 @@ APICapic: ; Entry Type 0 jnc readAPICstructures ; Read the next structure if CPU not usable inc word [p_cpu_detected] xchg eax, edx ; Restore the APIC ID back to EAX - stosb ; Store the 8-bit APIC ID + stosd ; Store the 8-bit APIC ID as a 32-bit value jmp readAPICstructures ; Read the next structure ; I/O APIC Structure - 5.2.12.3 @@ -285,6 +285,7 @@ APICinterruptsourceoverride: ; Entry Type 2 jmp readAPICstructures ; Read the next structure ; Processor Local x2APIC Structure - 5.2.12.12 +; TODO - Check if the same ID was found via APICapic - if so, ignore ;APICx2apic: ; Entry Type 9 ; xor eax, eax ; xor edx, edx diff --git a/src/init/smp.asm b/src/init/smp.asm index f2da210..4b9bba9 100644 --- a/src/init/smp.asm +++ b/src/init/smp.asm @@ -11,13 +11,17 @@ init_smp: cmp byte [cfg_smpinit], 1 ; Check if SMP should be enabled jne noMP ; If not then skip SMP init - ; Start the AP's one by one - xor eax, eax - xor edx, edx - mov rsi, [p_LocalAPICAddress] - mov eax, [rsi+0x20] ; Add the offset for the APIC ID location - shr rax, 24 ; APIC ID is stored in bits 31:24 - mov dl, al ; Store BSP APIC ID in DL + ; Get the BSP APIC ID + mov ecx, APIC_ID + call apic_read + + cmp byte [p_x2APIC], 1 + je init_smp_get_apic_done + + shr eax, 24 ; APIC ID is stored in bits 31:24 + +init_smp_get_apic_done: + mov edx, eax ; Store BSP APIC ID in EDX mov esi, IM_DetectedCoreIDs xor eax, eax @@ -26,9 +30,9 @@ init_smp: smp_send_INIT: cmp cx, 0 je smp_send_INIT_done - lodsb + lodsd - cmp al, dl ; Is it the BSP? + cmp eax, edx ; Is it the BSP? je smp_send_INIT_skipcore cmp byte [p_x2APIC], 1 @@ -77,9 +81,9 @@ smp_send_INIT_done: smp_send_SIPI: cmp cx, 0 je smp_send_SIPI_done - lodsb + lodsd - cmp al, dl ; Is it the BSP? + cmp eax, edx ; Is it the BSP? je smp_send_SIPI_skipcore cmp byte [p_x2APIC], 1 @@ -126,12 +130,11 @@ noMP: ; Gather and store the APIC ID of the BSP mov ecx, APIC_ID call apic_read -; xor eax, eax -; mov rsi, [p_LocalAPICAddress] -; add rsi, 0x20 ; Add the offset for the APIC ID location -; lodsd ; APIC ID is stored in bits 31:24 -; shr rax, 24 ; AL now holds the CPU's APIC ID (0 - 255) - mov [p_BSP], eax ; Store the BSP APIC ID + cmp byte [p_x2APIC], 1 + je smp_store_apic_id + shr eax, 24 ; AL now holds the CPU's APIC ID (0 - 255) +smp_store_apic_id: + mov [p_BSP], edx ; Store the BSP APIC ID ; Calculate base speed of CPU cpuid diff --git a/src/init/smp_ap.asm b/src/init/smp_ap.asm index 3815c96..4b06541 100644 --- a/src/init/smp_ap.asm +++ b/src/init/smp_ap.asm @@ -119,11 +119,29 @@ startap64: mov fs, ax mov gs, ax - ; Reset the stack. Each CPU gets a 1024-byte unique stack location + ; Configure the stack + cmp byte [p_x2APIC], 1 + je get_id_x2APIC + +get_id_APIC: mov rsi, [p_LocalAPICAddress] ; We would call p_smp_get_id here but the stack is not ... add rsi, 0x20 ; ... yet defined. It is safer to find the value directly. lodsd ; Load a 32-bit value. We only want the high 8 bits shr rax, 24 ; Shift to the right and AL now holds the CPU's APIC ID + jmp get_id_done + +get_id_x2APIC: + mov ecx, IA32_APIC_BASE + rdmsr + bts eax, 11 ; APIC Global Enable + bts eax, 10 ; Enable x2APIC mode + wrmsr + + mov ecx, 0x802 + rdmsr ; APIC ID returned in EAX + +get_id_done: + ; Reset the stack. Each CPU gets a 1024-byte unique stack location shl rax, 10 ; shift left 10 bits for a 1024byte stack add rax, 0x0000000000090000 ; stacks decrement when you "push", start at 1024 bytes in mov rsp, rax ; Pure64 leaves 0x50000-0x9FFFF free so we use that diff --git a/src/pure64.asm b/src/pure64.asm index 91d61ec..57e0eec 100644 --- a/src/pure64.asm +++ b/src/pure64.asm @@ -20,11 +20,11 @@ BITS 64 ORG 0x00008000 DEFAULT ABS -%ifdef NOVIDEO -PURE64SIZE equ 4096 ; Pad Pure64 to this length -%else +;%ifdef NOVIDEO +;PURE64SIZE equ 4096 ; Pad Pure64 to this length +;%else PURE64SIZE equ 6144 ; Pad Pure64 to this length -%endif +;%endif start: jmp bootmode ; This command will be overwritten with 'NOP's before the AP's are started From d71c907ed4addb7926a865541a4d161ae8b385f0 Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Tue, 28 Apr 2026 14:30:54 -0400 Subject: [PATCH 4/5] APIC ID shift check. --- src/init/cpu.asm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/init/cpu.asm b/src/init/cpu.asm index 414295a..0671771 100644 --- a/src/init/cpu.asm +++ b/src/init/cpu.asm @@ -180,7 +180,10 @@ skip_APIC: lock inc word [p_cpu_activated] mov ecx, APIC_ID call apic_read ; APIC ID is stored in bits 31:24 + cmp byte [p_x2APIC], 1 + je skip_shift shr eax, 24 ; AL now holds the CPU's APIC ID (0 - 255) +skip_shift: mov rdi, IM_ActivedCoreIDs ; The location where the activated cores set their record to 1 add rdi, rax ; RDI points to InfoMap CPU area + APIC ID. ex 0x5E01 would be APIC ID 1 mov al, 1 From 8bb3a4924eabe3f344cbc64545e393608ae5877a Mon Sep 17 00:00:00 2001 From: Ian Seyler Date: Tue, 28 Apr 2026 15:33:30 -0400 Subject: [PATCH 5/5] APIC progress - reconfigure saving of BSP APIC ID --- src/init/cpu.asm | 20 +++++++++++++------- src/init/smp.asm | 33 +++++++-------------------------- src/init/smp_ap.asm | 9 +++------ src/pure64.asm | 23 +++++++---------------- 4 files changed, 30 insertions(+), 55 deletions(-) diff --git a/src/init/cpu.asm b/src/init/cpu.asm index 0671771..75b4f00 100644 --- a/src/init/cpu.asm +++ b/src/init/cpu.asm @@ -138,13 +138,15 @@ avx512_not_supported: ; Enable APIC mov ecx, IA32_APIC_BASE rdmsr - bts eax, 11 ; APIC Global Enable + bts eax, 11 ; EN - xAPIC global enable/disable cmp byte [p_x2APIC], 1 jne skip_x2APIC_enable - bts eax, 10 ; Enable x2APIC mode + bts eax, 10 ; EXTD - Enable x2APIC mode skip_x2APIC_enable: wrmsr + mov r8d, eax ; Save MSR value as bit 8 is checked later + ; Configure APIC mov ecx, APIC_TPR mov eax, 0x00000020 @@ -179,13 +181,17 @@ skip_APIC: lock inc word [p_cpu_activated] mov ecx, APIC_ID - call apic_read ; APIC ID is stored in bits 31:24 + call apic_read cmp byte [p_x2APIC], 1 je skip_shift shr eax, 24 ; AL now holds the CPU's APIC ID (0 - 255) skip_shift: - mov rdi, IM_ActivedCoreIDs ; The location where the activated cores set their record to 1 - add rdi, rax ; RDI points to InfoMap CPU area + APIC ID. ex 0x5E01 would be APIC ID 1 + bt r8d, 8 ; Check for BSP bit + jnc skip_bsp + mov [p_BSP], eax +skip_bsp: + mov edi, IM_ActivedCoreIDs ; The location where the activated cores set their record to 1 + add edi, eax ; RDI points to InfoMap CPU area + APIC ID. ex 0x5E01 would be APIC ID 1 mov al, 1 stosb ; Store a 1 as the core is activated @@ -267,7 +273,7 @@ APIC_TMR equ 0x180 ; Trigger Mode Register (Starting Address) APIC_IRR equ 0x200 ; Interrupt Request Register (Starting Address) APIC_ESR equ 0x280 ; Error Status Register ; 0x290 - 0x2E0 are Reserved -APIC_ICR equ 0x300 ; Interrupt Command Register +APIC_ICR equ 0x300 ; Interrupt Command Register (64-bit - x2APIC only) APIC_ICRL equ 0x300 ; Interrupt Command Register (low 32 bits) APIC_ICRH equ 0x310 ; Interrupt Command Register (high 32 bits) APIC_LVT_TMR equ 0x320 ; LVT Timer Register @@ -313,7 +319,7 @@ x2APIC_TMR equ 0x018 ; Trigger Mode Register (Starting Address) - Read Only x2APIC_IRR equ 0x020 ; Interrupt Request Register (Starting Address) - Read Only x2APIC_ESR equ 0x028 ; Error Status Register ; 0x029 - 0x02E are Reserved -x2APIC_ICRL equ 0x030 ; Interrupt Command Register +x2APIC_ICR equ 0x030 ; Interrupt Command Register x2APIC_LVT_TMR equ 0x032 ; LVT Timer Register x2APIC_LVT_TSR equ 0x033 ; LVT Thermal Sensor Register x2APIC_LVT_PERF equ 0x034 ; LVT Performance Monitoring Counters Register diff --git a/src/init/smp.asm b/src/init/smp.asm index 4b9bba9..1903817 100644 --- a/src/init/smp.asm +++ b/src/init/smp.asm @@ -11,19 +11,8 @@ init_smp: cmp byte [cfg_smpinit], 1 ; Check if SMP should be enabled jne noMP ; If not then skip SMP init - ; Get the BSP APIC ID - mov ecx, APIC_ID - call apic_read - - cmp byte [p_x2APIC], 1 - je init_smp_get_apic_done - - shr eax, 24 ; APIC ID is stored in bits 31:24 - -init_smp_get_apic_done: - mov edx, eax ; Store BSP APIC ID in EDX - - mov esi, IM_DetectedCoreIDs + mov edx, [p_BSP] ; Get the BSP APIC ID + mov esi, IM_DetectedCoreIDs ; List of 32-bit APIC IDs xor eax, eax xor ecx, ecx mov cx, [p_cpu_detected] @@ -33,14 +22,14 @@ smp_send_INIT: lodsd cmp eax, edx ; Is it the BSP? - je smp_send_INIT_skipcore + je smp_send_INIT_skipcore ; If so, skip cmp byte [p_x2APIC], 1 je smp_send_INIT_x2APIC smp_send_INIT_APIC: ; Send 'INIT' IPI to APIC ID in AL - push rcx + push rcx ; Save counter shl eax, 24 mov ecx, APIC_ICRH ; Interrupt Command Register (ICR); bits 63-32 call apic_write @@ -51,17 +40,17 @@ smp_send_INIT_verify: call apic_read bt eax, 12 ; Verify that the command completed jc smp_send_INIT_verify - pop rcx + pop rcx ; Restore counter jmp smp_send_INIT_APIC_done smp_send_INIT_x2APIC: ; Send 'INIT' IPI to APIC ID in AL - push rcx + push rcx ; Save counter mov ecx, APIC_ICR ; Interrupt Command Register (ICR); bits 63-0 shl rax, 32 mov ax, 0x4500 call apic_write - pop rcx + pop rcx ; Restore counter smp_send_INIT_APIC_done: @@ -127,14 +116,6 @@ smp_send_SIPI_done: call timer_delay noMP: - ; Gather and store the APIC ID of the BSP - mov ecx, APIC_ID - call apic_read - cmp byte [p_x2APIC], 1 - je smp_store_apic_id - shr eax, 24 ; AL now holds the CPU's APIC ID (0 - 255) -smp_store_apic_id: - mov [p_BSP], edx ; Store the BSP APIC ID ; Calculate base speed of CPU cpuid diff --git a/src/init/smp_ap.asm b/src/init/smp_ap.asm index 4b06541..cc73ff9 100644 --- a/src/init/smp_ap.asm +++ b/src/init/smp_ap.asm @@ -119,29 +119,26 @@ startap64: mov fs, ax mov gs, ax - ; Configure the stack + ; Gather the CPU APIC ID without using the stack cmp byte [p_x2APIC], 1 je get_id_x2APIC - get_id_APIC: mov rsi, [p_LocalAPICAddress] ; We would call p_smp_get_id here but the stack is not ... add rsi, 0x20 ; ... yet defined. It is safer to find the value directly. lodsd ; Load a 32-bit value. We only want the high 8 bits shr rax, 24 ; Shift to the right and AL now holds the CPU's APIC ID jmp get_id_done - get_id_x2APIC: mov ecx, IA32_APIC_BASE rdmsr bts eax, 11 ; APIC Global Enable bts eax, 10 ; Enable x2APIC mode wrmsr - mov ecx, 0x802 rdmsr ; APIC ID returned in EAX - get_id_done: - ; Reset the stack. Each CPU gets a 1024-byte unique stack location + + ; Set the stack. Each CPU gets a 1024-byte unique stack location shl rax, 10 ; shift left 10 bits for a 1024byte stack add rax, 0x0000000000090000 ; stacks decrement when you "push", start at 1024 bytes in mov rsp, rax ; Pure64 leaves 0x50000-0x9FFFF free so we use that diff --git a/src/pure64.asm b/src/pure64.asm index 57e0eec..655bf0c 100644 --- a/src/pure64.asm +++ b/src/pure64.asm @@ -20,11 +20,11 @@ BITS 64 ORG 0x00008000 DEFAULT ABS -;%ifdef NOVIDEO -;PURE64SIZE equ 4096 ; Pad Pure64 to this length -;%else +%ifdef NOVIDEO +PURE64SIZE equ 4096 ; Pad Pure64 to this length +%else PURE64SIZE equ 6144 ; Pad Pure64 to this length -;%endif +%endif start: jmp bootmode ; This command will be overwritten with 'NOP's before the AP's are started @@ -720,7 +720,7 @@ pde_end: ; Read APIC Address from MSR and enable it (if not done so already) mov ecx, IA32_APIC_BASE rdmsr ; Returns APIC in EDX:EAX - bts eax, 11 ; APIC Global Enable + bts eax, 11 ; EN - xAPIC global enable wrmsr and eax, 0xFFFFF000 ; Clear lower 12 bits shl rdx, 32 ; Shift lower 32 bits to upper 32 bits @@ -729,10 +729,10 @@ pde_end: ; Check for x2APIC support mov eax, 1 - cpuid ; x2APIC is supported if bit 21 is set + cpuid ; x2APIC is supported if ECX[21] is set shr ecx, 21 and cl, 1 - mov byte [p_x2APIC], cl + mov byte [p_x2APIC], cl ; Set flag for x2APIC %ifndef NOVIDEO ; Visual Debug (3/8) @@ -799,15 +799,6 @@ pde_end: call debug_msg %endif -; Reset the stack to the proper location (was set to 0x8000 previously) - mov rsi, [p_LocalAPICAddress] ; We would call p_smp_get_id here but the stack is not ... - add rsi, 0x20 ; ... yet defined. It is safer to find the value directly. - lodsd ; Load a 32-bit value. We only want the high 8 bits - shr rax, 24 ; Shift to the right and AL now holds the CPU's APIC ID - shl rax, 10 ; shift left 10 bits for a 1024byte stack - add rax, 0x0000000000050400 ; stacks decrement when you "push", start at 1024 bytes in - mov rsp, rax ; Pure64 leaves 0x50000-0x9FFFF free so we use that - ; Build the InfoMap xor edi, edi mov di, 0x5000