From 2062e7070710989abf7271838efb99cbfbe511d0 Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Sun, 12 Sep 2021 12:53:33 -0500 Subject: SMP fixed for CPUs with defective cores modified: README.md modified: src/.gdb_history modified: src/bootloader/enter_kernel.asm modified: src/bootloader/gdt.asm modified: src/debug/gdbinit.gdb modified: src/include/int.h modified: src/include/paging.h modified: src/include/smp.h modified: src/include/smp_sync.h modified: src/indigo_os modified: src/kernel/int.c modified: src/kernel/kernel.c modified: src/kernel/klog.c modified: src/kernel/madt.c modified: src/kernel/page.c modified: src/kernel/panic.c modified: src/kernel/printf.c modified: src/kernel/smp.c modified: src/kernel/smp_trampoline.asm modified: .gitignore deleted: src/.gdb_history --- README.md | 14 +- src/.gdb_history | 314 ++++++++++++++++++++-------------------- src/bootloader/enter_kernel.asm | 6 +- src/bootloader/gdt.asm | 2 +- src/debug/gdbinit.gdb | 3 - src/include/int.h | 1 + src/include/paging.h | 2 +- src/include/smp.h | 22 +++ src/include/smp_sync.h | 6 + src/indigo_os | Bin 42912 -> 43488 bytes src/kernel/int.c | 4 +- src/kernel/kernel.c | 11 +- src/kernel/klog.c | 4 +- src/kernel/madt.c | 2 +- src/kernel/page.c | 4 +- src/kernel/panic.c | 3 +- src/kernel/printf.c | 3 +- src/kernel/smp.c | 47 ++++-- src/kernel/smp_trampoline.asm | 56 ++++--- 19 files changed, 298 insertions(+), 206 deletions(-) diff --git a/README.md b/README.md index b903991..35144e4 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,25 @@ With all that out of the way, check out the features. # Planned Features * SMP multi-core support * Preemptive multithreading +* VFS abstraction for filesystem modules * Unix-like file structure (/proc, /sys, /dev) * Port of ether X-org or wayland, combined with a complete WM * Basic network stack -* ex2 filesystem +* ex2 filesystem built in * Pseudoterminals * Ports of other software I like, such as bash, vim, some old 3d games # Project status This project will likely go very slow and take multiple years, as I'm dealing with things such as college and adulting. If there are blatently obvious bugs, or things look unfinished, I'm still working on them. Additionally, there's some pretty messy code. I've improved over the durentation of this project, so expect those things to be changed some time down the line. + +# What I'm working on now +1. Ensuring palloc() and malloc() are smp safe (current) +2. Creating kernel space threads with primative scheduler +3. VFS filesystem +4. ACPI, PCI +5. ext2 filesystem +6. Userspace processes!!! +7. IO buffering, process waitlists +8. Improve scheduler +9. Let's not get too ahead of ourselves... diff --git a/src/.gdb_history b/src/.gdb_history index b48fd09..e77f7f1 100644 --- a/src/.gdb_history +++ b/src/.gdb_history @@ -1,227 +1,233 @@ -thread 0 -thread 2 -print cores_active -context -thread 1 -next -c -print cores_active -print &cores_active -thread 2 +info reg rbx +info reg rsp +info reg rbx +info reg rax +x 0xffff8000bffde058 +stepi +info reg rsp +x 0xffff8000bffde058 +stepi info reg rax +stex 0x8111 +x 0x8111 info reg rax -x 0x1000bf +stepi quit -c -print smp_bootstrap_stackarray -print smp_bootstrap_corecount -print smp_bootstrap_bsp quit c -x smp_bootstrap_bsp -next -print smp_bootstrap_bsp -print smp_bootstrap_stackarray -print smp_bootstrap_bsp -print smp_bootstrap_bsp -info reg rax -x smp_bootstrap_corecount -print smp_bootstrap_corecount quit c -c -c -c quit c -c -c -c quit -b panic c -thread -threads -info thread -thread 2 -thread 3 -thread 4 quit +quit +hb bruh c -c -c -c +stepi +info rip +info reg rip quit +hb smp_enter_kernel +c quit -print final_gdt_descriptor -print gdt +hb smp_enter_kernel +c +stepi +info reg rsp quit quit +hb smp_longsetup +c +stepi quit -nexti -thread 1 -thread 23 -thread 2 -print final_gdt_descriptor.offset -qut quit -context -disassemble -x/i 0x80dd quit +hb smp_enter_kernel c +stepi +info reg rsp +quit c c quit -next -print gdt -print gdtr -next -print gdtr -print/x (void *)&gdtr -print/x *(void *)&gdtr -hexdump &gdtr -print/x gdtr -quit c -quit -next +stepi stepi info reg rax -info reg rdx -print final_gdt_descriptor -print &final_gdt_descriptor +stepi quit +c +stepi +info reg rbx +stepi +x $rbx quit +hb smp_enter_kernel c +info reg rsp +stepi +x $rsp +stepi +x $rsp quit +hb smp_enter_kernel c -thread 2 -next +stepi +info reg rsp +stepi +quit quit c -thread -threads -info threads -thread 1 c c -quit c -quit c quit -hb klog.c -hb klog -hb klog_init c quit -hb init_klog +hb fuckin_testeroni c -print sizeof(serial_ports) -print sizeof(serial_ports) / sizeof(uint16_t) +stepi +info reg rax +stepi +info reg bl +stepi quit +hb fuckin_testroni c quit +hb fuckin_testeroni c -quit +stepi +info reg bl +print/c 51 +stepi c -quit -hb smp_trampoline.asm:163 c -print smp_kinit -x smp_kinit -next -info reg rax -x smp_kinit -nexti -x smp_kinit -info reg rax -quit c -quit c +make quit c quit c quit -nexti -stepi -stepi -next -quit -b _putchar +hb smnp_boot c -stepi -next +print smp_bootstrap_stackarray +print &smp_bootstrap_stackarray +print smp_bootstrap_stackarray +quit c +print smp_stackarray +print *smp_stackarray +print smp_stackarray[0] +print smp_stackarray[1] +print smp_stackarray[2] +print smp_stackarray[3] +print smp_stackarray[4] +quit c +print smp_stackarray[0] +print smp_stackarray[1] +print smp_stackarray[2] +print smp_stackarray[3] quit -hb _putchar c +info threads +thread 2w +thread 2 c -next -step -print screen_buffer -x 0xffff8000000b80a0 -0xffff800000000000 -x 0xffff800000000000 quit +hb smp_enter_kernel c quit -b _putchar +hb smp_enter_kernel c c -step -print screen_buffer -stepi -c -d +threads +threads +info threads c +info threads +cpu 3 +info cpu 3 +thread 3 +context +stepi +info reg rsi quit -next -quit -b init_klog +hb smp_longsetup c -next -print serial_ports[0] -print/x serial_ports[0] -next -quit +stepi +info reg rsi +stepi +info reg rsi +print rsi+1 +x rsi +x $rsi +print (uint64_t *)$rsi +print *(uint64_t *)$rsi +x $rsi +x/x $rsi +x/c $rsi +x/p $rsi +x &rsi +x $rsi +x $rsi+8 +x $rsi+1 +print (uint64_t*)0xffff8000bffde059 +print *(uint64_t*)0xffff8000bffde059 +print/x *(uint64_t*)0xffff8000bffde059 +thread 1 +thread 0 +ls quit c +info threads +cpu 1 +thread 1 +stepi quit +hb smp_longsetup c +info thread +stepi +d +thread 0 +thread 3 +thread 4 +stepi +info reg bl +stepi +info reg rsi +stepi +info reg al +stepi +info reg rsi +print (struct core_stack *)0xffff8000bffde058 +print *(struct core_stack *)0xffff8000bffde058 +print *(struct core_stack *)0xffff8000bffde061 +stepi +stepi +uit quit +hb smp_trampoline +c +stepi c -quit c -quit c -quit -b init_klog c -print sizeof(serial_ports) / sizeof(uint16_t) -next -print p -next -make -quit -b init_klog c -next -step -b _putchar c -step -step -print (char *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2))) -print (char *)((uint64_t)0xb8000 + ((on_line * 160) + (on_char * 2))) -quit c +c +cq uit quit -hb test_shit +hb smp_trampoline c c c @@ -233,24 +239,18 @@ c c c c +thread 1 +thread 2 c quit +hb smp_protected c +print smp_stackarray_ptr +print smp_bootstrap_bsp +print &smp_bootstrap_bsp quit -quit -next -quit -quit -quit -info reg edx -nexti -info reg edx -quit -next -info reg ebx -quit -hb fuckyou -quit +hb smp_boot c -info reg ebx +print smp_bootstrap_ +print smp_bootstrap_corecount quit diff --git a/src/bootloader/enter_kernel.asm b/src/bootloader/enter_kernel.asm index bdf0a71..475e288 100644 --- a/src/bootloader/enter_kernel.asm +++ b/src/bootloader/enter_kernel.asm @@ -92,7 +92,9 @@ bits 64 mov rbp, 0 mov rsp, _kernel_stack_loc mov rax, QWORD kernel_init -;push QWORD 0 jmp rax -jmp $ +full_stop: +cli +hlt +jmp full_stop ret diff --git a/src/bootloader/gdt.asm b/src/bootloader/gdt.asm index 0e6d89b..a1d61e2 100644 --- a/src/bootloader/gdt.asm +++ b/src/bootloader/gdt.asm @@ -29,7 +29,7 @@ dq .gdt_start PROTECTED_CODE_SEGMENT equ .gdt_code - .gdt_start PROTECTED_DATA_SEGMENT equ .gdt_data - .gdt_start - +align 8 long_gdt: .gdt_start: ;and now we set up a temporary GDT creating a 1:1 mapping diff --git a/src/debug/gdbinit.gdb b/src/debug/gdbinit.gdb index 1a96557..a658ba4 100644 --- a/src/debug/gdbinit.gdb +++ b/src/debug/gdbinit.gdb @@ -1,9 +1,6 @@ target remote localhost:1234 symbol-file debug/debug_syms.o -hb fuckyou -hb kernel_init - define cs2bs print (1 << (5 + $arg0)) diff --git a/src/include/int.h b/src/include/int.h index 32313bd..6f1857b 100644 --- a/src/include/int.h +++ b/src/include/int.h @@ -79,6 +79,7 @@ void clear_int(); unsigned int alloc_idt(struct idt_entry *entry); void free_idt(unsigned int entry); void modify_idt(struct idt_entry *entry, unsigned int vector); +void smp_load_idt(); #endif diff --git a/src/include/paging.h b/src/include/paging.h index 302e567..5d33ca5 100644 --- a/src/include/paging.h +++ b/src/include/paging.h @@ -9,7 +9,7 @@ void unmap_lowmem(); size_t map_complete_physical(); -void debug_print_memory(); +void debug_pzone(); struct phys_map *init_pmap(size_t pagetable_size); diff --git a/src/include/smp.h b/src/include/smp.h index c4a675a..f4e3aa8 100644 --- a/src/include/smp.h +++ b/src/include/smp.h @@ -1,4 +1,26 @@ #ifndef SMP_INCLUDED #define SMP_INCLUDED +#include void smp_boot(); +extern uint8_t corecount; + +static inline void lock(uint8_t *lock) { + asm("mov al, 1\n" + "spinlock:\n" + "lock xchgb [%0], al\n" + "test al, al\n" + "pause\n" + "jnz spinlock\n" + ::"r"(lock):"al"); +} + +static inline void unlock(uint8_t *lock) { + asm("lock andb [%0], 0"::"r"(lock)); +} + +static inline void waitup(uint8_t *loto) { +} + +#define CREATE_LOTO(name) + #endif diff --git a/src/include/smp_sync.h b/src/include/smp_sync.h index 92784b8..93aac35 100644 --- a/src/include/smp_sync.h +++ b/src/include/smp_sync.h @@ -6,6 +6,7 @@ static inline void lock(uint8_t *lock) { "spinlock:\n" "lock xchgb [%0], al\n" "test al, al\n" + "pause\n" "jnz spinlock\n" ::"r"(lock):"al"); } @@ -14,4 +15,9 @@ static inline void unlock(uint8_t *lock) { asm("lock andb [%0], 0"::"r"(lock)); } +static inline void waitup(uint8_t *loto) { +} + +#define CREATE_LOTO(name) + #endif diff --git a/src/indigo_os b/src/indigo_os index 3fe850b..5f119d0 100755 Binary files a/src/indigo_os and b/src/indigo_os differ diff --git a/src/kernel/int.c b/src/kernel/int.c index 5901a90..5db0b9a 100644 --- a/src/kernel/int.c +++ b/src/kernel/int.c @@ -199,8 +199,10 @@ void init_exceptions() { for(e = 10; e < 15; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode); for(e = 18; e < 21; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception); } -//void new_idt +void smp_load_idt() { + asm("lidt [%0]\n"::"m"(idtr)); +} void init_interrupts_bsp() { init_madt(); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 11df1f1..ab60f18 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -15,16 +15,19 @@ #include #include #include +#include //testing headers -#include +//#include + void kmain() { PANIC(KERNEL_PANIC_KERNEL_RETURNED); } void smp_kinit() { - printf("\nKernal started on core\n"); //TODO get lapic working, then print core number + printf("Kernal started on core <<<<< \n"); + smp_load_idt(); kmain(); } @@ -47,8 +50,10 @@ void kernel_init() { randinit(); + clear_screen(); + debug_pzone(); smp_boot(); fix_stack(); - //unmap_lowmem(); + unmap_lowmem(); kmain(); } diff --git a/src/kernel/klog.c b/src/kernel/klog.c index c62c4d3..431c09b 100644 --- a/src/kernel/klog.c +++ b/src/kernel/klog.c @@ -109,10 +109,10 @@ static unsigned int on_line = 0; void clear_screen() { - char *screen_buffer = (void *)VIDEO_BUFFER; - for(unsigned int i = 0; i <= (80 * 25); i++) screen_buffer[i * 2] = ' '; on_char = 0; on_line = 0; + char *screen_buffer = (void *)VIDEO_BUFFER; + for(unsigned int i = 0; i <= (80 * 25); i++) screen_buffer[i * 2] = ' '; } void next_line() { diff --git a/src/kernel/madt.c b/src/kernel/madt.c index adeb547..25302f6 100644 --- a/src/kernel/madt.c +++ b/src/kernel/madt.c @@ -171,7 +171,7 @@ void get_coreinfo(struct cores_info *cores) { if(entry->type == LOCAL_APIC) { ap_info = (void *)entry + 2; if(ap_info->flags & 1) { - cores->apic_id[cores->corecount] = ap_info->processor_id; + cores->apic_id[cores->corecount] = ap_info->apic_id; cores->corecount++; } } diff --git a/src/kernel/page.c b/src/kernel/page.c index 3f6c4a8..dea3941 100644 --- a/src/kernel/page.c +++ b/src/kernel/page.c @@ -101,7 +101,7 @@ void unmap_lowmem() { entry[0].present = 0; } -void debug_print_memory() { +void debug_pzone() { struct memory_table *memtable = (void *)ZONE_MAP; printf(" __________________________________________________________________________\n"); printf("| type\tstart\t\t\tend\t\t\tsize\t\t |\n"); @@ -441,7 +441,7 @@ pmap_t *init_pmap(size_t pagetable_size) { pmap_size = (uint64_t)(pmap->buddy[pmap->max_buddy] + pmap->bsize[pmap->max_buddy]) - (uint64_t)pmap; first_pmap = pmap; //we spoof palloc into allocating from the specific required pmap. - palloc(pmap_size); + palloc(pmap_size); //TODO (MAJOR BUG) something isn't right, I don't think } } return pmap; diff --git a/src/kernel/panic.c b/src/kernel/panic.c index d17c185..06b37da 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -4,12 +4,13 @@ #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); + clear_screen(); #ifdef EASTEREGG_BLOATWARE printf("\nKernel PANIC!!!!!!!\n"); diff --git a/src/kernel/printf.c b/src/kernel/printf.c index b496bce..62261ec 100644 --- a/src/kernel/printf.c +++ b/src/kernel/printf.c @@ -33,6 +33,8 @@ #include #include +#include + #include "printf.h" @@ -870,7 +872,6 @@ 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, ...) diff --git a/src/kernel/smp.c b/src/kernel/smp.c index 9714c91..ff08f93 100644 --- a/src/kernel/smp.c +++ b/src/kernel/smp.c @@ -16,8 +16,10 @@ extern lapic_t lapic; 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; +extern struct gdt_descriptor final_gdt_descriptor; +extern struct cpu_info *smp_stackarray_ptr; + +uint8_t corecount; //total corecount struct icr_reg { uint8_t vector; @@ -43,12 +45,21 @@ struct gdt_descriptor { void *offset; } __attribute__((packed)); +struct cpu_info { + uint8_t apic_id; + uint8_t secondary_bsp; //force 8 bits for alignment and consistency purposes + void *stack; +} __attribute__((packed)); + + static struct gdt_descriptor gdtr; void smp_boot() { uint8_t cores_active = 1; + uint8_t stack_i = 0, core_i; struct cores_info cores; struct icr_reg icr; + struct cpu_info *stackarray; get_coreinfo(&cores); if(cores.corecount == 1) { asm("sgdt [%0]"::"m"(gdtr)); @@ -58,16 +69,28 @@ void smp_boot() { } bzero(&icr, sizeof(icr)); - void **core_stacks = malloc(sizeof(void *) * (cores.corecount - 1)); - for(unsigned int s = 0; s < (cores.corecount - 1); s++) { - core_stacks[s] = palloc(0x1000); + corecount = cores.corecount; + + stackarray = malloc(sizeof(struct cpu_info) * (cores.corecount - 1)); + for(core_i = 0; core_i < cores.corecount; core_i++) { + if(cores.apic_id[core_i] == cores.bsp) continue; + stackarray[stack_i].apic_id = cores.apic_id[core_i]; + stackarray[stack_i].stack = palloc(0x1000); + stackarray[stack_i].secondary_bsp = (stack_i)? false : true; + stack_i++; + } + for(stack_i = 0; stack_i < (cores.corecount - 1); stack_i++) { + printf("%i's stack: %lx\n", stackarray[stack_i].apic_id, stackarray[stack_i].stack); } memcpy(PHYS_TO_VIRT((void *)0x8000), PHYS_TO_VIRT(&__load_start_smp_bootloader), &__load_stop_smp_bootloader - &__load_start_smp_bootloader); - smp_bootstrap_corecount = &cores_active; - smp_bootstrap_bsp = cores.bsp; - smp_bootstrap_stackarray = (void *)core_stacks; + + //we have to use the virtual address, even though lowmem is still mapped, + //so GCC doesn't complain about the mcmodel + *(uint8_t *)PHYS_TO_VIRT(&smp_bootstrap_bsp) = cores.bsp; + *(uint8_t **)PHYS_TO_VIRT(&smp_bootstrap_corecount) = &cores_active; + *(struct cpu_info **)PHYS_TO_VIRT(&smp_stackarray_ptr) = stackarray; icr.deliv_mode = 0b101; icr.dest_shorthand = 0b11; @@ -82,9 +105,9 @@ void smp_boot() { if(cores_active != cores.corecount) write_icr(0, *(uint32_t *)&icr); usleep(200); if(cores_active != cores.corecount) { - printf("Only %i cores online (expected %i)\n", cores_active, cores.corecount); //maybe add a panic - PANIC(KERNEL_PANIC_SMP_FAILED); + printf("Only %i cores online (expected %i)\n", cores_active, cores.corecount); + PANIC(KERNEL_PANIC_SMP_FAILED); //will replace this with warning once we push public } - printf("%i \n", cores_active); - //asm("lgdt [%0]\n"::"r"(PHYS_TO_VIRT(&final_gdt_descriptor))); TODO NOW + printf("All detected %i cores have booted\n", cores_active); + asm("lgdt [%0]\n"::"r"(PHYS_TO_VIRT(&final_gdt_descriptor))); //note that segment registers are not reloaded } diff --git a/src/kernel/smp_trampoline.asm b/src/kernel/smp_trampoline.asm index 78303a3..20c971e 100644 --- a/src/kernel/smp_trampoline.asm +++ b/src/kernel/smp_trampoline.asm @@ -1,10 +1,11 @@ -global smp_bootstrap_stackarray +global smp_stackarray_ptr global smp_bootstrap_bsp global smp_bootstrap_corecount global final_gdt_descriptor extern smp_kinit extern _pmem_vaddr +extern temp_debug_2 [bits 16] smp_trampoline: @@ -61,6 +62,7 @@ smp_protected: bits 32 mov ax, SMP_PROTECTED_DATA_SEGMENT +mov es, ax mov ds, ax mov ss, ax mov es, ax @@ -88,7 +90,6 @@ shr ebx, 9 mov ecx, 0xc0000080 rdmsr or eax, 1 << 8 -fuckyou: or eax, ebx wrmsr @@ -107,6 +108,7 @@ jmp SMP_LONG_CODE_SEGMENT:smp_longsetup ;________________________________________________________________________________________ bits 64 +align 8 final_gdt: .start: ;and now we set up a temporary GDT creating a 1:1 mapping @@ -136,7 +138,6 @@ db 0 .end: ; later calculates offset in defs below - final_gdt_descriptor: dw final_gdt.end - final_gdt.start - 1 .offset: @@ -149,33 +150,52 @@ smp_longsetup: mov eax, 1 cpuid shr ebx, 24 -cmp bl, BYTE [smp_bootstrap_bsp] -jl .apic_below_bsp -sub bl, 1 - -.apic_below_bsp: -mov rax, QWORD [smp_bootstrap_stackarray] -mov rsp, QWORD [rax + rbx * 8] - -mov rax, 0xffff800000000000 -;or QWORD [final_gdt_descriptor.offset], rax -;lgdt [final_gdt_descriptor] -.inc_corecounter: +mov rsi, [smp_stackarray_ptr] +.search_for_cpuinfo: +mov al, [rsi] +cmp al, bl +je smp_longsetup.cpuinfo_found +add rsi, 10 +jmp .search_for_cpuinfo +.cpuinfo_found: +mov bl, [rsi + 1] +mov rsp, QWORD [rsi + 2] ;core_stack.stack mov rax, [smp_bootstrap_corecount] lock inc BYTE [rax] - smp_enter_kernel: +test bl, bl +jz .wait_for_gdt + +; setting gdt +mov rax, 0xffff800000000000 +or QWORD [final_gdt_descriptor.offset], rax +mov QWORD [smp_lock], 0 + + +.wait_for_gdt: + +mov al, [smp_lock] +test al, al +pause +jnz .wait_for_gdt +lgdt [final_gdt_descriptor] + mov rax, smp_kinit jmp rax +cli +hlt +jmp $ + align 8 -smp_bootstrap_stackarray: dq 0 -smp_lock: dq 0 +smp_stackarray_ptr: dq 0 +smp_lock: dq 1 +screen_debug_pos: dq 0 smp_bootstrap_bsp: db 0 smp_bootstrap_corecount: db 0 -- cgit v1.2.3