From: acevest Date: Sun, 28 Dec 2025 13:40:56 +0000 (+0800) Subject: 测试Local APIC寄存器的内存地址映射取值方法 X-Git-Url: http://repos.zhaoyanbai.com/?a=commitdiff_plain;h=f45fd32f177a90b7e38850cb9e3212346a4fb6b7;p=kernel.git 测试Local APIC寄存器的内存地址映射取值方法 --- diff --git a/boot/acpi.c b/boot/acpi.c index a401d46..cbe8727 100644 --- a/boot/acpi.c +++ b/boot/acpi.c @@ -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; diff --git a/boot/boot.c b/boot/boot.c index 900b534..a1dfb90 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include 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(); } diff --git a/gdbscript b/gdbscript index e9bf67f..06a6b20 100644 --- 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 index 0000000..c23a3b2 --- /dev/null +++ b/kernel/apic.c @@ -0,0 +1,69 @@ +/* + * ------------------------------------------------------------------------ + * File Name: apic.c + * Author: Zhao Yanbai + * 2025-12-28 20:52:47 Sunday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include + + 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(); +} diff --git a/kernel/setup.c b/kernel/setup.c index 5d18f83..70689f1 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -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(); diff --git a/mm/page.c b/mm/page.c index 311a5da..deb5210 100644 --- 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 1f61181..456d476 100755 --- 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}" diff --git a/scripts/serial_monitor/main.go b/scripts/serial_monitor/main.go index 67bdd28..679c257 100644 --- a/scripts/serial_monitor/main.go +++ b/scripts/serial_monitor/main.go @@ -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 }()