]> Zhao Yanbai Git Server - kernel.git/commitdiff
未进入页映射的时候的代码还是用物理地址
authoracevest <zhaoyanbai@126.com>
Sat, 27 Dec 2025 13:08:05 +0000 (21:08 +0800)
committeracevest <zhaoyanbai@126.com>
Sat, 27 Dec 2025 13:08:05 +0000 (21:08 +0800)
.gitignore
boot/boot.c
boot/multiboot.S
gdbscript
include/cpuid.h [new file with mode: 0644]
include/msr.h
kernel/cpuid.c
qemu.sh
scripts/link.ld

index bd17c85f026a51f4a38779ba2d3522c129c0758a..6b0ccfb1cfcd0c303fdaf70b2030542a682c7b9f 100644 (file)
@@ -37,6 +37,7 @@ bochsout.txt
 *.lock
 *.DS_Store
 .vscode/settings.json
+.vscode/*
 *.iso
 **/serial_monitor/serial_monitor
 **/mkrootfs/mkrootfs
@@ -44,3 +45,4 @@ initrd
 initfs
 rootfs
 **/init
+
index b006e98c587e5f4e231d151f2581b4a3c69f9be0..e4d52145f0237baca9612e11aaea44f9aed5cf01 100644 (file)
@@ -16,6 +16,8 @@
 #include <page.h>
 #include <string.h>
 #include <system.h>
+#include <msr.h>
+
 
 struct boot_params boot_params __attribute__((aligned(32)));
 
@@ -244,6 +246,42 @@ extern void *kernel_begin;
 extern void *kernel_end;
 extern void *bootmem_bitmap_begin;
 
+
+#include <cpuid.h>
+
+__attribute__((section(".unpaged_text")))
+void test_unpaged_break() {
+    // printk("test unpaged break\n");
+}
+
+
+void lapic_init() {
+    cpuid_regs_t r;
+    r = cpuid(1);
+    if(r.edx & (1 << 9)) {
+        printk("local apic supported\n");
+        if(r.ecx & (1 << 21)) {
+            printk("x2apic supported\n");
+        } else {
+            panic("x2apic not supported\n");
+        }
+    } else {
+        panic("local apic not supported\n");
+    }
+
+    uint64_t apic_base = read_msr(MSR_IA32_APIC_BASE);
+    printk("apic base: %016lx\n", apic_base);
+
+    // 开启2xapic
+    apic_base |= (1 << 10);
+    write_msr(MSR_IA32_APIC_BASE, apic_base);
+
+    apic_base = read_msr(MSR_IA32_APIC_BASE);
+    printk("after 2xapic enable apic base: %016lx\n", apic_base);
+
+    test_unpaged_break();
+}
+
 void init_system_info() {
     system.kernel_begin = &kernel_begin;
     system.kernel_end = &kernel_end;
@@ -257,4 +295,6 @@ void init_system_info() {
     printk("mem lower %uKB upper %uKB\n", boot_params.mem_lower >> 10, boot_params.mem_upper >> 10);
 
     boot_delay(DEFAULT_BOOT_DELAY_TICKS);
+
+    lapic_init();
 }
index 0d43837441dbaf386f4eff3f18e16c05898e38b2..2e9f7e601edc925cafc39f1e1df818dd3379cd1e 100644 (file)
@@ -45,7 +45,7 @@ main:
 .align 4
 real_kernel_entry:
     # Load GDT's Information To GDTR
-    lgdt    GDTR-KRNLADDR
+    lgdt    boot_gdtr
 
     movw    $0x10, %dx
     movw    %dx,%ds
@@ -54,12 +54,21 @@ real_kernel_entry:
     movw    %dx,%fs
     movw    %dx,%gs
 
-    movl    $(stack + MULTIBOOT_STACK_SIZE - KRNLADDR), %esp
+
+    nop
+    nop
+    nop
+    nop
+    movl    $(stack + MULTIBOOT_STACK_SIZE), %esp
+    #leal stack, %esp
+    #addl MULTIBOOT_STACK_SIZE, %esp
 
     # Reset EFLAGS
     pushl   $0
     popf
 
+    call test_unpaged_break
+
     # Save Multiboot Infomation...
     pushl   %eax
     addl    $KRNLADDR,%ebx
@@ -129,33 +138,38 @@ real_kernel_entry:
 
     jmp     4f
 4:
+    # 准备切保护模式
+    # 此时esp的地址还需要再调整一下
+    addl    $KRNLADDR, %esp
+    ljmp    $0x08,$Label+KRNLADDR
 
-    ljmp    $0x08,$Label
 Label:
-    call    check_kernel
-    addl    $8, %esp
+    leal    check_kernel, %eax
+    call    *%eax
 
     movl    $root_task + TASK_SIZE, %esp
-    call    init_system_info
+    leal    init_system_info, %eax
+    call    *%eax;
 
-    call    setup_kernel
+    leal    setup_kernel, %eax
+    call    *%eax
 
     subl    $128, %esp   // ss esp eip
-    movl    $root_task_entry, %eax
+    leal    root_task_entry, %eax
     jmpl    *%eax
 
-Die:
-    jmp     Die    # Should never come to here.
+die:
+    jmp     die    # Should never come to here.
 
 .align 32
-BootGDT:
+boot_gdt:
 EMPT: .long    0x00000000, 0x00000000
 Code: .long    0x0000FFFF, 0x00CF9B00
 Data: .long    0x0000FFFF, 0x00CF9300
-BootGDTEnd:
-GDTR:
-    GDTRLimit: .word BootGDTEnd-BootGDT
-    GDTRBase:  .long BootGDT-KRNLADDR
+boot_gdt_end:
+boot_gdtr:
+    boot_gdtr_limit: .word boot_gdt_end-boot_gdt
+    boot_gdtr_base:  .long boot_gdt
 
     .comm stack, MULTIBOOT_STACK_SIZE
 
index c5098296f9b6aad71368f9034fb7de1d0809cd66..e36ea99bda9883959f9931ea2a684c11d42ef5d1 100644 (file)
--- a/gdbscript
+++ b/gdbscript
@@ -1,6 +1,12 @@
 # 避免退出gdb时二次确认
 set confirm off
 
+set architecture i386
+
+#b *0x100000
+b multiboot.S:60
+b multiboot.S:136
+
 #b *0x7c00
 
 # watch point
diff --git a/include/cpuid.h b/include/cpuid.h
new file mode 100644 (file)
index 0000000..522ad4c
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: include/cpuid.h
+ *      Author: Zhao Yanbai
+ *              2025-12-27 16:13:55 Saturday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
+
+
+typedef struct cpuid_regs {
+    unsigned long eax, ebx, ecx, edx;
+} cpuid_regs_t;
+
+
+cpuid_regs_t cpuid(unsigned long op);
index 7348d7793be86b1271ee51606627d822bc5a55b1..d312989e749ba219541dbdf0b723098581b71965 100644 (file)
 
 #include <types.h>
 
+#define MSR_IA32_APIC_BASE 0x1B
+
+
+
 #define MSR_SYSENTER_CS 0x174
 #define MSR_SYSENTER_ESP 0x175
 #define MSR_SYSENTER_EIP 0x176
 #define MSR_IA32_PERF_STATUS 0x198
 #define MSR_IA32_PERF_CRTL 0x199
 
+
+// 本地APIC的版本寄存器
+#define MSR_IA32_LOCAL_APIC_VERSION 0x803
+
 #define rdmsr(msr, lowval, highval)                             \
     do {                                                        \
         asm("rdmsr;" : "=a"(lowval), "=d"(highval) : "c"(msr)); \
index e64fc69ce53f797970b2e7c9ff136cb87dce9714..57e1874bf4870c3f619633df8638542e9c2512c1 100644 (file)
 #include <bits.h>
 #include <printk.h>
 #include <string.h>
+#include <cpuid.h>
 
 #define TEST_FEATURE(val, bit, fea)                  \
     do {                                             \
         if (ISSET_BIT(val, bit)) printk(" %s", fea); \
     } while (0);
 
-typedef struct reg {
-    unsigned long eax, ebx, ecx, edx;
-} reg_t;
-reg_t cpuid(unsigned long op) {
-    reg_t r;
+cpuid_regs_t cpuid(unsigned long op) {
+    cpuid_regs_t r;
     asm("cpuid;" : "=a"(r.eax), "=b"(r.ebx), "=c"(r.ecx), "=d"(r.edx) : "a"(op));
 
     return r;
 }
 
 void detect_cpu() {
-    reg_t r;
+    cpuid_regs_t r;
     unsigned short int cpu_sn[6];  // serial number
     int i;
 
@@ -72,6 +70,11 @@ void detect_cpu() {
     r = cpuid(1);
     pn = ((r.ebx & 0x00FF0000) >> 16);
     printk(" x %d Cores\n", pn);
+    if(((r.ecx >> 21) & 0x01) == 1) {
+        printk("x2APIC\n");
+    }
+    printk("ECX %x\n", r.ecx);
+    printk("APIC ID: %x\n", (r.ebx >> 24) & 0xFF);
 
     /**********************Get the CPU's Feature***********************/
     int fv = r.edx;
diff --git a/qemu.sh b/qemu.sh
index f1b5adfec3f8225d2c77b0fffe7182050862f37a..d129fdd501bfde3410f4467cb6544436555bcca1 100755 (executable)
--- a/qemu.sh
+++ b/qemu.sh
@@ -20,6 +20,8 @@ set -m
 qemu-system-i386 \
     -boot d \
     -m 128 \
+    -smp 2 \
+    -cpu qemu32,+x2apic \
     -serial tcp::6666,server,nowait \
     -drive file=hd.img,format=raw,index=0,media=disk \
     -drive file=kernel.iso,index=1,media=cdrom \
@@ -30,6 +32,10 @@ qemu-system-i386 \
     -s -S \
     &
 
+
+    # -cpu qemu32,+apic \
+    # -cpu qemu32,+x2apic \
+    #-cpu core2duo-v1,+apic \
     #-drive file=HDb.IMG,format=raw,index=2,media=disk \
     #-cpu qemu32,+apic \
     #-cpu core2duo-v1,+apic \
@@ -55,4 +61,3 @@ i386-elf-gdb KERNEL.ELF -x gdbscript
 
 kill -9 $pid
 echo "kill pid ${pid}"
-
index 0bf67e706933f244c1a0c8f77a6e310884eded54..36e87a816da7f5dd271eba8505f1515e00736a05 100644 (file)
@@ -27,14 +27,30 @@ kernel_begin = kernel_virtual_addr_start + kernel_loaded_physic_addr;
 
 SECTIONS
 {
-    . = kernel_begin;
-    .text : AT(kernel_loaded_physic_addr) ALIGN(0x1000)
+    . = kernel_loaded_physic_addr;
+    .unpagged_text :
     {
-        code = .;
         *(.kernel_entry_text)
         *(.multiboot2_header)
-        /* 单独把 multiboot.S 的 .text 放在这个位置是为了便于调试,实际是可以不写这一句的 */
         boot/multiboot.S.o(.text)
+        *(.unpaged_text)
+    }
+    eunpagged_text = .;
+    . = ALIGN(0x1000);
+    .unpaged_data :
+    {
+        boot/multiboot.S.o(COMMON)
+       *(.unpaged_data)
+    }
+    eunpagged_data = .;
+
+    /* . = kernel_begin; */
+    . += kernel_virtual_addr_start;
+    . = ALIGN(0x1000);
+    .text : AT(ADDR(.text)-kernel_virtual_addr_start) ALIGN(0x1000)
+    {
+        code = .;
+        /* 单独把 multiboot.S 的 .text 放在这个位置是为了便于调试,实际是可以不写这一句的 */
         *(.text)
         *(.ring3.text);
         *(.sysexit) /* last */