diff --git a/LICENSE b/LICENSE
index a6281eb..003b733 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2023 Return Infinity
+Copyright (c) 2024 Return Infinity
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/docs/CREDITS.TXT b/docs/CREDITS.TXT
index f7fd74d..e82f2e1 100644
--- a/docs/CREDITS.TXT
+++ b/docs/CREDITS.TXT
@@ -1,6 +1,6 @@
===============================================================================
Pure64 -- a 64-bit loader written in Assembly for x86-64 systems
-Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
===============================================================================
diff --git a/docs/README.md b/docs/README.md
index 233793e..32d9a3d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -175,18 +175,47 @@ The Pure64 information table is located at `0x0000000000005000` and ends at `0x0
| 0x5016 - 0x501F | | | For future use |
| 0x5020 | 32-bit | RAMAMOUNT | Amount of system RAM in Mebibytes (MiB) |
| 0x5022 - 0x502F | | | For future use |
-| 0x5030 | 8-bit | IOAPIC_COUNT | Number of IO-APICs in the system |
-| 0x5031 - 0x503F | | | For future use |
+| 0x5030 | 8-bit | IOAPIC_COUNT | Number of I/O APICs in the system |
+| 0x5031 | 8-bit | IOAPIC_INTSOURCE_COUNT | Number of I/O APIC Interrupt Source Override |
+| 0x5032 - 0x503F | | | For future use |
| 0x5040 | 64-bit | HPET | Base memory address for the High Precision Event Timer |
| 0x5048 - 0x505F | | | For future use |
| 0x5060 | 64-bit | LAPIC | Local APIC address |
-| 0x5068 - 0x507F | 64-bit | IOAPIC | IO-APIC addresses (based on IOAPIC_COUNT) |
+| 0x5068 - 0x507F | | | For future use |
| 0x5080 | 32-bit | VIDEO_BASE | Base memory for video (if graphics mode set) |
| 0x5084 | 16-bit | VIDEO_X | X resolution |
| 0x5086 | 16-bit | VIDEO_Y | Y resolution |
| 0x5088 | 8-bit | VIDEO_DEPTH | Color depth |
| 0x5089 - 0x50FF | | | For future use |
-| 0x5100... | 8-bit | APIC_ID | APIC ID's for valid CPU cores (based on CORES_ACTIVE) |
+| 0x5100 - 0x51FF | 8-bit | APIC_ID | APIC ID's for valid CPU cores (based on CORES_ACTIVE) |
+| 0x5200 - 0x56FF | | | For future use |
+| 0x5600 - 0x56FF | 16 byte entries | IOAPIC | I/O APIC addresses (based on IOAPIC_COUNT) |
+| 0x5700 - 0x57FF | 8 byte entries | IOAPIC_INTSOURCE | I/O APIC Interrupt Source Override Entries (based on IOAPIC_INTSOURCE_COUNT) |
+
+
+IOAPIC list format:
+
+| Offset | Variable Size | Name | Description |
+| 0x00 | 32-bit | I/O APIC ID | The ID of an I/O APIC |
+| 0x00 | 32-bit | I/O APIC Address | The 32-bit physical address to access this I/O APIC |
+| 0x00 | 32-bit | Global System Interrupt Base | The global system interrupt number where this I/O APIC’s interrupt inputs start |
+| 0x00 | 32-bit | Reserved | This value should be 0 |
+
+
+IOAPIC_INTSOURCE list format:
+
+| Offset | Variable Size | Name | Description |
+| 0x00 | 8-bit | Bus | 0 |
+| 0x00 | 8-bit | Source | Bus-relative interrupt source |
+| 0x00 | 32-bit | Global System Interrupt | The Global System Interrupt that this bus-relative interrupt source will signal |
+| 0x00 | 16-bit | Flags | MPS INTI flags |
+
+
+MPS INTI flags:
+
+| Flags | Bit Length | Bit Offset | Description |
+| Polarity | 2 | 0 | 01 Active high, 11 Active low |
+| Trigger Mode | 2 | 2 | 01 Edge-triggered, 11 Level-triggered |
A copy of the E820 System Memory Map is stored at memory address `0x0000000000006000`. Each E820 record is 32 bytes in length and the memory map is terminated by a blank record.
diff --git a/src/boot/mbr.asm b/src/boot/mbr.asm
index 8104aab..03e7ba1 100644
--- a/src/boot/mbr.asm
+++ b/src/boot/mbr.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 MBR -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; This Master Boot Record will load Pure64 from a pre-defined location on the
; hard drive without making use of the file system.
@@ -225,7 +225,7 @@ times 510-$+$$ db 0
sign dw 0xAA55
-VBEModeInfoBlock: equ 0x5C00
+VBEModeInfoBlock: equ 0x5F00
; VESA
; Mandatory information for all VBE revisions
VBEModeInfoBlock.ModeAttributes equ VBEModeInfoBlock + 0 ; DW - mode attributes
diff --git a/src/boot/multiboot.asm b/src/boot/multiboot.asm
index cc796f6..33e7199 100644
--- a/src/boot/multiboot.asm
+++ b/src/boot/multiboot.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 Multiboot -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; http://stackoverflow.com/questions/33488194/creating-a-simple-multiboot-kernel-loaded-with-grub2
; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#OS-image-format
diff --git a/src/boot/multiboot2.asm b/src/boot/multiboot2.asm
index 6656884..bee725b 100644
--- a/src/boot/multiboot2.asm
+++ b/src/boot/multiboot2.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 Multiboot 2 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; http://nongnu.askapache.com/grub/phcoder/multiboot.pdf
; =============================================================================
diff --git a/src/boot/pxestart.asm b/src/boot/pxestart.asm
index fefdad9..67667ae 100644
--- a/src/boot/pxestart.asm
+++ b/src/boot/pxestart.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 PXE Start -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; This is a stub file for loading Pure64 and a kernel/software package via PXE.
;
@@ -191,7 +191,7 @@ sign dw 0xAA55 ; BIOS boot sector signature
times 1024-$+$$ db 0 ; Padding so that Pure64 will be aligned at 0x8000
-VBEModeInfoBlock: equ 0x5C00
+VBEModeInfoBlock: equ 0x5F00
; VESA
; Mandatory information for all VBE revisions
VBEModeInfoBlock.ModeAttributes equ VBEModeInfoBlock + 0 ; DW - mode attributes
diff --git a/src/boot/uefi.asm b/src/boot/uefi.asm
index 9c620bc..9804d61 100644
--- a/src/boot/uefi.asm
+++ b/src/boot/uefi.asm
@@ -1,6 +1,6 @@
; =============================================================================
; UEFI loader for Pure64
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; Adapted from https://stackoverflow.com/questions/72947069/how-to-write-hello-world-efi-application-in-nasm
; and https://github.com/charlesap/nasm-uefi/blob/master/shoe-x64.asm
diff --git a/src/init/acpi.asm b/src/init/acpi.asm
index 3eca13d..221d911 100644
--- a/src/init/acpi.asm
+++ b/src/init/acpi.asm
@@ -1,13 +1,13 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; INIT ACPI
; =============================================================================
init_acpi:
- mov al, [BootMode]
+ mov al, [p_BootMode]
cmp al, 'U'
je foundACPIfromUEFI
mov esi, 0x000E0000 ; Start looking for the Root System Description Pointer Structure
@@ -58,7 +58,7 @@ foundACPIv1:
cmp eax, 'RSDT' ; Make sure the signature is valid
jne novalidacpi ; Not the same? Bail out
sub rsi, 4
- mov [os_ACPITableAddress], rsi ; Save the RSDT Table Address
+ mov [p_ACPITableAddress], rsi ; Save the RSDT Table Address
add rsi, 4
xor eax, eax
lodsd ; Length
@@ -84,7 +84,7 @@ foundACPIv2:
cmp eax, 'XSDT' ; Make sure the signature is valid
jne novalidacpi ; Not the same? Bail out
sub rsi, 4
- mov [os_ACPITableAddress], rsi ; Save the XSDT Table Address
+ mov [p_ACPITableAddress], rsi ; Save the XSDT Table Address
add rsi, 4
xor eax, eax
lodsd ; Length
@@ -112,6 +112,9 @@ nextACPITable:
mov ebx, 'HPET' ; Signature for the HPET Description Table
cmp eax, ebx
je foundHPETTable
+; mov ebx, 'MCFG' ; Signature for the PCIe Enhanced Configuration Mechanism
+; cmp eax, ebx
+; je foundMCFGTable
cmp ecx, edx
jne nextACPITable
jmp init_smp_acpi_done ;noACPIAPIC
@@ -124,6 +127,10 @@ foundHPETTable:
call parseHPETTable
jmp nextACPITable
+;foundMCFGTable:
+; call parseMCFGTable
+; jmp nextACPITable
+
init_smp_acpi_done:
ret
@@ -148,10 +155,8 @@ parseAPICTable:
lodsd ; OEM Revision
lodsd ; Creator ID
lodsd ; Creator Revision
- xor eax, eax
- lodsd ; Local APIC Address
- mov [os_LocalAPICAddress], rax ; Save the Address of the Local APIC
- lodsd ; Flags
+ lodsd ; Local APIC Address (This should match what was pulled already via the MSR)
+ lodsd ; Flags (1 = Dual 8259 Legacy PICs Installed)
add ebx, 44
mov rdi, 0x0000000000005100 ; Valid CPU IDs
@@ -171,14 +176,20 @@ readAPICstructures:
; je APIClocalapicnmi
; cmp al, 0x05 ; Local APIC Address Override
; je APICaddressoverride
- cmp al, 0x09 ; Processor Local x2APIC
- je APICx2apic
+; cmp al, 0x06 ; I/O SAPIC Structure
+; je APICiosapic
+; cmp al, 0x07 ; Local SAPIC Structure
+; je APIClocalsapic
+; cmp al, 0x08 ; Platform Interrupt Source Structure
+; je APICplatformint
+; cmp al, 0x09 ; Processor Local x2APIC
+; je APICx2apic
; cmp al, 0x0A ; Local x2APIC NMI
; je APICx2nmi
jmp APICignore
-APICapic:
+APICapic: ; Entry Type 0
xor eax, eax
xor edx, edx
lodsb ; Length (will be set to 8)
@@ -189,60 +200,75 @@ APICapic:
lodsd ; Flags (Bit 0 set if enabled/usable)
bt eax, 0 ; Test to see if usable
jnc readAPICstructures ; Read the next structure if CPU not usable
- inc word [cpu_detected]
+ inc word [p_cpu_detected]
xchg eax, edx ; Restore the APIC ID back to EAX
stosb
jmp readAPICstructures ; Read the next structure
-APICioapic:
+APICioapic: ; Entry Type 1
xor eax, eax
lodsb ; Length (will be set to 12)
add ebx, eax
- lodsb ; IO APIC ID
- lodsb ; Reserved
- xor eax, eax
- lodsd ; IO APIC Address
push rdi
push rcx
- mov rdi, os_IOAPICAddress
+ mov rdi, IM_IOAPICAddress ; Copy this data directly to the InfoMap
xor ecx, ecx
- mov cl, [os_IOAPICCount]
- shl cx, 3 ; Quick multiply by 8
+ mov cl, [p_IOAPICCount]
+ shl cx, 4 ; Quick multiply by 16
add rdi, rcx
pop rcx
- stosd ; Store the IO APIC Address
- lodsd ; System Vector Base
- stosd ; Store the IO APIC Vector Base
+ xor eax, eax
+ lodsb ; IO APIC ID
+ stosd
+ lodsb ; Reserved
+ lodsd ; I/O APIC Address
+ stosd
+ lodsd ; Global System Interrupt Base
+ stosd
pop rdi
- inc byte [os_IOAPICCount]
+ inc byte [p_IOAPICCount]
jmp readAPICstructures ; Read the next structure
-APICinterruptsourceoverride:
+APICinterruptsourceoverride: ; Entry Type 2
xor eax, eax
lodsb ; Length (will be set to 10)
add ebx, eax
- lodsb ; Bus
- lodsb ; Source
+ push rdi
+ push rcx
+ mov rdi, IM_IOAPICIntSource ; Copy this data directly to the InfoMap
+ xor ecx, ecx
+ mov cl, [p_IOAPICIntSourceC]
+ shl cx, 3 ; Quick multiply by 8
+ add rdi, rcx
+ lodsb ; Bus Source
+ stosb
+ lodsb ; IRQ Source
+ stosb
lodsd ; Global System Interrupt
- lodsw ; Flags
+ stosd
+ lodsw ; Flags - bit 1 Low(1)/High(0), Bit 3 Level(1)/Edge(0)
+ stosw
+ pop rcx
+ pop rdi
+ inc byte [p_IOAPICIntSourceC]
jmp readAPICstructures ; Read the next structure
-APICx2apic:
- xor eax, eax
- xor edx, edx
- lodsb ; Length (will be set to 16)
- add ebx, eax
- lodsw ; Reserved; Must be Zero
- lodsd
- xchg eax, edx ; Save the x2APIC ID to EDX
- lodsd ; Flags (Bit 0 set if enabled/usable)
- bt eax, 0 ; Test to see if usable
- jnc APICx2apicEnd ; Read the next structure if CPU not usable
- xchg eax, edx ; Restore the x2APIC ID back to EAX
- ; TODO - Save the ID's somewhere
-APICx2apicEnd:
- lodsd ; ACPI Processor UID
- jmp readAPICstructures ; Read the next structure
+;APICx2apic: ; Entry Type 9
+; xor eax, eax
+; xor edx, edx
+; lodsb ; Length (will be set to 16)
+; add ebx, eax
+; lodsw ; Reserved; Must be Zero
+; lodsd
+; xchg eax, edx ; Save the x2APIC ID to EDX
+; lodsd ; Flags (Bit 0 set if enabled/usable)
+; bt eax, 0 ; Test to see if usable
+; jnc APICx2apicEnd ; Read the next structure if CPU not usable
+; xchg eax, edx ; Restore the x2APIC ID back to EAX
+; ; TODO - Save the ID's somewhere
+;APICx2apicEnd:
+; lodsd ; ACPI Processor UID
+; jmp readAPICstructures ; Read the next structure
APICignore:
xor eax, eax
@@ -273,7 +299,7 @@ parseHPETTable:
lodsd ; Event Timer Block ID
lodsd ; Base Address Settings
lodsq ; Base Address Value
- mov [os_HPETAddress], rax ; Save the Address of the HPET
+ mov [p_HPETAddress], rax ; Save the Address of the HPET
lodsb ; HPET Number
lodsw ; Main Counter Minimum
lodsw ; Page Protection And OEM Attribute
@@ -281,5 +307,29 @@ parseHPETTable:
; -----------------------------------------------------------------------------
+; -----------------------------------------------------------------------------
+;parseMCFGTable:
+; lodsd ; Length of MCFG in bytes
+; lodsb ; Revision
+; lodsb ; Checksum
+; lodsd ; OEMID (First 4 bytes)
+; lodsw ; OEMID (Last 2 bytes)
+; lodsq ; OEM Table ID
+; lodsd ; OEM Revision
+; lodsd ; Creator ID
+; lodsd ; Creator Revision
+; lodsq ; Reserved
+;
+; ; Loop through each entry
+; lodsq ; Base address of enhanced configuration mechanism
+; lodsw ; PCI Segment Group Number
+; lodsb ; Start PCI bus number decoded by this host bridge
+; lodsb ; End PCI bus number decoded by this host bridge
+; lodsd ; Reserved
+;
+; ret
+; -----------------------------------------------------------------------------
+
+
; =============================================================================
; EOF
diff --git a/src/init/cpu.asm b/src/init/cpu.asm
index 6105e94..030a359 100644
--- a/src/init/cpu.asm
+++ b/src/init/cpu.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; INIT CPU - This code is called by all activated CPU cores in the system
; =============================================================================
@@ -88,74 +88,123 @@ init_cpu:
finit
; Enable AVX
- mov eax, 1 ; CPUID Feature information 1
- cpuid ; Sets info in eax and ecx
- bt ecx, 28 ; AVX is supported if bit 28 is set in ecx
- jnc avx_not_supported ; Skip activating AVX if not supported
-
+ mov eax, 1 ; CPUID Feature information 1
+ cpuid ; Sets info in eax and ecx
+ bt ecx, 28 ; AVX is supported if bit 28 is set in ecx
+ jnc avx_not_supported ; Skip activating AVX if not supported
avx_supported:
-
mov rax, cr4
bts rax, 18 ; Enable OSXSAVE (Bit 18)
mov cr4, rax
-
- mov rcx, 0 ; Set load XCR Nr. 0
+ mov rcx, 0 ; Set load XCR Nr. 0
xgetbv ; Load XCR0 register
- bts rax, 0 ; Set X87 enable (Bit 0)
- bts rax, 1 ; Set SSE enable (Bit 1)
- bts rax, 2 ; Set AVX enable (Bit 2)
+ bts rax, 0 ; Set X87 enable (Bit 0)
+ bts rax, 1 ; Set SSE enable (Bit 1)
+ bts rax, 2 ; Set AVX enable (Bit 2)
xsetbv ; Save XCR0 register
avx_not_supported:
; Enable and Configure Local APIC
- mov rsi, [os_LocalAPICAddress]
- test rsi, rsi
- je noMP ; Skip MP init if we didn't get a valid LAPIC address
-
- xor eax, eax ; Clear Task Priority (bits 7:4) and Priority Sub-Class (bits 3:0)
- mov dword [rsi+0x80], eax ; Task Priority Register (TPR)
-
- mov eax, 0x01000000 ; Set bits 31-24 for all cores to be in Group 1
- mov dword [rsi+0xD0], eax ; Logical Destination Register
-
+ mov ecx, APIC_TPR
+ mov eax, 0x00000020
+ call apic_write ; Disable softint delivery
+ mov ecx, APIC_LVT_TMR
+ mov eax, 0x00010000
+ call apic_write ; Disable timer interrupts
+ mov ecx, APIC_LVT_PERF
+ mov eax, 0x00010000
+ call apic_write ; Disable performance counter interrupts
+ 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
- mov dword [rsi+0xE0], eax ; Destination Format Register
-
- mov eax, dword [rsi+0xF0] ; Spurious Interrupt Vector Register
- mov al, 0xF8
- bts eax, 8 ; Enable APIC (Set bit 8)
- mov dword [rsi+0xF0], eax
-
- mov eax, dword [rsi+0x320] ; LVT Timer Register
- bts eax, 16 ; Set bit 16 for mask interrupts
- mov dword [rsi+0x320], eax
-
-; mov eax, dword [rsi+0x350] ; LVT LINT0 Register
-; mov al, 0 ;Set interrupt vector (bits 7:0)
-; bts eax, 8 ;Delivery Mode (111b==ExtlNT] (bits 10:8)
-; bts eax, 9
-; bts eax, 10
-; bts eax, 15 ;bit15:Set trigger mode to Level (0== Edge, 1== Level)
-; btr eax, 16 ;bit16:unmask interrupts (0==Unmasked, 1== Masked)
-; mov dword [rsi+0x350], eax
-
-; mov eax, dword [rsi+0x360] ; LVT LINT1 Register
-; mov al, 0 ;Set interrupt vector (bits 7:0)
-; bts eax, 8 ;Delivery Mode (111b==ExtlNT] (bits 10:8)
-; bts eax, 9
-; bts eax, 10
-; bts eax, 15 ;bit15:Set trigger mode to Edge (0== Edge, 1== Level)
-; btr eax, 16 ;bit16:unmask interrupts (0==Unmasked, 1== Masked)
-; mov dword [rsi+0x360], eax
-
-; mov eax, dword [rsi+0x370] ; LVT Error Register
-; mov al, 0 ;Set interrupt vector (bits 7:0)
-; bts eax, 16 ;bit16:Mask interrupts (0==Unmasked, 1== Masked)
-; mov dword [rsi+0x370], eax
-
-
-ret
+ call apic_write ; Set Destination Format Register
+ mov ecx, APIC_LVT_LINT0
+ mov eax, 0x00008700 ; Bit 15 (1 = Level), Bits 10:8 for Ext
+ call apic_write ; Enable normal external interrupts
+ mov ecx, APIC_LVT_LINT1
+ mov eax, 0x00000400
+ call apic_write ; Enable normal NMI processing
+ mov ecx, APIC_LVT_ERR
+ mov eax, 0x00010000
+ call apic_write ; Disable error interrupts
+ mov ecx, APIC_SPURIOUS
+ mov eax, 0x000001FF
+ call apic_write ; Enable the APIC (bit 8) and set spurious vector to 0xFF
+
+ lock inc word [p_cpu_activated]
+ mov ecx, APIC_ID
+ call apic_read ; APIC ID is stored in bits 31:24
+ shr rax, 24 ; AL now holds the CPU's APIC ID (0 - 255)
+ mov rdi, 0x00005700 ; The location where the cpu values are stored
+ add rdi, rax ; RDI points to InfoMap CPU area + APIC ID. ex 0x5701 would be APIC ID 1
+ mov al, 1
+ stosb
+
+ ret
+
+; -----------------------------------------------------------------------------
+; apic_read -- Read from a register in the APIC
+; IN: ECX = Register to read
+; OUT: EAX = Register value
+; All other registers preserved
+apic_read:
+ push rsi
+ mov rsi, [p_LocalAPICAddress]
+ add rsi, rcx ; Add offset
+ lodsd
+ pop rsi
+ ret
+; -----------------------------------------------------------------------------
+
+
+; -----------------------------------------------------------------------------
+; apic_write -- Write to a register in the APIC
+; IN: ECX = Register to write
+; EAX = Value to write
+; OUT: All registers preserved
+apic_write:
+ push rdi
+ mov rdi, [p_LocalAPICAddress]
+ add rdi, rcx ; Add offset
+ stosd
+ pop rdi
+ ret
+; -----------------------------------------------------------------------------
+
+
+; Register list
+; 0x000 - 0x010 are Reserved
+APIC_ID equ 0x020 ; ID Register
+APIC_VER equ 0x030 ; Version Register
+; 0x040 - 0x070 are Reserved
+APIC_TPR equ 0x080 ; Task Priority Register
+APIC_APR equ 0x090 ; Arbitration Priority Register
+APIC_PPR equ 0x0A0 ; Processor Priority Register
+APIC_EOI equ 0x0B0 ; End Of Interrupt
+APIC_RRD equ 0x0C0 ; Remote Read Register
+APIC_LDR equ 0x0D0 ; Logical Destination Register
+APIC_DFR equ 0x0E0 ; Destination Format Register
+APIC_SPURIOUS equ 0x0F0 ; Spurious Interrupt Vector Register
+APIC_ISR equ 0x100 ; In-Service Register (Starting Address)
+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_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
+APIC_LVT_TSR equ 0x330 ; LVT Thermal Sensor Register
+APIC_LVT_PERF equ 0x340 ; LVT Performance Monitoring Counters Register
+APIC_LVT_LINT0 equ 0x350 ; LVT LINT0 Register
+APIC_LVT_LINT1 equ 0x360 ; LVT LINT1 Register
+APIC_LVT_ERR equ 0x370 ; LVT Error Register
+APIC_TMRINITCNT equ 0x380 ; Initial Count Register (for Timer)
+APIC_TMRCURRCNT equ 0x390 ; Current Count Register (for Timer)
+; 0x3A0 - 0x3D0 are Reserved
+APIC_TMRDIV equ 0x3E0 ; Divide Configuration Register (for Timer)
+; 0x3F0 is Reserved
; =============================================================================
diff --git a/src/init/pic.asm b/src/init/pic.asm
index 77ee67a..0fde33e 100644
--- a/src/init/pic.asm
+++ b/src/init/pic.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; INIT PIC
; =============================================================================
diff --git a/src/init/smp.asm b/src/init/smp.asm
index cb93e34..842a26a 100644
--- a/src/init/smp.asm
+++ b/src/init/smp.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; INIT SMP
; =============================================================================
@@ -14,7 +14,7 @@ init_smp:
; Start the AP's one by one
xor eax, eax
xor edx, edx
- mov rsi, [os_LocalAPICAddress]
+ 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
@@ -22,7 +22,7 @@ init_smp:
mov esi, 0x00005100
xor eax, eax
xor ecx, ecx
- mov cx, [cpu_detected]
+ mov cx, [p_cpu_detected]
smp_send_INIT:
cmp cx, 0
je smp_send_INIT_done
@@ -32,7 +32,7 @@ smp_send_INIT:
je smp_send_INIT_skipcore
; Send 'INIT' IPI to APIC ID in AL
- mov rdi, [os_LocalAPICAddress]
+ mov rdi, [p_LocalAPICAddress]
shl eax, 24
mov dword [rdi+0x310], eax ; Interrupt Command Register (ICR); bits 63-32
mov eax, 0x00004500
@@ -48,16 +48,16 @@ smp_send_INIT_skipcore:
smp_send_INIT_done:
- mov rax, [os_Counter_RTC]
+ mov rax, [p_Counter_RTC]
add rax, 10
smp_wait1:
- mov rbx, [os_Counter_RTC]
+ mov rbx, [p_Counter_RTC]
cmp rax, rbx
jg smp_wait1
mov esi, 0x00005100
xor ecx, ecx
- mov cx, [cpu_detected]
+ mov cx, [p_cpu_detected]
smp_send_SIPI:
cmp cx, 0
je smp_send_SIPI_done
@@ -67,7 +67,7 @@ smp_send_SIPI:
je smp_send_SIPI_skipcore
; Send 'Startup' IPI to destination using vector 0x08 to specify entry-point is at the memory-address 0x00008000
- mov rdi, [os_LocalAPICAddress]
+ mov rdi, [p_LocalAPICAddress]
shl eax, 24
mov dword [rdi+0x310], eax ; Interrupt Command Register (ICR); bits 63-32
mov eax, 0x00004608 ; Vector 0x08
@@ -84,34 +84,32 @@ smp_send_SIPI_skipcore:
smp_send_SIPI_done:
; Let things settle (Give the AP's some time to finish)
- mov rax, [os_Counter_RTC]
+ mov rax, [p_Counter_RTC]
add rax, 20
smp_wait2:
- mov rbx, [os_Counter_RTC]
+ mov rbx, [p_Counter_RTC]
cmp rax, rbx
jg smp_wait2
; Finish up
noMP:
- lock inc word [cpu_activated] ; BSP adds one here
-
xor eax, eax
- mov rsi, [os_LocalAPICAddress]
+ 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 [os_BSP], eax ; Store the BSP APIC ID
+ mov [p_BSP], eax ; Store the BSP APIC ID
; Calculate speed of CPU (At this point the RTC is firing at 1024Hz)
cpuid
xor edx, edx
xor eax, eax
- mov rcx, [os_Counter_RTC]
+ mov rcx, [p_Counter_RTC]
add rcx, 10
rdtsc
push rax
speedtest:
- mov rbx, [os_Counter_RTC]
+ mov rbx, [p_Counter_RTC]
cmp rbx, rcx
jl speedtest
rdtsc
@@ -120,7 +118,7 @@ speedtest:
xor edx, edx
mov rcx, 10240
div rcx
- mov [cpu_speed], ax
+ mov [p_cpu_speed], ax
cli ; Disable Interrupts
diff --git a/src/init/smp_ap.asm b/src/init/smp_ap.asm
index 9591644..0e8f60a 100644
--- a/src/init/smp_ap.asm
+++ b/src/init/smp_ap.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; INIT SMP AP
; =============================================================================
@@ -123,7 +123,7 @@ clearcs64_ap:
xor eax, eax
; Reset the stack. Each CPU gets a 1024-byte unique stack location
- mov rsi, [os_LocalAPICAddress] ; We would call os_smp_get_id here but the stack is not ...
+ 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
@@ -135,25 +135,15 @@ clearcs64_ap:
lidt [IDTR64] ; load IDT register
; Enable Local APIC on AP
- mov rsi, [os_LocalAPICAddress]
- add rsi, 0x00f0 ; Offset to Spurious Interrupt Register
- mov rdi, rsi
- lodsd
- or eax, 0000000100000000b
- stosd
+; mov rsi, [p_LocalAPICAddress]
+; add rsi, 0x00f0 ; Offset to Spurious Interrupt Register
+; mov rdi, rsi
+; lodsd
+; or eax, 0000000100000000b
+; stosd
call init_cpu ; Setup CPU
- lock inc word [cpu_activated]
- xor eax, eax
- mov rsi, [os_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 rdi, 0x00005700 ; The location where the cpu values are stored
- add rdi, rax ; RDI points to infomap CPU area + APIC ID. ex F701 would be APIC ID 1
- mov al, 1
- stosb
sti ; Activate interrupts for SMP
jmp ap_sleep
diff --git a/src/interrupt.asm b/src/interrupt.asm
index 43d7a6a..6ad9de4 100644
--- a/src/interrupt.asm
+++ b/src/interrupt.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; Interrupts
; =============================================================================
@@ -67,7 +67,7 @@ rtc:
push rdi
push rax
- add qword [os_Counter_RTC], 1 ; 64-bit counter started at boot up
+ add qword [p_Counter_RTC], 1 ; 64-bit counter started at boot up
mov al, 0x0C ; Select RTC register C
out 0x70, al ; Port 0x70 is the RTC index, and 0x71 is the RTC data
diff --git a/src/pure64.asm b/src/pure64.asm
index e239737..b0f9ec7 100644
--- a/src/pure64.asm
+++ b/src/pure64.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; The first stage loader is required to gather information about the system
; while the BIOS or UEFI is still available and load the Pure64 binary to
@@ -57,10 +57,10 @@ start32:
mov fs, ax
mov gs, ax
- mov edi, 0x5000 ; Clear the info map and system variable
+ mov edi, 0x5000 ; Clear the info map and system variable memory
xor eax, eax
- mov ecx, 768
- rep stosd
+ mov ecx, 960 ; 3840 bytes (Range is 0x5000 - 0x5EFF)
+ rep stosd ; Don't overwrite the VBE data at 0x5F00
xor eax, eax ; Clear all registers
xor ebx, ebx
@@ -263,7 +263,7 @@ clearcs64:
; Save the Boot Mode (it will be 'U' if started via UEFI)
mov al, [0x8005]
- mov [BootMode], al ; Save the byte as a Boot Mode flag
+ mov [p_BootMode], al ; Save the byte as a Boot Mode flag
; Patch Pure64 AP code ; The AP's will be told to start execution at 0x8000
mov edi, start ; We need to remove the BSP Jump call to get the AP's
@@ -271,7 +271,7 @@ clearcs64:
stosd
stosd ; Write 8 bytes in total to overwrite the 'far jump' and marker
- mov al, [BootMode]
+ mov al, [p_BootMode]
cmp al, 'U'
je uefi_memmap
; Process the E820 memory map to find all possible 2MiB pages that are free to use
@@ -313,7 +313,7 @@ processfree:
end820:
shl ebx, 1
- mov dword [mem_amount], ebx
+ mov dword [p_mem_amount], ebx
shr ebx, 1
jmp memmap_end
@@ -323,7 +323,7 @@ uefi_memmap: ; TODO fix this as it is a terrible hack
mov rcx, 32
rep stosb
mov ebx, 64
- mov dword [mem_amount], ebx
+ mov dword [p_mem_amount], ebx
memmap_end:
; Create the high memory map
@@ -444,7 +444,7 @@ make_interrupt_gates: ; make gates for the other interrupts
lidt [IDTR64] ; load IDT register
-; Clear memory 0xf000 - 0xf7ff for the infomap (2048 bytes)
+; Clear memory 0xf000 - 0xf7ff for the InfoMap (2048 bytes)
xor eax, eax
mov ecx, 256
mov edi, 0x0000F000
@@ -454,6 +454,21 @@ clearmapnext:
cmp ecx, 0
jne clearmapnext
+; Read APIC Address from MSR
+ mov ecx, 0x0000001B ; APIC_BASE
+ rdmsr ; Returns APIC in EDX:EAX
+ and eax, 0xFFFFF000 ; Clear lower 12 bits
+ shl rdx, 32 ; Shift lower 32 bits to upper 32 bits
+ add rax, rdx
+ mov [p_LocalAPICAddress], rax
+
+; Check for x2APIC support
+ mov eax, 1
+ cpuid ; x2APIC is supported if bit 21 is set
+ shr ecx, 21
+ and cl, 1
+ mov byte [p_x2APIC], cl
+
call init_acpi ; Find and process the ACPI tables
call init_cpu ; Configure the BSP CPU
@@ -463,7 +478,7 @@ clearmapnext:
call init_smp ; Init of SMP
; Reset the stack to the proper location (was set to 0x8000 previously)
- mov rsi, [os_LocalAPICAddress] ; We would call os_smp_get_id here but the stack is not ...
+ 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
@@ -471,46 +486,39 @@ clearmapnext:
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
+; Build the InfoMap
xor edi, edi
mov di, 0x5000
- mov rax, [os_ACPITableAddress]
+ mov rax, [p_ACPITableAddress]
stosq
- mov eax, [os_BSP]
+ mov eax, [p_BSP]
stosd
mov di, 0x5010
- mov ax, [cpu_speed]
+ mov ax, [p_cpu_speed]
stosw
- mov ax, [cpu_activated]
+ mov ax, [p_cpu_activated]
stosw
- mov ax, [cpu_detected]
+ mov ax, [p_cpu_detected]
stosw
mov di, 0x5020
- mov ax, [mem_amount]
+ mov ax, [p_mem_amount]
stosd
mov di, 0x5030
- mov al, [os_IOAPICCount]
+ mov al, [p_IOAPICCount]
+ stosb
+ mov al, [p_IOAPICIntSourceC]
stosb
mov di, 0x5040
- mov rax, [os_HPETAddress]
+ mov rax, [p_HPETAddress]
stosq
mov di, 0x5060
- mov rax, [os_LocalAPICAddress]
- stosq
- xor ecx, ecx
- mov cl, [os_IOAPICCount]
- mov rsi, os_IOAPICAddress
-nextIOAPIC:
- lodsq
+ mov rax, [p_LocalAPICAddress]
stosq
- sub cl, 1
- cmp cl, 0
- jne nextIOAPIC
mov di, 0x5080
mov eax, [VBEModeInfoBlock.PhysBasePtr] ; Base address of video memory (if graphics mode is set)
diff --git a/src/sysvar.asm b/src/sysvar.asm
index 346c0f2..e581954 100644
--- a/src/sysvar.asm
+++ b/src/sysvar.asm
@@ -1,6 +1,6 @@
; =============================================================================
; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
-; Copyright (C) 2008-2023 Return Infinity -- see LICENSE.TXT
+; Copyright (C) 2008-2024 Return Infinity -- see LICENSE.TXT
;
; System Variables
; =============================================================================
@@ -14,31 +14,32 @@ cfg_smpinit: db 1 ; By default SMP is enabled. Set to 0 to disable.
; Memory locations
E820Map: equ 0x0000000000004000
InfoMap: equ 0x0000000000005000
-SystemVariables: equ 0x0000000000005A00
-VBEModeInfoBlock: equ 0x0000000000005C00 ; 256 bytes
+IM_IOAPICAddress: equ 0x0000000000005600 ; 16 bytes per entry
+IM_IOAPICIntSource: equ 0x0000000000005700 ; 8 bytes per entry
+SystemVariables: equ 0x0000000000005800
+VBEModeInfoBlock: equ 0x0000000000005F00 ; 256 bytes
; DQ - Starting at offset 0, increments by 0x8
-os_ACPITableAddress: equ SystemVariables + 0x00
-os_LocalX2APICAddress: equ SystemVariables + 0x10
-os_Counter_Timer: equ SystemVariables + 0x18
-os_Counter_RTC: equ SystemVariables + 0x20
-os_LocalAPICAddress: equ SystemVariables + 0x28
-os_IOAPICAddress: equ SystemVariables + 0x30
-os_HPETAddress: equ SystemVariables + 0x38
-
-; DD - Starting at offset 128, increments by 4
-os_BSP: equ SystemVariables + 128
-mem_amount: equ SystemVariables + 132 ; in MiB
-
-; DW - Starting at offset 256, increments by 2
-cpu_speed: equ SystemVariables + 256
-cpu_activated: equ SystemVariables + 258
-cpu_detected: equ SystemVariables + 260
-
-; DB - Starting at offset 384, increments by 1
-os_IOAPICCount: equ SystemVariables + 384
-BootMode: equ SystemVariables + 385 ; 'U' for UEFI, otherwise BIOS
-
+p_ACPITableAddress: equ SystemVariables + 0x00
+p_LocalAPICAddress: equ SystemVariables + 0x10
+p_Counter_Timer: equ SystemVariables + 0x18
+p_Counter_RTC: equ SystemVariables + 0x20
+p_HPETAddress: equ SystemVariables + 0x28
+
+; DD - Starting at offset 0x80, increments by 4
+p_BSP: equ SystemVariables + 0x80
+p_mem_amount: equ SystemVariables + 0x84 ; in MiB
+
+; DW - Starting at offset 0x100, increments by 2
+p_cpu_speed: equ SystemVariables + 0x100
+p_cpu_activated: equ SystemVariables + 0x102
+p_cpu_detected: equ SystemVariables + 0x104
+
+; DB - Starting at offset 0x180, increments by 1
+p_IOAPICCount: equ SystemVariables + 0x180
+p_BootMode: equ SystemVariables + 0x181 ; 'U' for UEFI, otherwise BIOS
+p_IOAPICIntSourceC: equ SystemVariables + 0x182
+p_x2APIC: equ SystemVariables + 0x183
align 16
GDTR32: ; Global Descriptors Table Register