Browse Source

对多核启动的过程加锁

fslongjin 2 years ago
parent
commit
ac2508224e
6 changed files with 99 additions and 28 deletions
  1. 2 1
      .vscode/settings.json
  2. 1 1
      bochsrc
  3. 11 1
      kernel/common/printk.c
  4. 56 0
      kernel/process/spinlock.h
  5. 28 24
      kernel/smp/smp.c
  6. 1 1
      run.sh

+ 2 - 1
.vscode/settings.json

@@ -87,5 +87,6 @@
         "cstdbool": "c",
         "typeinfo": "c"
     },
-    "C_Cpp.errorSquiggles": "Enabled"
+    "C_Cpp.errorSquiggles": "Enabled",
+    "esbonio.sphinx.confDir": ""
 }

+ 1 - 1
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"

+ 11 - 1
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;
 }
 

+ 56 - 0
kernel/process/spinlock.h

@@ -0,0 +1,56 @@
+/**
+ * @file spinlock.h
+ * @author fslongjin ([email protected])
+ * @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");
+}

+ 28 - 24
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();
 }

+ 1 - 1
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"