From 1f71b9576db536af84155363e14fc49e92de2eef Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Sun, 29 Aug 2021 02:52:48 -0500 Subject: backup 8.29.21 --- src/kernel/acpi.c | 4 +- src/kernel/int.c | 22 ++---- src/kernel/kernel.c | 33 ++++---- src/kernel/klog.c | 180 +++++++++++++++++++++++++++++++----------- src/kernel/madt.c | 2 +- src/kernel/page.c | 2 +- src/kernel/panic.c | 12 ++- src/kernel/printf.c | 17 ++-- src/kernel/smp.c | 37 +++++---- src/kernel/smp_trampoline.asm | 76 +++++++++++------- src/kernel/timer.c | 6 +- 11 files changed, 256 insertions(+), 135 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/acpi.c b/src/kernel/acpi.c index e5a6e4d..0696e58 100644 --- a/src/kernel/acpi.c +++ b/src/kernel/acpi.c @@ -1,13 +1,13 @@ #include #include #include -#include #include -#include +#include #include #include #include #include +#include //finding rsdp diff --git a/src/kernel/int.c b/src/kernel/int.c index 34f1c78..5901a90 100644 --- a/src/kernel/int.c +++ b/src/kernel/int.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,7 +44,6 @@ .present = 1 \ }) -#define GDT_ADDR (uint64_t)PHYS_TO_VIRT(0x7e22) #define IOAPICR_VER 1 @@ -74,18 +73,10 @@ struct idt_reg { uint64_t offset; } __attribute__((packed)); -struct gdt_reg { - uint16_t size; - uint64_t offset; -} __attribute__((packed)); - struct idt_descriptor *idt; static struct idt_reg idtr; -struct gdt_reg gdtr = { - .size = 0x17, - .offset = GDT_ADDR -}; + lapic_t lapic; //would make this static but it's needed by timer.c @@ -211,7 +202,7 @@ void init_exceptions() { //void new_idt -void init_interrupts() { +void init_interrupts_bsp() { init_madt(); debug_madt(); lapic = get_lapic(); @@ -232,9 +223,7 @@ void init_interrupts() { bzero(&isr_bitmap, sizeof(isr_bitmap)); isr_bitmap[0] = (((uint64_t)1 << 32) - 1); - //set idt and new gdt - asm("lgdt [%0]\n" - "lidt [%1]\n":: "m"(gdtr), "m"(idtr)); + asm("lidt [%0]\n"::"m"(idtr)); //Spurrious Interrupt (permanent, required for APIC) @@ -251,3 +240,6 @@ void init_interrupts() { init_timer(); asm("sti\n"); } + +void smp_init_interrupts() { +} diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index d550e37..11df1f1 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,12 +1,12 @@ #include #include -#include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -19,31 +19,36 @@ //testing headers #include +void kmain() { + PANIC(KERNEL_PANIC_KERNEL_RETURNED); +} -void multicore_main() { - printf("\nKernal started\n"); - asm("cli\nhlt"); +void smp_kinit() { + printf("\nKernal started on core\n"); //TODO get lapic working, then print core number + kmain(); } -void main() { -#ifndef SCREEN_OUTPUT - if(init_serial(COM1)) printf("\nKernal started on CPU 1!\n"); -#endif +//TODO move to global constructors +void kernel_init() { + size_t pmap_size; + get_mem_capabilities(); - init_pmap(map_complete_physical()); + pmap_size = map_complete_physical(); + init_klog(); + init_pmap(pmap_size); + printf("\nKernal started on CPU 1!\n"); find_root_sdp(); debug_acpi(); - init_interrupts(); + init_interrupts_bsp(); randinit(); smp_boot(); fix_stack(); - unmap_lowmem(); - - PANIC(KERNEL_PANIC_KERNEL_RETURNED); + //unmap_lowmem(); + kmain(); } diff --git a/src/kernel/klog.c b/src/kernel/klog.c index 52444b1..c62c4d3 100644 --- a/src/kernel/klog.c +++ b/src/kernel/klog.c @@ -1,57 +1,104 @@ #include -#include #include #include -#include +#include #include #include +#include -//README -//this file has some temporary workarounds until I get further into development -//this isn't going to be the serial driver I end up keeping +//right now, this program is simply for debuging. +//Later in development, we will hook it up to a TTY, impliment FCS, etc #define VIDEO_BUFFER PHYS_TO_VIRT(0xb8000) #define MAX_LOOPBACK_ATTEMPTS 20 -//later we'll set it up for interrupting instead of polling -bool init_serial(uint16_t port) { - outb_wait(port + 1, 0x00); - outb_wait(port + 2, 0x00); - outb_wait(port + 3, 0x80); - outb_wait(port + 0, 0x01); //here - outb_wait(port + 1, 0x00); - outb_wait(port + 3, 0x03); - outb_wait(port + 2, 0xc7); - outb_wait(port + 4, 0x0b); - outb_wait(port + 4, 0x1e); - - - //we shouldn't accept this as a loopback success. - //I'm making an exception because my dell desktop has a faulty serial port - //that requires some extra effort. - - uint8_t loopback_byte; - for(int attempts = 0; attempts < MAX_LOOPBACK_ATTEMPTS; attempts++) { - outb_wait(port + 0, 0xae); // test char - loopback_byte = inb(port); - if(loopback_byte == 0xae) break; - } +#define KLOG_COM1 0 +#define KLOG_COM2 1 +#define KLOG_COM3 2 +#define KLOG_COM4 3 +#define KLOG_SCREEN 4 + +static int debug_output = KLOG_SCREEN; + +#define SERIAL_THR 0 //transmitter holding buffer +#define SERIAL_RBR 1 //receiving holding buffer +#define SERIAL_DLL 0 //divisor latch low byte +#define SERIAL_DLH 1 //divisor latch high byte +#define SERIAL_FCR 2 +#define SERIAL_IIR 2 +#define SERIAL_LCR 3 +#define SERIAL_MCR 4 +#define SERIAL_LSR 5 +#define SERIAL_MSR 6 +#define SERIAL_SR 7 + +#define COM1 0x3f8 +#define COM2 0x2f8 +#define COM3 0x3e8 +#define COM4 0x2e8 + +uint16_t serial_ports[4] = {COM1, COM2, COM3, COM4}; + +/** +enum com_ports { + COM1 = 0x3f8, + COM2 = 0x2f8, + COM3 = 0x3e8, + COM4 = 0x2e8 +}; +**/ + + +static bool detect_serial(uint16_t port) { + outb(port + SERIAL_FCR, 0xe7); + outb(port + SERIAL_SR, 0xba); + if((inb(port + SERIAL_IIR) & (1 << 6)) && (inb(port + SERIAL_SR) == 0xba)) { + outb_wait(port + 1, 0x00); + outb_wait(port + 2, 0x00); + outb_wait(port + 3, 0x80); + outb_wait(port + 0, 0x01); + outb_wait(port + 1, 0x00); + outb_wait(port + 3, 0x03); + outb_wait(port + 2, 0xc7); + outb_wait(port + 4, 0x0b); + outb_wait(port + 4, 0x1e); - if(loopback_byte != 0xae) { - //I'm sorry if these next few lines give you a stroke. They gave me one. + + uint8_t loopback_byte; + for(int attempts = 0; attempts < MAX_LOOPBACK_ATTEMPTS; attempts++) { + outb_wait(port + 0, 0xae); + loopback_byte = inb(port); + if(loopback_byte == 0xae) break; + } + + if(loopback_byte != 0xae) { + //you better delete this once you get tty drivers working... + int a = 0 / 0; + } - //My old Dell test desktop has disfunctional serial hardware that only works after a reboot. - //Seeing we don't have ACPI set up yet, we can't reboot without crashing. - //IM GOING TO REMOVE THIS ONCE I DEVELOP THE "REAL" SERIAL DRIVER!!!! - asm("mov rax, 0\n" - "div rax\n"); - return false; + outb_wait(port + 4, 0x0f); + return true; } - - outb_wait(port + 4, 0x0f); - return true; + return false; } + +//this function is going to be teleted after ttys work. +//but, for now, if a serial port is detected, it'll set debug_output to 0-3 (com port #). +//debug_output == 4 is for screen output. +void init_klog() { + for(unsigned int p = 0; p < (sizeof(serial_ports) / sizeof(uint16_t)); p++) { + if(detect_serial(serial_ports[p])) { + debug_output = p; + return; + } + } + debug_output = KLOG_SCREEN; + _putchar('\n'); +} + + + void _putchar_serial(uint16_t port, char msg) { while(!(inb(port + 5) & 0x20)); //wait for transmit to be done outb_wait(port, msg); @@ -80,13 +127,10 @@ void next_line() { } void move_cursor(unsigned int x, unsigned int y) { - //yeah yeah yeah, it doens't test for overflows... I'm gonna delete this once i get serial working - //on my second desktop on_char = x; on_line = y; } -//until we get serial working on hp void _putchar_screen(char msg) { if(on_char >= 80) { next_line(); @@ -94,7 +138,55 @@ void _putchar_screen(char msg) { next_line(); return; } - char *screen_buffer = (void *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2))); - *screen_buffer = msg; + *(char *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2))) = msg; on_char++; } + + + +void _putchar(char character) { + if(debug_output < (sizeof(serial_ports) / sizeof(uint16_t))) { + _putchar_serial(serial_ports[debug_output], character); + } + else { + _putchar_screen(character); + } +} + + + + +/** + * Set the value "0xE7" to the FCR to test the status of the FIFO flags. +Read the value of the IIR to test for what flags actually got set. +If Bit 6 is set Then + If Bit 7 is set Then + If Bit 5 is set Then + UART is 16750 (64 bit fifo) + Else + UART is 16550A (idk why this matters, 16 bit fifo) + End If + Else + UART is 16550 (16 bit fifo) + End If +Else you know the chip doesn't use FIFO, so we need to check the scratch register + Set some arbitrary value like 0x2A to the Scratch Register. + If the arbitrary value comes back identical + UART is 16450 (idk why this matters, 1 byte at a time) + Else + UART is 8250 (one byte at a time) + End If +End If + +#define UART_16750 0 +#define UART_16550A 1 +#define UART_16550 2 +#define UART_16450 3 +#define UART_8250 4 + +#define KLOG_COM1 0 +#define KLOG_COM2 1 +#define KLOG_COM3 2 +#define KLOG_COM4 3 +#define KLOG_SCREEN 4 * 5 // 5 leaves enough space for com ports +**/ diff --git a/src/kernel/madt.c b/src/kernel/madt.c index 62e0535..adeb547 100644 --- a/src/kernel/madt.c +++ b/src/kernel/madt.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/kernel/page.c b/src/kernel/page.c index 734194c..3f6c4a8 100644 --- a/src/kernel/page.c +++ b/src/kernel/page.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/kernel/panic.c b/src/kernel/panic.c index 82a761f..d17c185 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -1,12 +1,15 @@ #include #include #include -#include -#include +#include +#include #include +#include + +static uint8_t panic_lock = 0; void panic(int reason, void *eframe_p, struct registers *regs) { // will fill with debugging info latter - + lock(&panic_lock); #ifdef EASTEREGG_BLOATWARE printf("\nKernel PANIC!!!!!!!\n"); @@ -49,6 +52,9 @@ void panic(int reason, void *eframe_p, struct registers *regs) { // will fill wi break; case KERNEL_PANIC_HPET_REQUIRED: printf("\nHPET is required. \nIf you get this error, let know;\nif enough people share this issue, I'll impliment PIT usage.\n"); + case KERNEL_PANIC_SMP_FAILED: + printf("\nNot all cores booted successfully (see text before panic).\n"); + break; default: printf("\nUnknown panic code %i\n.", reason); break; diff --git a/src/kernel/printf.c b/src/kernel/printf.c index 8267755..b496bce 100644 --- a/src/kernel/printf.c +++ b/src/kernel/printf.c @@ -33,10 +33,11 @@ #include #include + #include "printf.h" //this is my own ugly library -#include +#include //and my options /** @@ -161,12 +162,7 @@ static inline void _out_char(char character, void* buffer, size_t idx, size_t ma { (void)buffer; (void)idx; (void)maxlen; if (character) { -#ifdef SCREEN_OUTPUT - _putchar_screen(character); -#else - _putchar_serial(COM1, character); // later we should figure out a way to not specifify exclusively com1 -#endif - + _putchar(character); } } @@ -874,17 +870,24 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const /////////////////////////////////////////////////////////////////////////////// +#include +static uint8_t printf_lock = 0; int printf_(const char* format, ...) { + //BRETT modification + lock(&printf_lock); va_list va; va_start(va, format); char buffer[1]; const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); va_end(va); + unlock(&printf_lock); return ret; } +/////////////////////////////////////////////////////////////////////////////// + int sprintf_(char* buffer, const char* format, ...) { diff --git a/src/kernel/smp.c b/src/kernel/smp.c index 5796ab9..9714c91 100644 --- a/src/kernel/smp.c +++ b/src/kernel/smp.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -7,6 +7,7 @@ #include #include #include +#include #define LAPIC_ICR_LOW 192 #define LAPIC_ICR_HIGH 196 @@ -16,6 +17,7 @@ extern char __load_start_smp_bootloader, __load_stop_smp_bootloader; extern uint8_t *smp_bootstrap_corecount; extern uint8_t smp_bootstrap_bsp; extern uint64_t *smp_bootstrap_stackarray; +extern char final_gdt_descriptor; struct icr_reg { uint8_t vector; @@ -30,22 +32,30 @@ struct icr_reg { unsigned int reserved_2:12; }__attribute__((packed)); -//1: get bsp number 2 -//2: get list of lapics 3 -//3: copy code 1 -//4: - static inline void write_icr(uint8_t dest, uint32_t message) { lapic[LAPIC_ICR_HIGH] = (uint32_t)dest << 24; lapic[LAPIC_ICR_LOW] = message; } +struct gdt_descriptor { + uint16_t size; + void *offset; +} __attribute__((packed)); + +static struct gdt_descriptor gdtr; + void smp_boot() { - uint8_t cores_active = 1; //TODO change in asm + uint8_t cores_active = 1; struct cores_info cores; struct icr_reg icr; get_coreinfo(&cores); + if(cores.corecount == 1) { + asm("sgdt [%0]"::"m"(gdtr)); + gdtr.offset = PHYS_TO_VIRT(gdtr.offset); + asm("lgdt [%0]"::"m"(gdtr)); + return; + } bzero(&icr, sizeof(icr)); void **core_stacks = malloc(sizeof(void *) * (cores.corecount - 1)); @@ -57,9 +67,7 @@ void smp_boot() { &__load_stop_smp_bootloader - &__load_start_smp_bootloader); smp_bootstrap_corecount = &cores_active; smp_bootstrap_bsp = cores.bsp; - smp_bootstrap_stackarray = (uint64_t)core_stacks; - - + smp_bootstrap_stackarray = (void *)core_stacks; icr.deliv_mode = 0b101; icr.dest_shorthand = 0b11; @@ -74,10 +82,9 @@ void smp_boot() { if(cores_active != cores.corecount) write_icr(0, *(uint32_t *)&icr); usleep(200); if(cores_active != cores.corecount) { - printf("NOT ALL CORES ONLINE\n"); - asm("cli\nhlt"); - } - else { - printf("%i!!!!!!\n", cores_active); + printf("Only %i cores online (expected %i)\n", cores_active, cores.corecount); //maybe add a panic + PANIC(KERNEL_PANIC_SMP_FAILED); } + printf("%i \n", cores_active); + //asm("lgdt [%0]\n"::"r"(PHYS_TO_VIRT(&final_gdt_descriptor))); TODO NOW } diff --git a/src/kernel/smp_trampoline.asm b/src/kernel/smp_trampoline.asm index 15b85e2..78303a3 100644 --- a/src/kernel/smp_trampoline.asm +++ b/src/kernel/smp_trampoline.asm @@ -1,13 +1,19 @@ global smp_bootstrap_stackarray global smp_bootstrap_bsp global smp_bootstrap_corecount +global final_gdt_descriptor -extern multicore_main +extern smp_kinit +extern _pmem_vaddr [bits 16] smp_trampoline: cli +in al, 0x92 +or al, 2 +out 0x92, al + xor ax, ax mov ds, ax lgdt [.gdt_descriptor_p] @@ -15,12 +21,11 @@ mov eax, cr0 or eax, 0x1 mov cr0, eax ; now in long mode -jmp 0x8:.smp_protected +jmp 0x8:smp_protected ;________________________________________________________________________________________ -;TODO find how to use old gdt .gdt_start_p: ; we need to start with a null gdt dd 0 dd 0 @@ -52,9 +57,9 @@ SMP_PROTECTED_DATA_SEGMENT equ .gdt_data_p - .gdt_start_p ;________________________________________________________________________________________ -.smp_protected: +smp_protected: -[bits 32] +bits 32 mov ax, SMP_PROTECTED_DATA_SEGMENT mov ds, ax mov ss, ax @@ -62,10 +67,8 @@ mov es, ax mov fs, ax mov gs, ax -lgdt [.gdt_descriptor_l] - -mov eax, 0x10000 ;TODO clarify _why_ this is a thing +mov eax, 0x10000 mov cr3, eax ;setting up misc features @@ -78,13 +81,15 @@ mov cr4, eax ;set NX and LME mov eax, 0x80000001 cpuid -and edx, 1 << 20 -shr edx, 9 +mov ebx, edx +and ebx, 1 << 20 +shr ebx, 9 mov ecx, 0xc0000080 rdmsr -or eax, 1 << 8 | 1 << 11 -or eax, edx +or eax, 1 << 8 +fuckyou: +or eax, ebx wrmsr @@ -94,14 +99,16 @@ or eax, 1 << 31 | 1 << 0; and ax, ~(1 << 2) mov cr0, eax +lgdt [final_gdt_descriptor] + -jmp SMP_LONG_CODE_SEGMENT:.counter +jmp SMP_LONG_CODE_SEGMENT:smp_longsetup ;________________________________________________________________________________________ -[bits 64] -;TODO do we really need all this? -.gdt_start_l: +bits 64 +final_gdt: +.start: ;and now we set up a temporary GDT creating a 1:1 mapping dw 0xffff dw 0 @@ -111,7 +118,7 @@ db 1 db 0 ;now for the code GDT: -.gdt_code_l: +.code: dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!) dw 0 ; base address 15:00 db 0 ; base address 23:16 @@ -119,7 +126,7 @@ db 10011010b db 00100000b db 0 -.gdt_data_l: +.data: dw 0 dw 0 db 0 @@ -127,17 +134,18 @@ db 10010010b db 00100000b db 0 -.gdt_end_l: ; later calculates offset in defs below +.end: ; later calculates offset in defs below -.gdt_descriptor_l: - dw .gdt_end_l - .gdt_start_l - 1 -dq .gdt_start_l +final_gdt_descriptor: + dw final_gdt.end - final_gdt.start - 1 +.offset: +dq final_gdt.start -SMP_LONG_CODE_SEGMENT equ .gdt_code_l - .gdt_start_l -SMP_LONG_DATA_SEGMENT equ .gdt_data_l - .gdt_start_l +SMP_LONG_CODE_SEGMENT equ final_gdt.code - final_gdt.start +SMP_LONG_DATA_SEGMENT equ final_gdt.data - final_gdt.start -.counter: +smp_longsetup: mov eax, 1 cpuid shr ebx, 24 @@ -146,19 +154,29 @@ jl .apic_below_bsp sub bl, 1 .apic_below_bsp: - mov rax, QWORD [smp_bootstrap_stackarray] -debug: mov rsp, QWORD [rax + rbx * 8] +mov rax, 0xffff800000000000 +;or QWORD [final_gdt_descriptor.offset], rax +;lgdt [final_gdt_descriptor] + +.inc_corecounter: + + mov rax, [smp_bootstrap_corecount] -inc BYTE [rax] +lock inc BYTE [rax] + -mov rax, multicore_main + +smp_enter_kernel: +mov rax, smp_kinit jmp rax align 8 smp_bootstrap_stackarray: dq 0 +smp_lock: dq 0 smp_bootstrap_bsp: db 0 smp_bootstrap_corecount: db 0 + times 512 - ($ - $$) db 0 diff --git a/src/kernel/timer.c b/src/kernel/timer.c index aed42ba..295abe2 100644 --- a/src/kernel/timer.c +++ b/src/kernel/timer.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -204,10 +204,8 @@ void init_timer() { uint32_t unused, cpuid_reg; __get_cpuid(0x80000007, &unused, &unused, &unused, &cpuid_reg); - //goto debug_tsc; if((cpuid_reg >> 8) & 1) { printf("Detected invariant TSC\n"); - //.1 second to calibrate, TODO do we need to check if the register is big enough? uint64_t hpet_ticks = (100000000000000 * (1 / (double)hpet_info.hpet_period)) + 0.5; printf("Starting TSC calibration...\n"); uint64_t volatile start_tsc, end_tsc; @@ -274,7 +272,7 @@ void init_timer() { apic_div = (((apic_div & 0b100) << 1) | (apic_div * 0b1011)); } - lapic_timer_lvt.vector = SPURRIOUS_VECTOR; //TODO CHANGE ME + lapic_timer_lvt.vector = SPURRIOUS_VECTOR; lapic_timer_lvt.timer_mode = LAPIC_TIMER_MODE_PERIODIC; lapic_timer_lvt.delivery_status = 0; lapic_timer_lvt.mask = 1; -- cgit v1.2.3