Ver Fonte

:bug: 暂时解决了由于时钟中断导致#DF的问题(用的华强北方法...以后再fix)

fslongjin há 2 anos atrás
pai
commit
a62454587e
5 ficheiros alterados com 173 adições e 35 exclusões
  1. 3 3
      bochsrc
  2. 26 0
      bx_enh_dbg.ini
  3. 94 19
      kernel/driver/interrupt/apic/apic.c
  4. 48 11
      kernel/exception/gate.h
  5. 2 2
      run.sh

+ 3 - 3
bochsrc

@@ -1,7 +1,7 @@
 # configuration file generated by Bochs
 plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, iodebug=1
 config_interface: textconfig
-# display_library: x11
+display_library: x, options="gui_debug"
 #memory: host=2048, guest=2048
 romimage: file="/usr/local/share/bochs/BIOS-bochs-latest"
 vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest"
@@ -21,7 +21,7 @@ ata3: enabled=0
 pci: enabled=1, chipset=i440fx
 vga: extension=vbe, update_freq=5
 
-cpu: count=1:1:1, ips=4000000, quantum=16, model=corei7_haswell_4770, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0, msrs="msrs.def"
+cpu: count=1:2:2, ips=4000000, quantum=16, model=corei7_haswell_4770, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0, msrs="msrs.def"
 
 cpuid: x86_64=1,level=6, mmx=1, sep=1, simd=avx512, aes=1, movbe=1, xsave=1,apic=x2apic,sha=1,movbe=1,adx=1,xsaveopt=1,avx_f16c=1,avx_fma=1,bmi=bmi2,1g_pages=1,pcid=1,fsgsbase=1,smep=1,smap=1,mwait=1,vmx=1
 cpuid: family=6, model=0x1a, stepping=5, vendor_string="GenuineIntel", brand_string="Intel(R) Core(TM) i7-4770 CPU (Haswell)"
@@ -36,7 +36,7 @@ clock: sync=none, time0=local, rtc_sync=0
 # no loader
 log: -
 logprefix: %t%e%d
-debug: action=ignore
+debug: action=ignore#, cpu0=report
 info: action=report
 error: action=report
 panic: action=ask

+ 26 - 0
bx_enh_dbg.ini

@@ -0,0 +1,26 @@
+# bx_enh_dbg_ini
+SeeReg[0] = TRUE
+SeeReg[1] = TRUE
+SeeReg[2] = TRUE
+SeeReg[3] = TRUE
+SeeReg[4] = FALSE
+SeeReg[5] = FALSE
+SeeReg[6] = FALSE
+SeeReg[7] = FALSE
+SingleCPU = FALSE
+ShowIOWindows = TRUE
+ShowButtons = TRUE
+SeeRegColors = TRUE
+ignoreNxtT = TRUE
+ignSSDisasm = TRUE
+UprCase = 0
+DumpInAsciiMode = 3
+isLittleEndian = TRUE
+DefaultAsmLines = 512
+DumpWSIndex = 0
+DockOrder = 0x123
+ListWidthPix[0] = 486
+ListWidthPix[1] = 663
+ListWidthPix[2] = 771
+MainWindow = 0, 0, 1291, 500
+FontName = Normal

+ 94 - 19
kernel/driver/interrupt/apic/apic.c

@@ -29,7 +29,6 @@ void apic_io_apic_init()
 
     kdebug("MADT->local intr controller addr=%#018lx", madt->Local_Interrupt_Controller_Address);
     kdebug("MADT->length= %d bytes", madt->header.Length);
-
     // 寻找io apic的ICS
     void *ent = (void *)(madt_addr) + sizeof(struct acpi_Multiple_APIC_Description_Table_t);
     struct apic_Interrupt_Controller_Structure_header_t *header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
@@ -53,6 +52,7 @@ void apic_io_apic_init()
     apic_ioapic_map.virtual_data_addr = (uint *)(APIC_IO_APIC_VIRT_BASE_ADDR + 0x10);
     apic_ioapic_map.virtual_EOI_addr = (uint *)(APIC_IO_APIC_VIRT_BASE_ADDR + 0x40);
 
+    kdebug("(ul)apic_ioapic_map.virtual_index_addr=%#018lx", (ul)apic_ioapic_map.virtual_index_addr);
     // 填写页表,完成地址映射
     mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
 
@@ -127,20 +127,74 @@ void apic_init_ap_core_local_apic()
         kinfo("xAPIC & x2APIC enabled!");
     // 设置SVR寄存器,开启local APIC、禁止EOI广播
 
-    __asm__ __volatile__("movq $0x80f, %%rcx    \n\t"
-                         "rdmsr  \n\t"
-                         "bts $8, %%rax  \n\t"
-                         "bts $12, %%rax \n\t"
-                         "movq $0x80f, %%rcx    \n\t"
-                         "wrmsr  \n\t"
-                         "movq $0x80f , %%rcx   \n\t"
-                         "rdmsr \n\t"
-                         : "=a"(eax), "=d"(edx)::"memory", "rcx");
+    // enable SVR[8]
+    __asm__ __volatile__("movq 	$0x80f,	%%rcx	\n\t"
+                         "rdmsr	\n\t"
+                         "bts	$8,	%%rax	\n\t"
+                         //				"bts	$12,	%%rax\n\t"
+                         "wrmsr	\n\t"
+                         "movq 	$0x80f,	%%rcx	\n\t"
+                         "rdmsr	\n\t"
+                         : "=a"(eax), "=d"(edx)
+                         :
+                         : "memory");
 
     if (eax & 0x100)
-        kinfo("APIC Software Enabled.");
-    if (eax & 0x1000)
-        kinfo("EOI-Broadcast Suppression Enabled.");
+        printk_color(RED, YELLOW, "SVR[8] enabled\n");
+    if (edx & 0x1000)
+        printk_color(RED, YELLOW, "SVR[12] enabled\n");
+
+    // get local APIC ID
+    __asm__ __volatile__("movq $0x802,	%%rcx	\n\t"
+                         "rdmsr	\n\t"
+                         : "=a"(eax), "=d"(edx)
+                         :
+                         : "memory");
+
+    printk_color(RED, YELLOW, "x2APIC ID:%#010x\n", eax);
+
+    // 由于尚未配置LVT对应的处理程序,因此先屏蔽所有的LVT
+
+    // mask all LVT
+    __asm__ __volatile__(             //"movq 	$0x82f,	%%rcx	\n\t"	//CMCI
+                                      //"wrmsr	\n\t"
+        "movq 	$0x832,	%%rcx	\n\t" // Timer
+        "wrmsr	\n\t"
+        "movq 	$0x833,	%%rcx	\n\t" // Thermal Monitor
+        "wrmsr	\n\t"
+        "movq 	$0x834,	%%rcx	\n\t" // Performance Counter
+        "wrmsr	\n\t"
+        "movq 	$0x835,	%%rcx	\n\t" // LINT0
+        "wrmsr	\n\t"
+        "movq 	$0x836,	%%rcx	\n\t" // LINT1
+        "wrmsr	\n\t"
+        "movq 	$0x837,	%%rcx	\n\t" // Error
+        "wrmsr	\n\t"
+        :
+        : "a"(0x10000), "d"(0x00)
+        : "memory");
+
+    /*
+    io_mfence();
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI) = 0x1000000;
+    io_mfence();
+    kdebug("cmci = %#018lx", *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI));
+    */
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER) = 0x10000;
+    io_mfence();
+    /*
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL) = 0x1000000;
+    io_mfence();
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) = 0x1000000;
+    io_mfence();
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0) = 0x1000000;
+    io_mfence();
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1) = 0x1000000;
+    io_mfence();
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR) = 0x1000000;
+    io_mfence();
+    */
+    kdebug("All LVT Masked");
 }
 /**
  * @brief 初始化local apic
@@ -219,7 +273,7 @@ void apic_local_apic_init()
                          "wrmsr  \n\t"
                          "movq $0x80f , %%rcx   \n\t"
                          "rdmsr \n\t"
-                         : "=a"(eax), "=d"(edx)::"memory", "rcx");
+                         : "=a"(eax), "=d"(edx)::"memory");
 
     /*
    //enable SVR[8]
@@ -297,8 +351,10 @@ void apic_local_apic_init()
     *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI) = 0x1000000;
     io_mfence();
     kdebug("cmci = %#018lx", *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI));
-    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER) = 0x1000000;
+    */
+    *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER) = 0x10000;
     io_mfence();
+    /*
     *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL) = 0x1000000;
     io_mfence();
     *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) = 0x1000000;
@@ -333,14 +389,30 @@ void apic_local_apic_init()
  */
 void apic_init()
 {
-    // 初始化中断门, 中断使用第二个ist
-    for (int i = 32; i <= 55; ++i)
-        set_intr_gate(i, 2, interrupt_table[i - 32]);
 
+    
+        // 初始化主芯片
+        io_out8(0x20, 0x11);    // 初始化主芯片的icw1
+        io_out8(0x21, 0x20);    // 设置主芯片的中断向量号为0x20(0x20-0x27)
+        io_out8(0x21, 0x04);    // 设置int2端口级联从芯片
+        io_out8(0x21, 0x01);    // 设置为AEOI模式、FNM、无缓冲
+
+        // 初始化从芯片
+        io_out8(0xa0, 0x11);
+        io_out8(0xa1, 0x28);    // 设置从芯片的中断向量号为0x28(0x28-0x2f)
+        io_out8(0xa1, 0x02);    // 设置从芯片连接到主芯片的int2
+        io_out8(0xa1, 0x01);
     // 屏蔽类8259A芯片
-    io_out8(0x21, 0xff);
+    io_mfence();
     io_out8(0xa1, 0xff);
+    io_mfence();
+    io_out8(0x21, 0xff);
+    io_mfence();
+
     kdebug("8259A Masked.");
+    // 初始化中断门, 中断使用第二个ist
+    for (int i = 32; i <= 55; ++i)
+        set_intr_gate(i, 2, interrupt_table[i - 32]);
 
     // enable IMCR
     io_out8(0x22, 0x70);
@@ -349,7 +421,10 @@ void apic_init()
     apic_local_apic_init();
 
     apic_io_apic_init();
+    kdebug("vvvvv");
+
     sti();
+    kdebug("qqqqq");
 }
 /**
  * @brief 中断服务程序

+ 48 - 11
kernel/exception/gate.h

@@ -6,7 +6,10 @@
  *
  */
 
-#pragma once
+#ifndef __GATE_H__
+#define __GATE_H__
+
+#include "../common/kprint.h"
 
 //描述符表的结构体
 struct desc_struct
@@ -55,11 +58,36 @@ void set_gate(ul *gate_selector_addr, ul attr, unsigned char ist, ul *code_addr)
     *(gate_selector_addr + 1) = __d1;
 }
 
+#define _set_gate(gate_selector_addr, attr, ist, code_addr)                                                 \
+    do                                                                                                      \
+    {                                                                                                       \
+        unsigned long __d0, __d1;                                                                           \
+        __asm__ __volatile__("movw	%%dx,	%%ax	\n\t"                                                         \
+                             "andq	$0x7,	%%rcx	\n\t"                                                        \
+                             "addq	%4,	%%rcx	\n\t"                                                          \
+                             "shlq	$32,	%%rcx	\n\t"                                                         \
+                             "addq	%%rcx,	%%rax	\n\t"                                                       \
+                             "xorq	%%rcx,	%%rcx	\n\t"                                                       \
+                             "movl	%%edx,	%%ecx	\n\t"                                                       \
+                             "shrq	$16,	%%rcx	\n\t"                                                         \
+                             "shlq	$48,	%%rcx	\n\t"                                                         \
+                             "addq	%%rcx,	%%rax	\n\t"                                                       \
+                             "movq	%%rax,	%0	\n\t"                                                          \
+                             "shrq	$32,	%%rdx	\n\t"                                                         \
+                             "movq	%%rdx,	%1	\n\t"                                                          \
+                             : "=m"(*((unsigned long *)(gate_selector_addr))),                              \
+                               "=m"(*(1 + (unsigned long *)(gate_selector_addr))), "=&a"(__d0), "=&d"(__d1) \
+                             : "i"(attr << 8),                                                              \
+                               "3"((unsigned long *)(code_addr)), "2"(0x8 << 16), "c"(ist)                  \
+                             : "memory");                                                                   \
+    } while (0)
+
 void set_tss_descriptor(unsigned int n, void *addr)
 {
 
-    *(unsigned long *)(GDT_Table + n) = (103UL & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | (((unsigned long)addr >> 16 & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((103UL >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute
-    *(unsigned long *)(GDT_Table + n + 1) = ((unsigned long)addr >> 32 & 0xffffffff) | 0;
+    unsigned long limit = 103;
+    *(unsigned long *)(&GDT_Table[n]) = (limit & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | ((((unsigned long)addr >> 16) & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((limit >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute
+    *(unsigned long *)(&GDT_Table[n + 1]) = (((unsigned long)addr >> 32) & 0xffffffff) | 0;
 }
 
 /**
@@ -67,10 +95,10 @@ void set_tss_descriptor(unsigned int n, void *addr)
  * @param n TSS基地址在GDT中的第几项
  * 左移3位的原因是GDT每项占8字节
  */
-#define load_TR(n)                                      \
-    do                                                  \
-    {                                                   \
-        __asm__ __volatile__("ltr %%ax" ::"a"((n)<< 3)); \
+#define load_TR(n)                                        \
+    do                                                    \
+    {                                                     \
+        __asm__ __volatile__("ltr %%ax" ::"a"((n) << 3)); \
     } while (0)
 
 /**
@@ -82,7 +110,8 @@ void set_tss_descriptor(unsigned int n, void *addr)
  */
 void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
 {
-    set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(&addr)); // p=1,DPL=0, type=E
+    _set_gate((IDT_Table + n), 0x8E, ist, addr); // p=1,DPL=0, type=E
+    // set_gate((ul *)(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1,DPL=0, type=E
 }
 
 /**
@@ -94,7 +123,10 @@ void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
  */
 void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
 {
-    set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(&addr)); // p=1,DPL=0, type=F
+    // kdebug("addr=%#018lx", (ul)(addr));
+
+    // set_gate((ul *)(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1,DPL=0, type=F
+    _set_gate((IDT_Table + n), 0x8F, ist, addr); // p=1,DPL=0, type=F
 }
 
 /**
@@ -106,7 +138,10 @@ void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
  */
 void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr)
 {
-    set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(&addr)); // p=1,DPL=3, type=F
+    // kdebug("addr=%#018lx", (ul)(addr));
+
+    // set_gate((ul *)(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1,DPL=3, type=F
+    _set_gate((IDT_Table + n), 0xEF, ist, addr); // p=1,DPL=3, type=F
 }
 
 /**
@@ -126,4 +161,6 @@ void set_TSS64(ul rsp0, ul rsp1, ul rsp2, ul ist1, ul ist2, ul ist3, ul ist4, ul
     *(ul *)(TSS64_Table + 17) = ist5;
     *(ul *)(TSS64_Table + 19) = ist6;
     *(ul *)(TSS64_Table + 21) = ist7;
-}
+}
+
+#endif

+ 2 - 2
run.sh

@@ -12,7 +12,7 @@ if [ ! "$1" == "--nobuild" ]; then
     make clean
 fi
 
-IA32_USE_QEMU=1
+IA32_USE_QEMU=0
 bochsrc="./bochsrc"
 ARCH="x86_64"
 
@@ -93,7 +93,7 @@ if [ $flag_can_run -eq 1 ]; then
         bochs -q -f ${bochsrc} -rc ./tools/bochsinit
     else
         qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \
-        -monitor stdio -d cpu_reset,guest_errors -s -S -cpu IvyBridge --enable-kvm \
+        -monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu IvyBridge --enable-kvm \
         -drive id=disk,file=bin/disk.img,if=none \
         -device ahci,id=ahci \
         -device ide-hd,drive=disk,bus=ahci.0    \