diff --git a/kernel/main.v b/kernel/main.v index 643ba5034..fabf85ff7 100644 --- a/kernel/main.v +++ b/kernel/main.v @@ -103,6 +103,8 @@ pub fn kmain() { idt.initialise() isr.initialise() + x2apic_mode = smp_req.response.flags & 1 != 0 + // Init terminal term.initialise() serial.early_initialise() diff --git a/kernel/modules/acpi/madt.v b/kernel/modules/acpi/madt.v index 2a9516ad3..9bea3687e 100644 --- a/kernel/modules/acpi/madt.v +++ b/kernel/modules/acpi/madt.v @@ -29,6 +29,16 @@ pub: flags u32 } +@[packed] +struct MADTLocalX2Apic { +pub: + header MADTHeader + reserved [2]u8 + x2apic_id u32 + flags u32 + processor_id u32 +} + @[packed] struct MADTIoApic { pub: @@ -61,6 +71,7 @@ pub: __global ( madt &MADT madt_local_apics []&MADTLocalApic + madt_local_x2apics []&MADTLocalX2Apic madt_io_apics []&MADTIoApic madt_isos []&MADTISO madt_nmis []&MADTNMI @@ -83,6 +94,12 @@ fn madt_init() { println('acpi/madt: Found local APIC #${madt_local_apics.len}') madt_local_apics << unsafe { &MADTLocalApic(header) } } + 9 { + if x2apic_mode { + println('acpi/madt: Found local x2APIC #${madt_local_x2apics.len}') + madt_local_x2apics << unsafe { &MADTLocalX2Apic(header) } + } + } 1 { println('acpi/madt: Found IO APIC #${madt_io_apics.len}') madt_io_apics << unsafe { &MADTIoApic(header) } diff --git a/kernel/modules/x86/apic/apic.v b/kernel/modules/x86/apic/apic.v index 50a5daa12..8e0bc9798 100644 --- a/kernel/modules/x86/apic/apic.v +++ b/kernel/modules/x86/apic/apic.v @@ -22,22 +22,47 @@ const ( __global ( lapic_base = u64(0) + x2apic_mode = bool(false) ) -fn lapic_read(reg u32) u32 { +fn xapic_read(reg u32) u32 { if lapic_base == u64(0) { lapic_base = u64(msr.rdmsr(0x1b) & 0xfffff000) + higher_half } return kio.mmin(&u32(lapic_base + reg)) } -fn lapic_write(reg u32, val u32) { +fn x2apic_read(reg u32) u64 { + return msr.rdmsr(0x800 + (reg >> 4)) +} + +fn xapic_write(reg u32, val u32) { if lapic_base == u64(0) { lapic_base = u64(msr.rdmsr(0x1b) & 0xfffff000) + higher_half } kio.mmout(&u32(lapic_base + reg), val) } +fn x2apic_write(reg u32, val u64) { + msr.wrmsr(0x800 + (reg >> 4), val) +} + +fn lapic_read(reg u32) u64 { + if x2apic_mode { + return x2apic_read(reg) + } else { + return xapic_read(reg) + } +} + +fn lapic_write(reg u32, val u64) { + if x2apic_mode { + x2apic_write(reg, val) + } else { + xapic_write(reg, u32(val)) + } +} + pub fn lapic_timer_stop() { lapic_write(apic.lapic_reg_timer_initcnt, 0) lapic_write(apic.lapic_reg_timer, (1 << 16)) @@ -86,9 +111,13 @@ pub fn lapic_eoi() { lapic_write(apic.lapic_reg_eoi, 0) } -pub fn lapic_send_ipi(lapic_id u8, vector u8) { - lapic_write(apic.lapic_reg_icr1, u32(lapic_id) << 24) - lapic_write(apic.lapic_reg_icr0, vector) +pub fn lapic_send_ipi(lapic_id u32, vector u8) { + if x2apic_mode { + x2apic_write(apic.lapic_reg_icr0, (u64(lapic_id) << 32) | vector) + } else { + xapic_write(apic.lapic_reg_icr1, u32(lapic_id) << 24) + xapic_write(apic.lapic_reg_icr0, vector) + } } fn io_apic_read(io_apic int, reg u32) u32 { diff --git a/kernel/modules/x86/smp/smp.v b/kernel/modules/x86/smp/smp.v index 92898dbcf..5e7f7377a 100644 --- a/kernel/modules/x86/smp/smp.v +++ b/kernel/modules/x86/smp/smp.v @@ -19,6 +19,7 @@ __global ( @[_linker_section: '.requests'] __global ( volatile smp_req = limine.LimineSMPRequest{ + flags: 1 // x2apic allowed response: unsafe { nil } } ) @@ -28,6 +29,7 @@ pub fn initialise() { println('smp: BSP LAPIC ID: ${smp_tag.bsp_lapic_id:x}') println('smp: Total CPU count: ${smp_tag.cpu_count}') + println('smp: Using x2APIC: ${x2apic_mode}') smp_info_array := smp_tag.cpus