diff --git a/kernel/Makefile b/kernel/Makefile index fca951b6..89a586f5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,8 +15,9 @@ all: kernel # cp kernel ../bin/kernel/kernel.elf -kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o syscall.o multiboot2.o +kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o syscall.o multiboot2.o cpu.o ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o exception/8259A.o mm/mm.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \ + common/cpu.o \ -T link.lds head.o: head.S @@ -59,5 +60,8 @@ syscall.o: syscall/syscall.c multiboot2.o: driver/multiboot2/multiboot2.c gcc $(CFLAGS) -c driver/multiboot2/multiboot2.c -o driver/multiboot2/multiboot2.o +cpu.o: common/cpu.c + gcc $(CFLAGS) -c common/cpu.c -o common/cpu.o + clean: rm -rf $(GARBAGE) \ No newline at end of file diff --git a/kernel/common/cpu.c b/kernel/common/cpu.c new file mode 100644 index 00000000..482c3c48 --- /dev/null +++ b/kernel/common/cpu.c @@ -0,0 +1,64 @@ +#include "cpu.h" +#include "kprint.h" +#include "printk.h" + +void cpu_init(void) +{ + // 获取处理器制造商信息 + uint tmp_info[4] = {0}; + cpu_cpuid(0, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); + + // 保存CPU支持的最大cpuid指令主功能号 + Cpu_cpuid_max_Basic_mop = tmp_info[0]; + // 保存制造商名称 + *(uint *)&Cpu_Manufacturer_Name[0] = tmp_info[1]; + *(uint *)&Cpu_Manufacturer_Name[4] = tmp_info[3]; + *(uint *)&Cpu_Manufacturer_Name[8] = tmp_info[2]; + Cpu_Manufacturer_Name[12] = '\0'; + kinfo("CPU manufacturer: %s", Cpu_Manufacturer_Name); + + // 获取处理器型号信息 + int count = 0; + for (uint i = 0x80000002; i < 0x80000005; ++i) + { + cpu_cpuid(i, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); + for (int j = 0; j <= 3; ++j) + { + *(uint *)&Cpu_BrandName[4 * count] = tmp_info[j]; + ++count; + } + } + Cpu_BrandName[48] = '\0'; + + kinfo("CPU Brand Name: %s", Cpu_BrandName); + + // 使用cpuid主功能号0x01进行查询(未保存ebx ecx edx的信息,具体参见白皮书) + cpu_cpuid(1, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); + + // EAX中包含 Version Informatin Type,Family,Model,and Stepping ID + Cpu_Stepping_ID = tmp_info[0] & 0xf; + Cpu_Model_ID = (tmp_info[0]>>4) & 0xf; + Cpu_Family_ID = (tmp_info[0]>>8) & 0xf; + Cpu_Processor_Type = (tmp_info[0]>>12)& 0x3; + // 14-15位保留 + Cpu_Extended_Model_ID = (tmp_info[0]>>16)&0xf; + Cpu_Extended_Family_ID = (tmp_info[0]>>20)&0xff; + //31-25位保留 + kinfo("Family ID=%#03lx\t Extended Family ID=%#03lx\t Processor Type=%#03lx\t",Cpu_Family_ID, Cpu_Extended_Family_ID, Cpu_Processor_Type); + kinfo("Model ID=%#03lx\t Extended Model ID=%#03lx\tStepping ID=%#03lx\t",Cpu_Model_ID, Cpu_Extended_Model_ID,Cpu_Stepping_ID); + + // 使用0x80000008主功能号,查询处理器支持的最大可寻址地址线宽度 + cpu_cpuid(0x80000008, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); + Cpu_max_phys_addrline_size = tmp_info[0]&0xff; + Cpu_max_linear_addrline_size = (tmp_info[0]>>8)&0xff; + + kinfo("Cpu_max_phys_addrline_size = %d", Cpu_max_phys_addrline_size); + kinfo("Cpu_max_linear_addrline_size = %d", Cpu_max_linear_addrline_size); + + cpu_cpuid(0x80000000, 0, &tmp_info[0], &tmp_info[1], &tmp_info[2], &tmp_info[3]); + Cpu_cpuid_max_Extended_mop = tmp_info[0]; + + kinfo("Max basic mop=%#05lx",Cpu_cpuid_max_Basic_mop); + kinfo("Max extended mop=%#05lx",Cpu_cpuid_max_Extended_mop); + return; +} \ No newline at end of file diff --git a/kernel/common/cpu.h b/kernel/common/cpu.h index ace43937..60e369df 100644 --- a/kernel/common/cpu.h +++ b/kernel/common/cpu.h @@ -1,3 +1,55 @@ #pragma once -#define CPU_NUM 8 \ No newline at end of file +#include "glib.h" + +#define CPU_NUM 8 + +// cpu支持的最大cpuid指令的基础主功能号 +uint Cpu_cpuid_max_Basic_mop; +// cpu支持的最大cpuid指令的扩展主功能号 +uint Cpu_cpuid_max_Extended_mop; +// cpu制造商信息 +char Cpu_Manufacturer_Name[17]={0}; +// 处理器名称信息 +char Cpu_BrandName[49] = {0}; +// 处理器家族ID +uint Cpu_Family_ID; +// 处理器扩展家族ID +uint Cpu_Extended_Family_ID; +// 处理器模式ID +uint Cpu_Model_ID; +// 处理器扩展模式ID +uint Cpu_Extended_Model_ID; +// 处理器步进ID +uint Cpu_Stepping_ID; +// 处理器类型 +uint Cpu_Processor_Type; +// 处理器支持的最大物理地址可寻址地址线宽度 +uint Cpu_max_phys_addrline_size; +// 处理器支持的最大线性地址可寻址地址线宽度 +uint Cpu_max_linear_addrline_size; + +/** + * @brief 执行cpuid指令 + * + * @param mop 主功能号 + * @param sop 子功能号 + * @param eax 结果的eax值 + * @param ebx 结果的ebx值 + * @param ecx 结果的ecx值 + * @param edx 结果的edx值 + * + * cpuid指令参考英特尔开发手册卷2A Chapter3 3.2 Instruction + */ +void cpu_cpuid(uint mop, uint sop, uint *eax, uint*ebx, uint*ecx, uint*edx) +{ + // 向eax和ecx分别输入主功能号和子功能号 + // 结果输出到eax, ebx, ecx, edx + __asm__ __volatile__("cpuid \n\t":"=a"(*eax),"=b"(*ebx), "=c"(*ecx), "=d"(*edx):"0"(mop),"2"(sop):"memory"); +} + +/** + * @brief 初始化获取处理器信息模块 + * + */ +void cpu_init(void); diff --git a/kernel/exception/trap.c b/kernel/exception/trap.c index 02dcc215..b2ad0a6b 100644 --- a/kernel/exception/trap.c +++ b/kernel/exception/trap.c @@ -3,7 +3,7 @@ #include "../process/ptrace.h" #include"../common/kprint.h" -void init_sys_vector() +void sys_vector_init() { set_trap_gate(0, 1, divide_error); set_trap_gate(1, 1, debug); diff --git a/kernel/main.c b/kernel/main.c index 5bd4e92a..b74e8e17 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -85,6 +85,8 @@ void system_initialize() // 先初始化系统调用模块 syscall_init(); + cpu_init(); + // 再初始化进程模块。顺序不能调转 process_init(); }