diff --git a/.vscode/settings.json b/.vscode/settings.json index 88adf437..2b95eac1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -87,5 +87,6 @@ "cstdbool": "c", "typeinfo": "c" }, - "C_Cpp.errorSquiggles": "Enabled" + "C_Cpp.errorSquiggles": "Enabled", + "esbonio.sphinx.confDir": "" } \ No newline at end of file diff --git a/bochsrc b/bochsrc index 09ff6cf3..206512d2 100644 --- a/bochsrc +++ b/bochsrc @@ -1,7 +1,7 @@ # configuration file generated by Bochs plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, iodebug=1 config_interface: textconfig -display_library: x, options="gui_debug" +display_library: x#, options="gui_debug" #memory: host=2048, guest=2048 romimage: file="/usr/local/share/bochs/BIOS-bochs-latest" vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest" diff --git a/kernel/common/printk.c b/kernel/common/printk.c index 27547fa2..a71affaf 100644 --- a/kernel/common/printk.c +++ b/kernel/common/printk.c @@ -5,10 +5,13 @@ #include "kprint.h" #include "../driver/multiboot2/multiboot2.h" #include "../mm/mm.h" +#include "../process/spinlock.h" + //#include "linkage.h" struct screen_info pos; ul VBE_FB_phys_addr; // 由bootloader传来的帧缓存区的物理地址 +static spinlock_t printk_lock; int calculate_max_charNum(int len, int size) { @@ -33,11 +36,14 @@ int printk_init(const int char_size_x, const int char_size_y) pos.max_x = calculate_max_charNum(pos.width, char_size_x); pos.max_y = calculate_max_charNum(pos.height, char_size_y); - // @todo:将来需要将帧缓冲区物理地址填写到这个地址的页表项中 + VBE_FB_phys_addr = (ul)info.framebuffer_addr; pos.FB_address = (uint *)0x0000000003000000; pos.FB_length = 1UL*pos.width * pos.height; + // 初始化自旋锁 + spin_init(&printk_lock); + // ======== 临时的将物理地址填写到0x0000000003000000处 之后会在mm内将帧缓存区重新映射===== global_CR3 = get_CR3(); @@ -649,6 +655,8 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. * @param ... 格式化字符串 */ + spin_lock(&printk_lock); + va_list args; va_start(args, fmt); @@ -704,6 +712,8 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. } } + for(int j=0;j<1e5;++j); + spin_unlock(&printk_lock); return i; } diff --git a/kernel/process/spinlock.h b/kernel/process/spinlock.h new file mode 100644 index 00000000..c36caf12 --- /dev/null +++ b/kernel/process/spinlock.h @@ -0,0 +1,56 @@ +/** + * @file spinlock.h + * @author fslongjin (longjin@RinGoTek.cn) + * @brief 自旋锁 + * @version 0.1 + * @date 2022-04-07 + * + * @copyright Copyright (c) 2022 + * + */ +#include "../common/glib.h" + +/** + * @brief 定义自旋锁结构体 + * + */ +typedef struct +{ + __volatile__ char lock; // 1:unlocked 0:locked +} spinlock_t; + +/** + * @brief 初始化自旋锁 + * + * @param lock + */ +void spin_init(spinlock_t *lock) +{ + lock->lock = 1; +} + +/** + * @brief 自旋锁加锁 + * + * @param lock + */ +void spin_lock(spinlock_t *lock) +{ + __asm__ __volatile__("1: \n\t" + "lock decq %0 \n\t" // 尝试-1 + "jns 3f \n\t" // 加锁成功,跳转到步骤3 + "2: \n\t" // 加锁失败,稍后再试 + "pause \n\t" + "cmpq $0, %0 \n\t" + "jle 2b \n\t" // 若锁被占用,则继续重试 + "jmp 1b \n\t" // 尝试加锁 + "3:" + : "=m"(lock->lock)::"memory"); +} + + +void spin_unlock(spinlock_t * lock) +{ + __asm__ __volatile__("movq $1, %0 \n\t" + :"=m"(lock->lock)::"memory"); +} \ No newline at end of file diff --git a/kernel/smp/smp.c b/kernel/smp/smp.c index d23d8341..a769e259 100644 --- a/kernel/smp/smp.c +++ b/kernel/smp/smp.c @@ -5,15 +5,22 @@ #include "../common/cpu.h" #include "../mm/slab.h" #include "../process/process.h" +#include "../process/spinlock.h" + +static spinlock_t multi_core_starting_lock; // 多核启动锁 static struct acpi_Processor_Local_APIC_Structure_t *proc_local_apic_structs[MAX_SUPPORTED_PROCESSOR_NUM]; static uint32_t total_processor_num = 0; int current_starting_cpu = 0; + + void smp_init() { - ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0}; + spin_init(&multi_core_starting_lock); + ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0}; + apic_get_ics(ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC, tmp_vaddr, &total_processor_num); kdebug("processor num=%d", total_processor_num); @@ -34,19 +41,18 @@ void smp_init() icr_entry.res_2 = 0; icr_entry.res_3 = 0; + icr_entry.vector = 0x00; + icr_entry.deliver_mode = ICR_INIT; + icr_entry.dest_shorthand = ICR_ALL_EXCLUDE_Self; + icr_entry.destination.x2apic_destination = 0x00; + + wrmsr(0x830, *(unsigned long *)&icr_entry); // INIT IPI + for (int i = 1; i < total_processor_num; ++i) // i从1开始,不初始化bsp { - if(proc_local_apic_structs[i]->ACPI_ID==0) - continue; + spin_lock(&multi_core_starting_lock); current_starting_cpu = i; - icr_entry.vector = 0x00; - icr_entry.deliver_mode = ICR_INIT; - icr_entry.dest_shorthand = ICR_ALL_EXCLUDE_Self; - icr_entry.destination.x2apic_destination = current_starting_cpu; - - wrmsr(0x830, *(unsigned long *)&icr_entry); // INIT IPI - kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->ACPI_ID, proc_local_apic_structs[i]->flags); // 为每个AP处理器分配栈空间、tss空间 cpu_core_info[i].stack_start = (uint64_t)kmalloc(STACK_SIZE, 0); @@ -57,23 +63,23 @@ void smp_init() cpu_core_info[i].tss_vaddr = (uint64_t)kmalloc(128, 0); set_tss_descriptor(10 + (i * 2), (void *)(cpu_core_info[i].tss_vaddr)); - set_tss64((uint*)cpu_core_info[i].tss_vaddr, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start,cpu_core_info[i].stack_start); + set_tss64((uint *)cpu_core_info[i].tss_vaddr, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start, cpu_core_info[i].stack_start); kdebug("GDT Table %#018lx, \t %#018lx", GDT_Table[10 + i * 2], GDT_Table[10 + i * 2 + 1]); kdebug("(cpu_core_info[i].tss_vaddr)=%#018lx", (cpu_core_info[i].tss_vaddr)); kdebug("(cpu_core_info[i].stack_start)=%#018lx", (cpu_core_info[i].stack_start)); icr_entry.vector = 0x20; icr_entry.deliver_mode = ICR_Start_up; icr_entry.dest_shorthand = ICR_No_Shorthand; - icr_entry.destination.x2apic_destination = current_starting_cpu; + icr_entry.destination.x2apic_destination = proc_local_apic_structs[i]->ACPI_ID; // 先init ipi, 然后连续发送两次start-up IPI // x2APIC下,ICR寄存器地址为0x830 // xAPIC下则为0xfee00300(31-0) 0xfee00310 (63-32) - + wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI wrmsr(0x830, *(ul *)&icr_entry); // start-up IPI + //for(int k=0;i<1e5;++k); } - } /** @@ -84,27 +90,25 @@ void smp_ap_start() { // 切换栈基地址 //uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE; - - __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory"); __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory"); -/* - __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(stack_start) - : "memory"); - __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(stack_start) - : "memory");*/ + /* + __asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(stack_start) + : "memory"); + __asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(stack_start) + : "memory");*/ ksuccess("AP core successfully started!"); kdebug("current=%d", current_starting_cpu); apic_init_ap_core_local_apic(); load_TR(10 + current_starting_cpu * 2); + spin_unlock(&multi_core_starting_lock); sti(); kdebug("IDT_addr = %#018lx", &IDT_Table); - sti(); - //int a = 1 / 0; // 在这儿会出现异常,cs fs gs ss寄存器会被改变 + //sti(); + // int a = 1 / 0; // 在这儿会出现异常,cs fs gs ss寄存器会被改变 kdebug("IDT_addr = %#018lx", &IDT_Table); hlt(); - hlt(); } \ No newline at end of file diff --git a/run.sh b/run.sh index 0a269047..eee3cb61 100644 --- a/run.sh +++ b/run.sh @@ -12,7 +12,7 @@ if [ ! "$1" == "--nobuild" ]; then make clean fi -IA32_USE_QEMU=0 +IA32_USE_QEMU=1 bochsrc="./bochsrc" ARCH="x86_64"