From 275671262edacceccd4ec33df80d9ac9d04a36ec Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Mon, 6 Nov 2023 14:55:33 +0100 Subject: [PATCH 1/4] percpu: cleanup percpu page upon allocation Signed-off-by: Pawel Wieczorkiewicz --- common/percpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/percpu.c b/common/percpu.c index f933746b..c77d0935 100644 --- a/common/percpu.c +++ b/common/percpu.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -51,6 +52,7 @@ percpu_t *get_percpu_page(unsigned int cpu) { */ percpu = get_free_page(GFP_IDENT | GFP_KERNEL | GFP_USER); BUG_ON(!percpu); + memset(percpu, 0, PAGE_SIZE); percpu->cpu_id = cpu; From 260aa2e6b4fce8a507b5d38dbb5a64c4340eb4ea Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Mon, 6 Nov 2023 18:50:56 +0100 Subject: [PATCH 2/4] console: replace printk with warnings when due Signed-off-by: Pawel Wieczorkiewicz --- arch/x86/pagetables.c | 8 ++++---- arch/x86/traps.c | 2 +- common/cmdline.c | 6 +++--- common/kernel.c | 2 +- common/pci.c | 4 ++-- common/sched.c | 2 +- common/setup.c | 9 +++++---- common/usermode.c | 2 +- drivers/hpet.c | 2 +- drivers/keyboard.c | 4 ++-- smp/mptables.c | 4 ++-- tests/test.c | 2 +- 12 files changed, 24 insertions(+), 23 deletions(-) diff --git a/arch/x86/pagetables.c b/arch/x86/pagetables.c index f388c1a4..7f25f886 100644 --- a/arch/x86/pagetables.c +++ b/arch/x86/pagetables.c @@ -216,10 +216,10 @@ static inline void pgentry_fixup_flags(pgentry_t *entry, unsigned long flags) { if (unlikely(*entry != entry_new)) { char flags_str_old[16]; char flags_str_new[16]; - printk("WARNING: Already-present PTE protection flags conflicts with our.\n" - " Updating present flags: %s -> %s\n", - dump_pte_flags(flags_str_old, 16, (pte_t) *entry), - dump_pte_flags(flags_str_new, 16, (pte_t) entry_new)); + warning("Already-present PTE protection flags conflict with our.\n" + " Updating present flags: %s -> %s", + dump_pte_flags(flags_str_old, 16, (pte_t) *entry), + dump_pte_flags(flags_str_new, 16, (pte_t) entry_new)); *entry = entry_new; barrier(); flush_tlb(); diff --git a/arch/x86/traps.c b/arch/x86/traps.c index 30b3e6d1..7750d6f7 100644 --- a/arch/x86/traps.c +++ b/arch/x86/traps.c @@ -325,7 +325,7 @@ void do_exception(cpu_regs_t *regs) { /* Handle user tasks' exceptions */ if (enter_from_usermode(regs->exc.cs)) { - printk("Task exception: %s\n", panic_str); + warning("Task exception: %s", panic_str); terminate_user_task(); } diff --git a/common/cmdline.c b/common/cmdline.c index f4e02d8c..e510056e 100644 --- a/common/cmdline.c +++ b/common/cmdline.c @@ -117,9 +117,9 @@ void __text_init cmdline_parse(const char *cmdline) { strncpy(param->var, optval, param->varlen); if (strlen(optval) >= param->varlen) { ((char *) param->var)[param->varlen - 1] = '\0'; - printk("WARNING: The commandline parameter value for %s does not fit " - "into the preallocated buffer (size %lu >= %u)\n", - param->name, strlen(optval), param->varlen); + warning("The commandline parameter value for %s does not fit " + "into the preallocated buffer (size %lu >= %u)", + param->name, strlen(optval), param->varlen); } break; case ULONG: diff --git a/common/kernel.c b/common/kernel.c index 873a1aa5..557c5541 100644 --- a/common/kernel.c +++ b/common/kernel.c @@ -37,7 +37,7 @@ #endif void reboot(void) { - printk("Rebooting...\n"); + warning("Rebooting..."); io_delay(); #ifdef KTF_ACPICA diff --git a/common/pci.c b/common/pci.c index 4241262b..62319736 100644 --- a/common/pci.c +++ b/common/pci.c @@ -119,14 +119,14 @@ static void probe_pci(void) { const uint32_t vendor_reg = pci_cfg_read(bus, dev, func, PCI_REG_VENDOR); if (!PCI_DEV_EXISTS(vendor_reg)) { - printk("pci: non-existent host bridge @ 00.0.0\n"); + warning("pci: non-existent host bridge @ 00.0.0"); return; } class_reg = pci_cfg_read(bus, dev, func, PCI_REG_CLASS); if (PCI_CLASS(class_reg) != PCI_CLASS_BRIDGE && PCI_SUBCLASS(class_reg) != PCI_SUBCLASS_HOST_BRIDGE) { - printk("pci: expected host bridge class code @ 00.0.0\n"); + warning("pci: expected host bridge class code @ 00.0.0"); return; } diff --git a/common/sched.c b/common/sched.c index 66060bf2..485ba0c3 100644 --- a/common/sched.c +++ b/common/sched.c @@ -175,7 +175,7 @@ int schedule_task(task_t *task, cpu_t *cpu) { ASSERT(task); if (!cpu) { - printk("Unable to schedule task: %s. CPU does not exist.", task->name); + warning("Unable to schedule task: %s. CPU does not exist.", task->name); return -EEXIST; } diff --git a/common/setup.c b/common/setup.c index 5b06aa30..1cd2d060 100644 --- a/common/setup.c +++ b/common/setup.c @@ -178,9 +178,10 @@ void __text_init init_timers(cpu_t *cpu) { if (opt_apic_timer) { if (hpet_initialized || opt_pit) /* Needed for APIC timer calibration */ init_apic_timer(); - else - printk("CPU%u: Unable to initialize APIC timer - no calibration timers!\n", - cpu->id); + else { + warning("CPU%u: Unable to initialize APIC timer - no calibration timers!", + cpu->id); + } } } @@ -288,7 +289,7 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, unsigned long int ret = pfm_initialize(); if (ret != PFM_SUCCESS) - printk("Warning: PFM library initialization failed: %d\n", ret); + warning("PFM library initialization failed: %d", ret); #endif /* Jump from .text.init section to .text */ diff --git a/common/usermode.c b/common/usermode.c index af16f035..cadab6a5 100644 --- a/common/usermode.c +++ b/common/usermode.c @@ -71,7 +71,7 @@ long syscall_handler(long syscall_nr, long arg1, long arg2, long arg3, long arg4 } default: - printk("Unknown syscall: %lu\n", syscall_nr); + warning("Unknown syscall: %lu", syscall_nr); return -1; } } diff --git a/drivers/hpet.c b/drivers/hpet.c index 5e311c83..6333d15a 100644 --- a/drivers/hpet.c +++ b/drivers/hpet.c @@ -48,7 +48,7 @@ bool init_hpet(const cpu_t *cpu) { #endif if (!hpet) { - printk("HPET not initialized\n"); + warning("HPET not initialized"); return false; } diff --git a/drivers/keyboard.c b/drivers/keyboard.c index 8e6ddea0..f1bd9b46 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -123,7 +123,7 @@ void init_keyboard(const cpu_t *cpu) { /* Controller self test */ outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_SELF_TEST); if (inb(KEYBOARD_PORT_DATA) != KEYBOARD_RES_SELF_TEST) { - printk("Self test did not succeed\n"); + warning("Self test did not succeed"); return; } @@ -148,7 +148,7 @@ void init_keyboard(const cpu_t *cpu) { dprintk("Port1 available? %d - port2 available? %d\n", port1, port2); if (!port1 && !port2) { - printk("No available PS/2 working ports\n"); + warning("No available PS/2 working ports"); return; } diff --git a/smp/mptables.c b/smp/mptables.c index 65ac1bcd..70eafb0e 100644 --- a/smp/mptables.c +++ b/smp/mptables.c @@ -301,7 +301,7 @@ int init_mptables(void) { mpc_hdr_t *mpc_ptr; if (!mpf_ptr) { - printk("No MP Floating Structure Pointer found!\n"); + warning("No MP Floating Structure Pointer found!"); return -ENODEV; } @@ -309,7 +309,7 @@ int init_mptables(void) { dump_mpf(mpf_ptr); if (mpf_ptr->mpc_type > 0 || mpf_ptr->mpc_base == 0x0) { - printk("No MP Configuration Table present!\n"); + warning("No MP Configuration Table present!"); return -ENOENT; } diff --git a/tests/test.c b/tests/test.c index 90ac8d9f..c25e107e 100644 --- a/tests/test.c +++ b/tests/test.c @@ -51,7 +51,7 @@ static get_next_test_result_t get_next_test(test_fn **out_test_fn, char **out_na if (*out_name) { *out_test_fn = symbol_address(*out_name); if (!*out_test_fn) { - printk("Symbol for test %s not found\n", *out_name); + warning("Symbol for test %s not found", *out_name); return TESTS_ERROR; } return TESTS_FOUND; From cdf083eb7f58df17553dcd765b475fdb032bf19f Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Tue, 7 Nov 2023 11:48:10 +0100 Subject: [PATCH 3/4] cpu: refactor cpu_t structure Add cpu_flags_t structure to handle all CPU specific flags. Signed-off-by: Pawel Wieczorkiewicz --- common/acpi.c | 12 ++++++------ common/cpu.c | 6 +++--- common/sched.c | 4 ++-- common/setup.c | 2 +- include/cpu.h | 25 +++++++++++++++++-------- smp/mptables.c | 2 +- smp/smp.c | 2 +- 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/common/acpi.c b/common/acpi.c index 6f487655..f036fcd1 100644 --- a/common/acpi.c +++ b/common/acpi.c @@ -268,7 +268,7 @@ static int process_madt_entries(void) { cpu_t *cpu = get_cpu(madt_cpu->apic_proc_id) ?: add_cpu(madt_cpu->apic_proc_id, false, enabled); - cpu->enabled = enabled; + cpu->flags.enabled = enabled; percpu_t *percpu = cpu->percpu; percpu->cpu_id = madt_cpu->apic_proc_id; @@ -498,7 +498,7 @@ static void madt_parser(ACPI_SUBTABLE_HEADER *entry, void *arg) { cpu_t *cpu = get_cpu(lapic->ProcessorId) ?: add_cpu(lapic->ProcessorId, false, enabled); - cpu->enabled = enabled; + cpu->flags.enabled = enabled; percpu_t *percpu = cpu->percpu; percpu->apic_id = lapic->Id; @@ -602,7 +602,7 @@ static void madt_parser(ACPI_SUBTABLE_HEADER *entry, void *arg) { cpu_t *cpu = get_cpu(slapic->ProcessorId) ?: add_cpu(slapic->ProcessorId, false, enabled); - cpu->enabled = enabled; + cpu->flags.enabled = enabled; percpu_t *percpu = cpu->percpu; percpu->sapic_id = slapic->Id; @@ -610,7 +610,7 @@ static void madt_parser(ACPI_SUBTABLE_HEADER *entry, void *arg) { percpu->sapic_uid = slapic->Uid; percpu->sapic_uid_str[0] = slapic->UidString[0]; - if (cpu->enabled) { + if (is_cpu_enabled(cpu)) { printk("ACPI: [MADT] SAPIC Processor ID: %u, SAPIC ID: %u, SAPIC EID: %u, " "SAPIC UID: %u, SAPIC UID Str: %c Flags: %08x\n", cpu->id, slapic->Id, slapic->Eid, slapic->Uid, slapic->UidString[0], @@ -627,12 +627,12 @@ static void madt_parser(ACPI_SUBTABLE_HEADER *entry, void *arg) { bool enabled = !!(x2lapic->LapicFlags & 0x1); cpu_t *cpu = get_cpu(x2lapic->Uid) ?: add_cpu(x2lapic->Uid, false, enabled); - cpu->enabled = enabled; + cpu->flags.enabled = enabled; percpu_t *percpu = cpu->percpu; percpu->apic_id = x2lapic->LocalApicId; - if (cpu->enabled) { + if (is_cpu_enabled(cpu)) { printk("ACPI: [MADT] X2APIC Processor ID: %u, APIC ID: %u, Flags: %08x\n", cpu->id, percpu->apic_id, x2lapic->LapicFlags); } diff --git a/common/cpu.c b/common/cpu.c index 7f01cca4..1bd0dc85 100644 --- a/common/cpu.c +++ b/common/cpu.c @@ -40,8 +40,8 @@ static cpu_t bsp = {0}; static void init_cpu(cpu_t *cpu, unsigned int id, bool is_bsp, bool enabled) { memset(cpu, 0, sizeof(*cpu)); cpu->id = id; - cpu->bsp = is_bsp; - cpu->enabled = enabled; + cpu->flags.bsp = is_bsp; + cpu->flags.enabled = enabled; init_cpu_runstate(cpu); if (is_bsp) @@ -131,7 +131,7 @@ void wait_for_all_cpus(void) { cpu_t *cpu; list_for_each_entry (cpu, &cpus, list) { - if (cpu->bsp) + if (is_cpu_bsp(cpu)) continue; while (!is_cpu_finished(cpu) || !list_is_empty(&cpu->task_queue)) diff --git a/common/sched.c b/common/sched.c index 485ba0c3..34e9e94d 100644 --- a/common/sched.c +++ b/common/sched.c @@ -252,7 +252,7 @@ void process_task_repeat(task_t *task) { void run_tasks(cpu_t *cpu) { task_t *task, *safe; - if (!cpu->bsp) + if (!is_cpu_bsp(cpu)) wait_cpu_unblocked(cpu); set_cpu_unfinished(cpu); @@ -272,7 +272,7 @@ void run_tasks(cpu_t *cpu) { } } while (!list_is_empty(&cpu->task_queue)); - if (!cpu->bsp) + if (!is_cpu_bsp(cpu)) set_cpu_blocked(cpu); set_cpu_finished(cpu); } diff --git a/common/setup.c b/common/setup.c index 1cd2d060..0976a787 100644 --- a/common/setup.c +++ b/common/setup.c @@ -167,7 +167,7 @@ static void __text_init init_vga_console(void) { void __text_init init_timers(cpu_t *cpu) { static bool __data_init hpet_initialized = false; - if (cpu->bsp) { + if (is_cpu_bsp(cpu)) { if (opt_hpet) hpet_initialized = init_hpet(cpu); diff --git a/include/cpu.h b/include/cpu.h index ed979bfb..31b39d2f 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -35,19 +35,20 @@ #define CPU_UNBLOCKED (1 << 0) #define CPU_FINISHED (1 << 1) +struct cpu_flags { + uint64_t bsp : 1, enabled : 1, rsvd : 62; +}; +typedef struct cpu_flags cpu_flags_t; + struct cpu { list_head_t list; - - unsigned int id; - unsigned int bsp : 1, enabled : 1; - - atomic_t run_state; - percpu_t *percpu; - spinlock_t lock; - list_head_t task_queue; + atomic_t run_state; + + unsigned int id; + cpu_flags_t flags; }; typedef struct cpu cpu_t; @@ -66,6 +67,14 @@ extern void wait_for_all_cpus(void); /* Static declarations */ +static inline bool is_cpu_bsp(cpu_t *cpu) { + return cpu->flags.bsp; +} + +static inline bool is_cpu_enabled(cpu_t *cpu) { + return cpu->flags.enabled; +} + static inline void init_cpu_runstate(cpu_t *cpu) { atomic_set(&cpu->run_state, 0); } diff --git a/smp/mptables.c b/smp/mptables.c index 70eafb0e..5b9f3316 100644 --- a/smp/mptables.c +++ b/smp/mptables.c @@ -223,7 +223,7 @@ static void process_mpc_entries(mpc_hdr_t *mpc_ptr) { cpu = get_cpu(mpc_cpu->lapic_id) ?: add_cpu(mpc_cpu->lapic_id, false, enabled); - cpu->enabled = enabled; + cpu->flags.enabled = enabled; percpu_t *percpu = cpu->percpu; percpu->apic_id = mpc_cpu->lapic_id; diff --git a/smp/smp.c b/smp/smp.c index fc0ef959..4aa5147d 100644 --- a/smp/smp.c +++ b/smp/smp.c @@ -75,7 +75,7 @@ static __text_init void boot_cpu(cpu_t *cpu) { percpu_t *percpu = cpu->percpu; apic_icr_t icr; - if (cpu->bsp) + if (is_cpu_bsp(cpu)) return; ap_new_sp = get_free_pages_top(PAGE_ORDER_2M, GFP_KERNEL_MAP); From 2dc846e291f6230081ad940d4cc4dccbc363cdeb Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Tue, 7 Nov 2023 11:49:17 +0100 Subject: [PATCH 4/4] smp: perform full AP initialization before releasing All initialization routines and settings must be through, before letting BSP continue. Signed-off-by: Pawel Wieczorkiewicz --- smp/smp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/smp/smp.c b/smp/smp.c index 4aa5147d..bff4b570 100644 --- a/smp/smp.c +++ b/smp/smp.c @@ -56,15 +56,16 @@ void __noreturn ap_startup(void) { init_traps(cpu); init_apic(ap_cpuid, apic_get_mode()); - ap_callin = true; - smp_wmb(); - init_timers(cpu); sti(); if (opt_fpu) enable_fpu(); + /* Release BSP after full AP initialization */ + ap_callin = true; + smp_wmb(); + while (true) run_tasks(cpu); @@ -103,6 +104,7 @@ static __text_init void boot_cpu(cpu_t *cpu) { apic_wait_ready(); + /* Wait for AP initialization */ while (!ap_callin) cpu_relax();