Skip to content
This repository has been archived by the owner on May 31, 2021. It is now read-only.

Commit

Permalink
Fix APIC and tsc so my ThinkPad actually boots.
Browse files Browse the repository at this point in the history
Also turn the fbterm back on since I'm moving to a real device
that doesn't have a usable serial port.
  • Loading branch information
klange committed May 25, 2021
1 parent 8e37ae1 commit c7cdd21
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 13 deletions.
12 changes: 9 additions & 3 deletions base/usr/include/kernel/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
39 changes: 32 additions & 7 deletions kernel/arch/x86_64/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <kernel/string.h>
#include <kernel/process.h>
#include <kernel/printf.h>
#include <kernel/misc.h>
#include <kernel/arch/x86_64/acpi.h>
#include <kernel/arch/x86_64/mmu.h>

Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand All @@ -150,6 +159,7 @@ void acpi_initialize(void) {
check += *tmp;
}
if (check != 0) {
printf("Bad checksum on RSDP\n");
return; /* bad checksum */
}

Expand All @@ -166,20 +176,33 @@ 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 */
}
}
}
}

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) {
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions kernel/arch/x86_64/cmos.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions kernel/arch/x86_64/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions kernel/misc/fbterm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit c7cdd21

Please sign in to comment.