From c7cdd21dc7c539330d0e450ae3be08b2e4b5501f Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Tue, 25 May 2021 19:28:38 +0900 Subject: [PATCH] Fix APIC and tsc so my ThinkPad actually boots. Also turn the fbterm back on since I'm moving to a real device that doesn't have a usable serial port. --- base/usr/include/kernel/process.h | 12 +++++++--- kernel/arch/x86_64/acpi.c | 39 +++++++++++++++++++++++++------ kernel/arch/x86_64/cmos.c | 1 + kernel/arch/x86_64/main.c | 9 ++++--- kernel/misc/fbterm.c | 1 + 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/base/usr/include/kernel/process.h b/base/usr/include/kernel/process.h index 290b9a3..92861fd 100644 --- a/base/usr/include/kernel/process.h +++ b/base/usr/include/kernel/process.h @@ -146,10 +146,16 @@ struct ProcessorLocal { * there is nothing else to do. */ process_t * kernel_idle_task; - union PML * current_pml; - volatile int sync_depth; - int cpu_id; + /** + * @brief Process this core was last scheduled to run. + */ volatile process_t * previous_process; + + int cpu_id; + union PML * current_pml; +#ifdef __x86_64__ + int lapic_id; +#endif }; extern struct ProcessorLocal processor_local_data[32]; diff --git a/kernel/arch/x86_64/acpi.c b/kernel/arch/x86_64/acpi.c index 705f770..7418c6e 100644 --- a/kernel/arch/x86_64/acpi.c +++ b/kernel/arch/x86_64/acpi.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -89,18 +90,23 @@ static void short_delay(unsigned long amount) { while (read_tsc() < clock + amount * arch_cpu_mhz()); } +static volatile int _ap_current = 0; + /* C entrypoint for APs */ void ap_main(void) { + arch_set_core_base((uintptr_t)&processor_local_data[_ap_current]); + uint32_t ebx; asm volatile ("cpuid" : "=b"(ebx) : "a"(0x1) : "ecx", "edx", "memory"); - arch_set_core_base((uintptr_t)&processor_local_data[ebx >> 24]); + if (this_core->lapic_id != (int)(ebx >> 24)) { + printf("alert: lapic id does not match\n"); + } /* Load the IDT */ idt_ap_install(); fpu_initialize(); pat_initialize(); - this_core->cpu_id = ebx >> 24; /* Set our pml pointers */ this_core->current_pml = &init_page_region[0]; @@ -141,7 +147,10 @@ void acpi_initialize(void) { } } - if (!good) return; + if (!good) { + printf("No RSD PTR found\n"); + return; + } struct rsdp_descriptor * rsdp = (struct rsdp_descriptor *)scan; uint8_t check = 0; @@ -150,6 +159,7 @@ void acpi_initialize(void) { check += *tmp; } if (check != 0) { + printf("Bad checksum on RSDP\n"); return; /* bad checksum */ } @@ -166,7 +176,16 @@ void acpi_initialize(void) { for (uint8_t * entry = madt->entries; entry < table + madt->header.length; entry += entry[1]) { switch (entry[0]) { case 0: - if (entry[4] & 0x01) cores++; + if (entry[4] & 0x01) { + printf("cpu%d = %d\n", cores, entry[3]); + processor_local_data[cores].cpu_id = cores; + processor_local_data[cores].lapic_id = entry[3]; + cores++; + if (cores == 33) { + printf("too many cores\n"); + arch_fatal(); + } + } break; /* TODO: Other entries */ } @@ -174,12 +193,16 @@ void acpi_initialize(void) { } } - if (!lapic_base || cores <= 1) return; + if (!lapic_base || cores <= 1) { + printf("Not setting up SMP\n"); + return; + } /* Allocate a virtual address with which we can poke the lapic */ lapic_final = (uintptr_t)mmu_map_mmio_region(lapic_base, 0x1000); /* Map the bootstrap code */ + printf("Installing trampoline...\n"); memcpy(mmu_map_from_physical(0x1000), &_ap_bootstrap_start, (uintptr_t)&_ap_bootstrap_end - (uintptr_t)&_ap_bootstrap_start); for (int i = 1; i < cores; ++i) { @@ -191,12 +214,14 @@ void acpi_initialize(void) { /* Make an initial stack for this AP */ _ap_stack_base = (uintptr_t)valloc(KERNEL_STACK_SIZE)+ KERNEL_STACK_SIZE; + _ap_current = i; + /* Send INIT */ - lapic_send_ipi(i, 0x4500); + lapic_send_ipi(processor_local_data[i].lapic_id, 0x4500); short_delay(5000UL); /* Send SIPI */ - lapic_send_ipi(i, 0x4601); + lapic_send_ipi(processor_local_data[i].lapic_id, 0x4601); /* Wait for AP to signal it is ready before starting next AP */ do { asm volatile ("pause" : : : "memory"); } while (!_ap_startup_flag); diff --git a/kernel/arch/x86_64/cmos.c b/kernel/arch/x86_64/cmos.c index 2639ba3..7a2fb0c 100644 --- a/kernel/arch/x86_64/cmos.c +++ b/kernel/arch/x86_64/cmos.c @@ -182,6 +182,7 @@ void arch_clock_initialize(void) { uintptr_t end = ((end_hi & 0xFFFFffff) << 32) | (end_lo & 0xFFFFffff); uintptr_t start = ((uintptr_t)(start_hi & 0xFFFFffff) << 32) | (start_lo & 0xFFFFffff); tsc_mhz = (end - start) / 10000; + if (tsc_mhz == 0) tsc_mhz = 1000; /* uh oh */ } #define SUBTICKS_PER_TICK 1000000 diff --git a/kernel/arch/x86_64/main.c b/kernel/arch/x86_64/main.c index 652b679..fbfbed5 100644 --- a/kernel/arch/x86_64/main.c +++ b/kernel/arch/x86_64/main.c @@ -40,6 +40,7 @@ extern void portio_initialize(void); extern void keyboard_install(void); extern void mouse_install(void); extern void serial_initialize(void); +extern void fbterm_initialize(void); #define EARLY_LOG_DEVICE 0x3F8 static size_t _early_log_write(size_t size, uint8_t * buffer) { @@ -277,14 +278,16 @@ int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp) { tsc_mhz = atoi(args_value("tsc_mhz")); } + /* Scheduler is running and we have parsed the kcmdline, initialize video. */ + framebuffer_initialize(); + fbterm_initialize(); + /* Allow SMP to disabled with an arg */ if (!args_present("nosmp")) { + printf("Setting up APs...\n"); acpi_initialize(); } - /* Scheduler is running and we have parsed the kcmdline, initialize video. */ - framebuffer_initialize(); - /* Decompress and mount all initial ramdisks. */ mount_multiboot_ramdisks(mboot); diff --git a/kernel/misc/fbterm.c b/kernel/misc/fbterm.c index fc69af3..beea7db 100644 --- a/kernel/misc/fbterm.c +++ b/kernel/misc/fbterm.c @@ -234,4 +234,5 @@ void fbterm_initialize(void) { fbterm_width = (lfb_resolution_x - LEFT_PAD) / char_width; fbterm_height = (lfb_resolution_y) / char_height; + printf_output = fbterm_write; }