From b2dc154433fecdacc245387d6b15736e3415532e Mon Sep 17 00:00:00 2001 From: Brett Weiland <brett_weiland@bpcspace.com> Date: Thu, 26 Aug 2021 21:39:57 -0500 Subject: [PATCH] smp boots! --- src/.gdb_history | 440 +++++++++++++++++----------------- src/bootloader/bootloader.asm | 1 - src/debug/gdbinit.gdb | 1 + src/include/kernel.h | 2 + src/include/paging.h | 1 + src/indigo_os | Bin 41152 -> 0 bytes src/kernel/kernel.c | 8 +- src/kernel/page.c | 6 +- src/kernel/smp.c | 39 +-- src/kernel/smp_trampoline.asm | 44 +++- src/link.ld | 16 +- 11 files changed, 297 insertions(+), 261 deletions(-) delete mode 100755 src/indigo_os diff --git a/src/.gdb_history b/src/.gdb_history index edbca99..df12f20 100644 --- a/src/.gdb_history +++ b/src/.gdb_history @@ -1,256 +1,256 @@ -c -info threads -quit -c -info threads +thread 1 +next +thread 1 step -c -print cores -print cores_active -info threads -c -info threads +print core_stacks +print core_stacks[0] +print core_stacks[1] +print core_stacks[2] +print core_stacks[3] quit c -info threads -c -info threads -quit -b smp_boot -c -qit -quit -b smp.c:59 -c -next -info threads -next -info threads -next -info threads -info threads -info threads -quit -b smp.c:65 -c -next -info threads -info thread 2 -quit -b timer.c:57 c quit -b timer.c:57 +hb debug +c +c +next +info reg rax +thread 1 +thread 2 +info reg rax +print smp_bootstrap_stackarray +print *smp_bootstrap_stackarray +print/x *smp_bootstrap_stackarray +inf ore g rax +print smp_bootstrap_array +quit +hb debug +c c quit -b smp.c:57 +hb debug c -print *(uint32_t *)&icr -print/x *(uint32_t *)&icr -info threads -next -info threads -next -info threads -next -info threads -next -info threads -next -info threads -next -info threads -print/x *(uint32_t *)&icr -pirnt (void *)0x8000 -prit (void *)0x8000 -print (void *)0x8000 -print *(void *)0x8000 -print __load_start_smp_bootloader -print &__load_start_smp_bootloader -print (void *)&__load_start_smp_bootloader -print (void *)&__load_stop_smp_bootloader +c +nexti +info reg ebx +info reg ebx quit -print &__load_start_smp_bootloader -print &__load_stop_smp_bootloader -print &__load_stop_smp_bootloader -print smp_bootstrap -print smp_bootloader -print &__load_stop_smp_bootloader -print __load_stop_smp_bootloader -print &__load_stop_smp_bootloader -print smp_bootstrap_corecount -b smp_trampoline -hb smp_trampoline +hb debug c -d -d -hb smp_trampoline c -info reg rip +quit +hb debug +c +c +stepi +info reg ebx +stepi +stepi +info reg rsp +stepi +info reg esp +info reg rsp +x rbx +info reg rbx +print smp_bootstrap_stackarray +print/x *smp_bootstrap_stackarray +info reg ebx +quit +quit +stepi +info reg cl +info reg ecx +quit +next +quit +nexti +info reg ecx +stepi +info reg ebx +quit +c +quit +stepi +info reg ebx +stepi +info reg bl +print smp_bootstrap_bsp +info reg bl +stepi +info reg bl +info reg ebx +x 0x80f0 +print (uint64_t *)0x80f0 +print (uint64_t*)0x80f0 +x 0x80f9 +stepi +stepi +info reg rsp +print smp_bootstrap_stackarray +print/x *smp_bootstrap_stackarray +quit +info reg rax +info reg rax +x 0xbffde058 +print smp_bootstrap_bsp +print &smp_bootstrap_bsp +print smp_bootstrap_bsp +x 0x80f1 +print (uint64_t)*0x80f1 +x smp_bootstrap_bsp +smp_bootstrap_bsp +print smp_bootstrap_bsp +smp_bootstrap_stackarray +print smp_bootstrap_stackarray +print *smp_bootstrap_stackarray +print smp_bootstrap_stackarray[0] +print/x smp_bootstrap_stackarray[0] +print/x smp_bootstrap_stackarray[1] +print/x smp_bootstrap_stackarray[0] +info reg rax +print smp_bootstrap_stackarray +quit +info reg rax +quit +next +stepi +quit +c +quit +c +stepi quit hb smp_trampoline c +next +hb debug +c quit c quit -hb smp_trampoline -c -info threads -hexdump 0 -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -cc -c -c -c -c -c -c -c -d -c -quit -b smp_trampoline -c -hb smp_trampoline -d 2 -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c -c c quit c -info threads +stepi quit c -info threads quit -info threads -next -next -print 0x8000 / 0x1000 -next -quit -quit -next -info threads -next -info threads -next -info threads -quit -next -info threads -next -info threads -next -info threads -next -info threads -next -info threads -next -info threads -quit -hb 0 -c -quit -next -next -next -print icr -next -next -info threads -quit -next -info threads -next -info threads -next -info threads -next -info threads -quit -b smp.c:60 c next -info threads -next -info threads +info reg rsp +thread 2 +context +quit quit -b memcpy c -print dest -x 0xffff800000008000 -print 0xffff800000008000 -print/x 0xffff800000008000 -print n -b 54 +info reg cl +info reg ecx +quit c next -info reg +quit +info reg rax +c +info reg rax +stepi +info rax +inf oreg rax info reg rax info reg rbx -inf reg rdi -x/i 0xffff800000000000 -x/i 0xffff800000008000 - smp_trampoline -hexdump 0xffff800000008000 +x 0xffff8000bffde058 +x *0xffff8000bffde058 +print *0xffff8000bffde058 +print/x *0xffff8000bffde058 +print/x (uint64_t)*0xffff8000bffde058 +print/x (uint64_t)0xffff8000bffde058 +print/x (uint64_t)*0xffff8000bffde058 +print/x (uint64_t)0xffff8000bffde058 +print/x (uint64_t)0xffff8000bffde058[1] +print ((uint64_t)0xffff8000bffde058)[1] +print ((uint64_t *)0xffff8000bffde058)[1] +print ((uint64_t *)0xffff8000bffde058)[0] +print ((uint64_t *)0xffff8000bffde058)[1] +print/x ((uint64_t *)0xffff8000bffde058)[1] quit -b memcpy c -print dest -hexdump 0xffff800000008000 -b 64 +nexti +quit +c +stepi +stepi +info thread 0 +thread 1 c -hexdump 0xffff800000008000 -print __load_start_smp_bootloader -hexdump 0xffff800000000800 quit -info reg rsp +next +print cores_active +print cores.corecount +next +print cores.corecount +print cores_active +next +c +print cores_active +thread 0 +print cores_active +thread 1 +print cores_active +quit +c +stepi +info reg rax +thread 0 +thread 2 +print cores_active +context +thread 1 +next +c +print cores_active +print &cores_active +thread 2 +info reg rax +info reg rax +x 0x1000bf +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 +c +c +c +c quit diff --git a/src/bootloader/bootloader.asm b/src/bootloader/bootloader.asm index f912e49..8e5fbeb 100644 --- a/src/bootloader/bootloader.asm +++ b/src/bootloader/bootloader.asm @@ -116,5 +116,4 @@ jmp $ %include "bootloader/cpu_check.asm" %include "bootloader/video.asm" %include "bootloader/enter_kernel.asm" - times 2048 - ($ - $$) db 0 diff --git a/src/debug/gdbinit.gdb b/src/debug/gdbinit.gdb index c890f8d..b6ad20a 100644 --- a/src/debug/gdbinit.gdb +++ b/src/debug/gdbinit.gdb @@ -1,5 +1,6 @@ target remote localhost:1234 symbol-file debug/debug_syms.o +hb debug hb smp_boot diff --git a/src/include/kernel.h b/src/include/kernel.h index 4d8ea22..db0f049 100644 --- a/src/include/kernel.h +++ b/src/include/kernel.h @@ -9,5 +9,7 @@ #define DEV_EMAIL "brett_weiland@bpcspace.com" +void multicore_main(); + #endif diff --git a/src/include/paging.h b/src/include/paging.h index 16afae2..302e567 100644 --- a/src/include/paging.h +++ b/src/include/paging.h @@ -18,6 +18,7 @@ void pfree(void *addr, size_t size); void debug_pmap(); void get_mem_capabilities(); void ram_stresser(); +void fix_stack(); #endif diff --git a/src/indigo_os b/src/indigo_os deleted file mode 100755 index 0a9c1af6e847cc4b0eaa7e9ccbe4341cb0a6de3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41152 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%0AvtEj@h+`bccI!*%lL;6de~g<q-`)m zE~1{*8Z<lKrTn&8bj+r%R3l;*j#KHMY8jVk`uTt#v8@YuJk8b*%%<;+`{7SXPOB>Z z!R;G;?{vCbIhTSRXXRH(sD``~537nJb`@t6>#cs&3=U_d*ARC{`r0bj5SBV%G~5!F zYsqTDpCLCR6qHxv7qi-xc(6vx49YbE<YCZ9L75gB5amvOKNgfr5r~zA<*|5DE@II8 z6wd30Op7@|xd6XNF%Az94ayga_jC9i6!XM;CclH?ryzryx@MwWDC*+|6{?LDr$cx4 zj0ZL>{}jK7Z|2sD+(_j=2Pi9c*ULBnG8&@@F7uVhxvrNqY^)KlS&jL4#h8hf;g;7> z3g~|aD%etKHGtt(j2ga)&Afo=je|N|+THT)z?pvOWUP=gvwQ<!&~kKJYYr~@Ebq0? z**dy%JHf;rIUi9lzm#bzYYr9i2!sI|!XSu&KJtP0KY_DArz0rSq6U@!F)lxi6QoL= zNy+#H#*z%;RuY8Ae|+f`e}?=oL@n<0U5B5CXQ0xvVQ=_GVt*Fa|5MgD^>ZwI@po+| z*`RF%qVL))v_YEyYBQC1a`Pq`YC~RU<ZljrJ(3Rg&*o2Z_;9^}mu`lrUgQ;5Iuv5* z1AnP#+#vCw-&0$;5-THBN~!ixp0u<cmnjSapXu@85(m190@p}*t1EDI!rVFdYKWaJ z-UiD~0(^>Mr?x56%??(cT>csOCdmW#LXEGXGEZ%!3mUAY8$c#5_EaohR$Yrrk0j}2 z@t4sDaS<^+o`9xPrXsUwK$X_LBWMI4l`vEI{+4*s`g_|YyI*>1I=`Fi?AE%uBrPmH z**bOm$DjSZ)Sm)BiHKY4q$%r7^8wxu{EAfkfc2(k;KpFN?OgN-n?}ajyhfn_v=RT# zgM<CLR6J;8G;tJ(;_Sx1hp--d5ormF4~jEf%m*n>6#u-?iLYSnNQ<+LmxaZBM)YwG zTJK{!2PZG;$3u_P$7{|PUat7UZSe@#3pAKea5&uAtglaxhdCqEVa;!O`Nq7b>P~!$ zrVg#Is%}aiF519VSu6Q>(V}{OqWM@?X`Iq}&pgyJEkxR7aL(qnw@(a%48(At8Nc** zsAAl)_bbAI&Ei$kUW<PBVW^DP?z;1i+vk+=l8&b1tlC>zU{6tW!WO!Fh%qGT6wGj7 zw8XBcSS-jK_oY_o>eqPvXimu;CAY(s_s-kzD5HrO%!C{bOE6F++6Ge|{n7cqA$u^e zd(^yp?p|<z$-I)gOYSMT_de}4y4T0<Vh#0ve7C30-ylBaL*Me5pe(K<)liEs^WaHq opeJ1)SPJ>fq#|4G;C3V9u}obKX0>Fm&3PnuO<wa^v{mx|0Xt~dS^xk5 diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 50b8359..d550e37 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -20,7 +20,10 @@ #include <testmalloc.h> - +void multicore_main() { + printf("\nKernal started\n"); + asm("cli\nhlt"); +} void main() { #ifndef SCREEN_OUTPUT @@ -28,7 +31,6 @@ void main() { #endif get_mem_capabilities(); init_pmap(map_complete_physical()); - unmap_lowmem(); find_root_sdp(); @@ -40,6 +42,8 @@ void main() { randinit(); smp_boot(); + fix_stack(); + unmap_lowmem(); PANIC(KERNEL_PANIC_KERNEL_RETURNED); } diff --git a/src/kernel/page.c b/src/kernel/page.c index 9db8660..734194c 100644 --- a/src/kernel/page.c +++ b/src/kernel/page.c @@ -77,8 +77,7 @@ void get_mem_capabilities() { NX_capable = (edx >> 20) & 1; } - -void unmap_lowmem() { +void fix_stack() { struct stack_frame *frame; asm("addq rsp, %0\n" @@ -92,7 +91,10 @@ void unmap_lowmem() { frame->next = PHYS_TO_VIRT((void *)frame->next); frame = frame->next; } +} + +void unmap_lowmem() { //[future] //eventually, you should use the function that unmaps pages when you write it page_table *entry = (page_table *)PAGEMAP_LOCATION; diff --git a/src/kernel/smp.c b/src/kernel/smp.c index d3c74fe..5796ab9 100644 --- a/src/kernel/smp.c +++ b/src/kernel/smp.c @@ -1,9 +1,12 @@ #include <kernel.h> +#include <printf.h> #include <madt.h> #include <timer.h> #include <cpuid.h> #include <int.h> #include <libc.h> +#include <paging.h> +#include <heap.h> #define LAPIC_ICR_LOW 192 #define LAPIC_ICR_HIGH 196 @@ -11,6 +14,8 @@ 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; struct icr_reg { uint8_t vector; @@ -37,19 +42,24 @@ static inline void write_icr(uint8_t dest, uint32_t message) { } void smp_boot() { - uint8_t cores_active = 0; //TODO change in asm + uint8_t cores_active = 1; //TODO change in asm struct cores_info cores; - unsigned int ci; - struct icr_reg icr; + get_coreinfo(&cores); 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); + } + memcpy(PHYS_TO_VIRT((void *)0x8000), PHYS_TO_VIRT(&__load_start_smp_bootloader), &__load_stop_smp_bootloader - &__load_start_smp_bootloader); - *(uint8_t **)PHYS_TO_VIRT(&smp_bootstrap_corecount) = &cores_active; + smp_bootstrap_corecount = &cores_active; + smp_bootstrap_bsp = cores.bsp; + smp_bootstrap_stackarray = (uint64_t)core_stacks; - get_coreinfo(&cores); icr.deliv_mode = 0b101; icr.dest_shorthand = 0b11; @@ -61,20 +71,13 @@ void smp_boot() { icr.vector = 8; write_icr(0, *(uint32_t *)&icr); usleep(200); - write_icr(0, *(uint32_t *)&icr); - - /** + if(cores_active != cores.corecount) write_icr(0, *(uint32_t *)&icr); + usleep(200); if(cores_active != cores.corecount) { - write_icr(0, *(uint32_t *)&icr); - usleep(200); + printf("NOT ALL CORES ONLINE\n"); + asm("cli\nhlt"); } - **/ - /** - for(ci = 0; ci < cores.corecount; ci++) { - if(ci == cores.bsp) continue; - //send init sipi - write_icr(ci, *(uint32_t *)&icr); + else { + printf("%i!!!!!!\n", cores_active); } - **/ - } diff --git a/src/kernel/smp_trampoline.asm b/src/kernel/smp_trampoline.asm index f723aa6..15b85e2 100644 --- a/src/kernel/smp_trampoline.asm +++ b/src/kernel/smp_trampoline.asm @@ -1,10 +1,12 @@ -global smp_bootstrap_corecount; +global smp_bootstrap_stackarray +global smp_bootstrap_bsp +global smp_bootstrap_corecount + +extern multicore_main [bits 16] smp_trampoline: cli -hlt -hlt xor ax, ax mov ds, ax @@ -50,7 +52,7 @@ SMP_PROTECTED_DATA_SEGMENT equ .gdt_data_p - .gdt_start_p ;________________________________________________________________________________________ -.smp_protected +.smp_protected: [bits 32] mov ax, SMP_PROTECTED_DATA_SEGMENT @@ -60,6 +62,9 @@ mov es, ax mov fs, ax mov gs, ax +lgdt [.gdt_descriptor_l] + + mov eax, 0x10000 ;TODO clarify _why_ this is a thing mov cr3, eax @@ -82,12 +87,14 @@ or eax, 1 << 8 | 1 << 11 or eax, edx wrmsr + ;enable paging mov eax, cr0 or eax, 1 << 31 | 1 << 0; and ax, ~(1 << 2) mov cr0, eax + jmp SMP_LONG_CODE_SEGMENT:.counter ;________________________________________________________________________________________ @@ -123,7 +130,7 @@ db 0 .gdt_end_l: ; later calculates offset in defs below -.descriptor_l: +.gdt_descriptor_l: dw .gdt_end_l - .gdt_start_l - 1 dq .gdt_start_l @@ -131,10 +138,27 @@ SMP_LONG_CODE_SEGMENT equ .gdt_code_l - .gdt_start_l SMP_LONG_DATA_SEGMENT equ .gdt_data_l - .gdt_start_l .counter: -mov rax, [smp_bootstrap_corecount] -inc QWORD [rax] -cli -hlt -;TODO set up stack; enter kernel +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] +debug: +mov rsp, QWORD [rax + rbx * 8] + +mov rax, [smp_bootstrap_corecount] +inc BYTE [rax] + +mov rax, multicore_main +jmp rax + +align 8 +smp_bootstrap_stackarray: dq 0 +smp_bootstrap_bsp: db 0 smp_bootstrap_corecount: db 0 +times 512 - ($ - $$) db 0 diff --git a/src/link.ld b/src/link.ld index 529d43f..9d707b4 100644 --- a/src/link.ld +++ b/src/link.ld @@ -11,23 +11,23 @@ SECTIONS bootloader.o(.text) } smp_bootloader 0x8000 : - AT(SIZEOF(bootloader)) + AT(0 + SIZEOF(bootloader)) { smp_trampoline.o(.text) } kernel _kernel_s1_loc : - AT (SIZEOF(bootloader)) + AT (0 + SIZEOF(smp_bootloader) + SIZEOF(bootloader)) { - EXCLUDE_FILE (*bootloader.o) *(.text .data .bss .rodata .comment .eh_frame) + EXCLUDE_FILE (*bootloader.o *smp_trampoline.o) *(.text .data .bss .rodata .comment .eh_frame) } } -_kernel_sector_size = ((SIZEOF(kernel) + SIZEOF(smp_bootloader) + 511) / 512); -_kernel_page_size = ((SIZEOF(kernel) + SIZEOF(smp_bootloader) + 0xfff) / 0x1000); -_bootloader_stage1_size = (SIZEOF(bootloader) + 511) / 512; +_kernel_sector_size = ((SIZEOF(kernel) + 511) / 512); +_kernel_page_size = ((SIZEOF(kernel) + 0xfff) / 0x1000); +_bootloader_stage1_size = (SIZEOF(bootloader) + SIZEOF(smp_bootloader) + 511) / 512; -__load_start_smp_bootloader = LOADADDR(smp_bootloader); -__load_stop_smp_bootloader = LOADADDR(smp_bootloader) + SIZEOF(smp_bootloader); +__load_start_smp_bootloader = LOADADDR(smp_bootloader) + 0x7c00; +__load_stop_smp_bootloader = LOADADDR(smp_bootloader) + SIZEOF(smp_bootloader) + 0x7c00; _kernel_stack_loc = (0x100000 + (_kernel_page_size * 0x1000) + 0x2000) - 8; _kernel_shared_zone_begin = 0x100000 + (_kernel_page_size * 0x1000) + 0x2000;