summaryrefslogtreecommitdiff
path: root/sys
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
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')
-rw-r--r--sys/arch/amd64/amd64/lapic.c55
-rw-r--r--sys/arch/amd64/amd64/machdep.c13
-rw-r--r--sys/firmware/acpi/acpi_init.c1
-rw-r--r--sys/firmware/acpi/acpi_madt.c9
-rw-r--r--sys/include/arch/amd64/cpu.h2
-rw-r--r--sys/include/arch/amd64/lapic.h1
-rw-r--r--sys/include/firmware/acpi/acpi.h3
7 files changed, 45 insertions, 39 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 */
diff --git a/sys/firmware/acpi/acpi_init.c b/sys/firmware/acpi/acpi_init.c
index 93a9cf4..4ba1928 100644
--- a/sys/firmware/acpi/acpi_init.c
+++ b/sys/firmware/acpi/acpi_init.c
@@ -107,7 +107,6 @@ acpi_init(void)
panic("Root SDT has an invalid checksum!\n");
}
root_sdt_entries = (root_sdt->hdr.length - sizeof(root_sdt->hdr)) / 4;
- acpi_parse_madt();
#if defined(__x86_64__)
/* Hyra requires HPET on x86_64 */
diff --git a/sys/firmware/acpi/acpi_madt.c b/sys/firmware/acpi/acpi_madt.c
index 119a842..4f5ff10 100644
--- a/sys/firmware/acpi/acpi_madt.c
+++ b/sys/firmware/acpi/acpi_madt.c
@@ -31,6 +31,7 @@
#include <firmware/acpi/tables.h>
#include <machine/ioapic.h>
#include <machine/lapic.h>
+#include <machine/cpu.h>
#include <sys/cdefs.h>
#include <sys/panic.h>
#include <sys/syslog.h>
@@ -46,7 +47,7 @@ __KERNEL_META("$Hyra$: acpi_madt.c, Ian Marco Moffett, "
static struct acpi_madt *madt = NULL;
static void
-do_parse(void)
+do_parse(struct cpu_info *ci)
{
uint8_t *cur = NULL;
uint8_t *end = NULL;
@@ -62,7 +63,7 @@ do_parse(void)
/* Init the Local APIC */
lapic_mmio_base = (void *)(uintptr_t)madt->lapic_addr;
- lapic_set_base(lapic_mmio_base);
+ ci->lapic_base = lapic_mmio_base;
/* Parse the rest of the MADT */
while (cur < end) {
@@ -127,7 +128,7 @@ irq_to_gsi(uint8_t irq)
}
void
-acpi_parse_madt(void)
+acpi_parse_madt(struct cpu_info *ci)
{
/* Prevent this function from running twice */
if (madt != NULL) {
@@ -139,5 +140,5 @@ acpi_parse_madt(void)
panic("Failed to query for ACPI MADT\n");
}
- do_parse();
+ do_parse(ci);
}
diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h
index 9645aac..ff294de 100644
--- a/sys/include/arch/amd64/cpu.h
+++ b/sys/include/arch/amd64/cpu.h
@@ -54,6 +54,8 @@ struct cpu_info {
/* AMD64 */
volatile size_t lapic_tmr_freq;
+ volatile void *lapic_base;
+ volatile bool has_x2apic;
volatile struct tss_entry *tss;
};
diff --git a/sys/include/arch/amd64/lapic.h b/sys/include/arch/amd64/lapic.h
index 11edfe4..1e7caf6 100644
--- a/sys/include/arch/amd64/lapic.h
+++ b/sys/include/arch/amd64/lapic.h
@@ -36,7 +36,6 @@
#define LAPIC_TMR_PERIODIC 0x01
void lapic_timer_init(size_t *freq_out);
-void lapic_set_base(void *mmio_base);
void lapic_init(void);
#endif /* !_AMD64_LAPIC_H_ */
diff --git a/sys/include/firmware/acpi/acpi.h b/sys/include/firmware/acpi/acpi.h
index 3352627..7d092e7 100644
--- a/sys/include/firmware/acpi/acpi.h
+++ b/sys/include/firmware/acpi/acpi.h
@@ -31,6 +31,7 @@
#define _ACPI_ACPI_H_
#include <firmware/acpi/tables.h>
+#include <machine/cpu.h>
#include <sys/types.h>
void acpi_init(void);
@@ -39,6 +40,6 @@ void *acpi_query(const char *query);
bool acpi_is_checksum_valid(struct acpi_header *hdr);
struct acpi_root_sdt *acpi_get_root_sdt(void);
size_t acpi_get_root_sdt_len(void);
-void acpi_parse_madt(void);
+void acpi_parse_madt(struct cpu_info *ci);
#endif /* !_ACPI_ACPI_H_ */