]> Zhao Yanbai Git Server - kernel.git/commitdiff
测试Local APIC寄存器的内存地址映射取值方法
authoracevest <zhaoyanbai@126.com>
Sun, 28 Dec 2025 13:40:56 +0000 (21:40 +0800)
committeracevest <zhaoyanbai@126.com>
Sun, 28 Dec 2025 13:40:56 +0000 (21:40 +0800)
boot/acpi.c
boot/boot.c
gdbscript
kernel/apic.c [new file with mode: 0644]
kernel/setup.c
mm/page.c
qemu.sh
scripts/serial_monitor/main.go

index a401d46cd88ab16b2ed2ef2da1e0c8f8486df605..cbe87272c975a8e9daa3743f393e4be5ba8c5e95 100644 (file)
@@ -131,12 +131,6 @@ void parse_rsdt(void *addr) {
         return;
     }
 
-    // unsigned long ddd = 0xFEC00000;
-    // while(ddd < 0xFF000000)  {
-    //     page_map((void*)ddd, (void*)ddd, PAGE_P);
-    //     ddd += 0x1000;
-    // }
-
     page_map(addr, addr, PAGE_P | PAGE_WR);
 
     rsdt_t *rsdt = (rsdt_t *)addr;
index 900b5343aa642ef5af716bde3d0cc0c6253f0f31..a1dfb90271ddaf20ff17513e24d83025c9d8f523 100644 (file)
@@ -16,8 +16,6 @@
 #include <page.h>
 #include <string.h>
 #include <system.h>
-#include <msr.h>
-#include <cpuid.h>
 #include <elf.h>
 
 struct boot_params boot_params __attribute__((aligned(32)));
@@ -286,42 +284,6 @@ void check_kernel(unsigned long addr, unsigned long magic) {
 #endif
 }
 
-
-void for_breakpoint() {
-
-}
-
-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);
-
-    uint64_t apic_version = read_msr(MSR_IA32_X2APIC_VERSION);
-    printk("apic version: %08lx\n", apic_version);
-
-    for_breakpoint();
-}
-
-
 extern void *kernel_begin;
 extern void *kernel_end;
 extern void *bootmem_bitmap_begin;
@@ -339,7 +301,4 @@ 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 e9bf67faeb259e621770a42369f41c20e8e16f4d..06a6b20f80d73417b644b618781558259c0409ca 100644 (file)
--- a/gdbscript
+++ b/gdbscript
@@ -3,7 +3,8 @@ set confirm off
 
 set architecture i386
 
-b main
+#b acpi.c:144
+#b main
 #b boot_paging
 #b *0x100000
 
diff --git a/kernel/apic.c b/kernel/apic.c
new file mode 100644 (file)
index 0000000..c23a3b2
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: apic.c
+ *      Author: Zhao Yanbai
+ *              2025-12-28 20:52:47 Sunday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include <msr.h>
+#include <cpuid.h>
+#include <system.h>
+
+ 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);
+
+
+    // apic 必然已经开启
+    assert((apic_base & (1 << 11)) != 0);
+
+    // 开启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);
+
+    uint64_t apic_version = read_msr(MSR_IA32_X2APIC_VERSION);
+    printk("apic version: %08lx\n", apic_version);
+
+
+    unsigned long apic_phys_base_addr = apic_base & 0xFFFFF000;
+    unsigned long apic_virt_base_addr = apic_phys_base_addr;
+    #if 0
+    unsigned long ddd = 0xFEC00000;
+    while(ddd < 0xFF000000)  {
+        page_map((void*)ddd, (void*)ddd, PAGE_P);
+        ddd += 0x1000;
+    }
+    #endif
+    page_map((void*)apic_virt_base_addr, (void*)apic_phys_base_addr, PAGE_P);
+
+    {
+        volatile uint32_t *base = (volatile uint32_t *)apic_virt_base_addr;
+        uint32_t id = base[0x20/4]; // APIC ID 偏移
+        uint32_t version = base[0x30/4];
+        printk("APIC id %08x version %08x\n", id, version);
+    }
+
+}
+
+
+void init_apic() {
+    lapic_init();
+}
index 5d18f830c380af29eb44c68ecd1ac5909ab24e08..70689f18947fe7d36354ce986b2ea42926a4e679 100644 (file)
@@ -91,8 +91,13 @@ void setup_kernel() {
 
     init_buffer();
 
+    #if 1
     parse_rsdt(system.rsdt_addr);
 
+    void init_apic();
+    init_apic();
+    #endif
+
     void init_mount();
     init_mount();
 
index 311a5daeacb7940368a693bc889c6016ae14f3b9..deb5210e48e30336a7c4c4556eadf61429632b94 100644 (file)
--- a/mm/page.c
+++ b/mm/page.c
@@ -159,4 +159,15 @@ void page_map(void *vaddr, void *paddr, uint32_t flags) {
 
     // 页表指向物理地址
     pgt[npte] = PAGE_ALIGN(paddr) | flags;
+
+
+    asm volatile("invlpg (%0)" : : "r"(vaddr));
+
+    uint32_t cr3 = 0;
+    asm("mov %%cr3, %0" : "=r"(cr3));
+
+    asm("nop;nop;nop;");
+
+    asm("mov %0, %%cr3" : : "r"(cr3));
+    // asm volatile("mov %0, %%cr3" : : "r"(pgd_pyhs_addr));
 }
diff --git a/qemu.sh b/qemu.sh
index 1f611818ab2cc602aab62dcfcf8739da45f7449a..456d4761e5c13eea7879e42e5bc1a1b1b86d4a74 100755 (executable)
--- a/qemu.sh
+++ b/qemu.sh
@@ -25,6 +25,9 @@ qemu-system-i386 \
     -serial tcp::6666,server,nowait \
     -drive file=hd.img,format=raw,index=0,media=disk \
     -drive file=kernel.iso,index=1,media=cdrom \
+    -drive file=sata.img,format=raw,if=none,id=sata-disk \
+    -device ahci,id=ahci0 \
+    -device ide-hd,drive=sata-disk,bus=ahci0.0 \
     -name kernel \
     -vga std \
     -display cocoa \
@@ -34,6 +37,8 @@ qemu-system-i386 \
 
     # nc -U /tmp/qemu-monitor.sock
 
+    # -d int,cpu_reset \
+
     # -machine pc-q35-9.2  \
     # -cpu qemu32,+apic \
     # -cpu qemu32,+x2apic \
@@ -42,6 +47,9 @@ qemu-system-i386 \
     #-cpu qemu32,+apic \
     #-cpu core2duo-v1,+apic \
 
+    # -serial file:serial_output.log \
+    # -serial tcp::6666,server,nowait \
+
 pid=$!
 echo "pid is ${pid}"
 
index 67bdd2851c7a1311518738a91e52fa60f893dde2..679c2574b97c5d46a5bd25966de69393fc124835 100644 (file)
@@ -11,23 +11,44 @@ import (
 )
 
 var addr string
+var logFile string
+var clearMode bool
 
 func main() {
        flag.StringVar(&addr, "a", ":6666", "")
+       flag.StringVar(&logFile, "f", "last.log", "")
+       flag.BoolVar(&clearMode, "c", true, "clear log file every time")
        flag.Parse()
 
+       // 创建一个可写的文本文件
+       f, err := os.Create(logFile)
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer f.Close()
+
        for {
-               log.Printf("addr %v", addr)
-               monitor()
+               var modeStr string
+               if clearMode {
+                       modeStr = "clear log file every time"
+               } else {
+                       modeStr = "do not clear log file"
+               }
+               log.Printf("listen addr %v log file %v %v", addr, logFile, modeStr)
+
+               monitor(f)
+
+
        }
 }
 
-func monitor() {
+func monitor(f *os.File) {
        var conn net.Conn
        var err error
 
        start := time.Now()
 
+
        // 不断尝试连接串行控制台
        for {
                conn, err = net.Dial("tcp", addr)
@@ -35,19 +56,43 @@ func monitor() {
                        log.Printf("\nconnected...\n")
                        break
                } else {
-                       fmt.Printf("\r\033[Kwait %d seconds", int(time.Now().Sub(start).Seconds()))
+                       fmt.Printf("\r\033[Kwait %d seconds", int(time.Since(start).Seconds()))
                        time.Sleep(500 * time.Millisecond)
                }
        }
 
        defer conn.Close()
 
+
+
+       // 每次连接成功,就清空这个文件,从头开始写数据
+       if clearMode {
+               err = f.Truncate(0)
+               if err != nil {
+                       log.Fatal(err)
+               }
+
+               f.Seek(0, 0)
+       }
+
+       // 写入当前时间
+       f.WriteString("\n\n")
+       _, err = f.WriteString(time.Now().Format("2006-01-02 15:04:05.000") + "\n")
+       if err != nil {
+               log.Fatal(err)
+       }
+       f.WriteString("\n\n")
+
        end := make(chan bool, 0)
 
        // 将串行控制台的输出发送到屏幕
        go func() {
-               _, _ = io.Copy(os.Stdout, conn)
-               log.Printf("qemu -> stdout end\n")
+               // 将conn的输出复制到os.Stdout和f
+               _, err = io.Copy(io.MultiWriter(os.Stdout, f), conn)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               fmt.Printf("qemu -> stdout end\n")
                end <- true
        }()