aboutsummaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2023-12-19 22:08:43 -0500
committerIan Moffett <ian@osmora.org>2023-12-19 22:08:43 -0500
commite07242e3a1589742772732c4e739f78bdab20a00 (patch)
treebe63a8cc66ce3388dc73ba1c441e816ae18ec5d3 /sys/arch
parent4a6226af28a98501c05d961d8878c5e1091d0dee (diff)
kernel/amd64: lapic: Fixup LAPIC state tracking
This commit removes the lapic_set_base() function and certain globals from the Local APIC driver so it won't cause problems on hardware with many CPU sockets or that is just wacky. Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/lapic.c55
-rw-r--r--sys/arch/amd64/amd64/machdep.c13
2 files changed, 36 insertions, 32 deletions
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
index 2f5cd9f..0ac2670 100644
--- a/sys/arch/amd64/amd64/lapic.c
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -55,9 +55,7 @@ __KERNEL_META("$Hyra$: lapic.c, Ian Marco Moffett, "
} \
} while (0);
-static void *lapic_base = NULL;
static struct timer lapic_timer = { 0 };
-static bool has_x2apic = false;
/*
* Returns true if LAPIC is supported.
@@ -83,9 +81,10 @@ static inline uint32_t
lapic_readl(uint32_t reg)
{
void *addr;
+ const struct cpu_info *ci = this_cpu();
- if (!has_x2apic) {
- addr = (void *)((uintptr_t)lapic_base + reg);
+ if (!ci->has_x2apic) {
+ addr = (void *)((uintptr_t)ci->lapic_base + reg);
return mmio_read32(addr);
} else {
reg >>= 4;
@@ -103,9 +102,10 @@ static inline void
lapic_writel(uint32_t reg, uint32_t val)
{
void *addr;
+ const struct cpu_info *ci = this_cpu();
- if (!has_x2apic) {
- addr = (void *)((uintptr_t)lapic_base + reg);
+ if (!ci->has_x2apic) {
+ addr = (void *)((uintptr_t)ci->lapic_base + reg);
mmio_write32(addr, val);
} else {
reg >>= 4;
@@ -172,9 +172,9 @@ lapic_reg_clear(uint32_t reg, uint32_t value)
* current processor.
*/
static inline uint32_t
-lapic_get_id(void)
+lapic_get_id(const struct cpu_info *ci)
{
- if (!has_x2apic) {
+ if (!ci->has_x2apic) {
return (lapic_readl(LAPIC_ID) >> 24) & 0xF;
} else {
return lapic_readl(LAPIC_ID);
@@ -186,7 +186,7 @@ lapic_get_id(void)
* mode. Returns true if so.
*/
static inline bool
-lapic_has_x2apic(void)
+has_x2apic(void)
{
uint32_t ecx, tmp;
@@ -202,9 +202,9 @@ lapic_has_x2apic(void)
* is readonly.
*/
static inline void
-lapic_set_ldr(void)
+lapic_set_ldr(struct cpu_info *ci)
{
- if (!has_x2apic)
+ if (!ci->has_x2apic)
lapic_writel(LAPIC_LDR, LAPIC_STARTUP_LID);
}
@@ -229,24 +229,12 @@ lapic_timer_init(size_t *freq_out)
}
void
-lapic_set_base(void *mmio_base)
-{
- if (lapic_base == NULL)
- lapic_base = mmio_base;
-}
-
-void
lapic_init(void)
{
struct cpu_info *ci;
uint64_t tmp;
size_t tmr_freq;
- /* Sanity check */
- if (lapic_base == NULL) {
- panic("LAPIC base not set!\n");
- }
-
if (!lapic_check_support()) {
/*
* Hyra currently depends on the existance
@@ -255,18 +243,27 @@ lapic_init(void)
panic("This machine does not support LAPIC!\n");
}
- has_x2apic = lapic_has_x2apic();
+ /* Get the current processor, and lock its structure */
+ ci = this_cpu();
+ CPU_INFO_LOCK(ci);
+
+ ci->has_x2apic = has_x2apic();
+
+ /* Sanity check */
+ if (ci->lapic_base == NULL) {
+ panic("LAPIC base not set!\n");
+ }
/* Hardware enable the Local APIC */
tmp = rdmsr(IA32_APIC_BASE_MSR);
- tmp |= has_x2apic << x2APIC_ENABLE_SHIFT;
+ tmp |= ci->has_x2apic << x2APIC_ENABLE_SHIFT;
wrmsr(IA32_APIC_BASE_MSR, tmp | LAPIC_HW_ENABLE);
/* Software enable the Local APIC via SVR */
lapic_reg_set(LAPIC_SVR, LAPIC_SW_ENABLE);
BSP_KINFO("Enabled Local APIC for BSP\n");
- lapic_set_ldr();
+ lapic_set_ldr(ci);
/* Setup the timer descriptor */
lapic_timer.name = "LAPIC_INTEGRATED_TIMER";
@@ -276,16 +273,12 @@ lapic_init(void)
/* Register the timer for scheduler usage */
register_timer(TIMER_SCHED, &lapic_timer);
- /* Get the current processor, and lock its structure */
- ci = this_cpu();
- CPU_INFO_LOCK(ci);
-
/* Calibrate timer */
lapic_timer_init(&tmr_freq);
ci->lapic_tmr_freq = tmr_freq;
/* Set the Local APIC ID */
- ci->id = lapic_get_id();
+ ci->id = lapic_get_id(ci);
BSP_KINFO("BSP Local APIC ID: %d\n", ci->id);
CPU_INFO_UNLOCK(ci);
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 66778a6..0c31985 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -37,6 +37,7 @@
#include <machine/tss.h>
#include <machine/spectre.h>
#include <machine/cpu.h>
+#include <firmware/acpi/acpi.h>
__MODULE_NAME("machdep");
__KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, "
@@ -44,6 +45,7 @@ __KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, "
#define ISR(func) ((uintptr_t)func)
#define INIT_FLAG_IOAPIC 0x00000001U
+#define INIT_FLAG_ACPI 0x00000002U
static inline void
init_tss(struct cpu_info *cur_cpu)
@@ -93,13 +95,22 @@ processor_init(void)
CPU_INFO_LOCK(cur_cpu);
init_tss(cur_cpu);
- CPU_INFO_UNLOCK(cur_cpu);
+ if (!__TEST(init_flags, INIT_FLAG_ACPI)) {
+ /*
+ * Parse the MADT... This is needed to fetch required information
+ * to set up the Local APIC(s) and I/O APIC(s)...
+ */
+ init_flags |= INIT_FLAG_ACPI;
+ acpi_parse_madt(cur_cpu);
+ }
if (!__TEST(init_flags, INIT_FLAG_IOAPIC)) {
init_flags |= INIT_FLAG_IOAPIC;
ioapic_init();
}
+ CPU_INFO_UNLOCK(cur_cpu);
+
lapic_init(); /* Per core */
/* Use spectre mitigation if enabled */