*.lock
*.DS_Store
.vscode/settings.json
+.vscode/*
*.iso
**/serial_monitor/serial_monitor
**/mkrootfs/mkrootfs
initfs
rootfs
**/init
+
#include <page.h>
#include <string.h>
#include <system.h>
+#include <msr.h>
+
struct boot_params boot_params __attribute__((aligned(32)));
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;
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();
}
.align 4
real_kernel_entry:
# Load GDT's Information To GDTR
- lgdt GDTR-KRNLADDR
+ lgdt boot_gdtr
movw $0x10, %dx
movw %dx,%ds
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
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
# 避免退出gdb时二次确认
set confirm off
+set architecture i386
+
+#b *0x100000
+b multiboot.S:60
+b multiboot.S:136
+
#b *0x7c00
# watch point
--- /dev/null
+/*
+ * ------------------------------------------------------------------------
+ * 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);
#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)); \
#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;
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;
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 \
-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 \
kill -9 $pid
echo "kill pid ${pid}"
-
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 */