.align 32
.global ap_code32_entry_address
-ap_code32_entry_address: .long ap_code32_entry - ap_realmode_base # 在BSP复制代码后会动态调整
+ap_code32_entry_address: .long ap_code32_entry # 在BSP复制代码后会动态调整
.word 0x0008, 0x0000
+# 下面的定义会一鱼两吃 [也会复制两份]:
+# 1. 在实模式式下用一次 [只不过BSP复制到1MB以下的内存会稍作调整]
+# 2. 在保护模式下用一次 [因为加载了最终的页目录就无法以一一映射的方式访问这段实模式内存]
.align 32
+.global ap_gdtr
.global ap_gdtr_base
ap_gdtr:
ap_gdtr_limit: .word ap_gdt_end-ap_gdt
- ap_gdtr_base: .long ap_gdt - ap_realmode_base # 在BSP复制代码后会动态调整
+ ap_gdtr_base: .long ap_gdt # 在BSP复制代码后会动态调整
+
+# 此处定义8个GDT项, 参考ap.c里的AP_GDT_CNT
.align 32
+.global ap_gdt
ap_gdt:
-empty: .long 0x00000000, 0x00000000
-code_desc: .long 0x0000FFFF, 0x00CF9B00
-data_desc: .long 0x0000FFFF, 0x00CF9300
-pad0: .long 0x00000000, 0x00000000
-pad1: .long 0x00000000, 0x00000000
-pad2: .long 0x00000000, 0x00000000
+empty: .long 0x00000000, 0x00000000
+ap_code: .long 0x0000FFFF, 0x00CF9B00
+ap_data: .long 0x0000FFFF, 0x00CF9300
+ap_tss: .long 0x00000000, 0x00000000
+pad0: .long 0x00000000, 0x00000000
+pad1: .long 0x00000000, 0x00000000
+pad2: .long 0x00000000, 0x00000000
+pad3: .long 0x00000000, 0x00000000
ap_gdt_end:
ap_boot_end:
*/
#include <multiboot2.h>
+#include <linkage.h>
// 启用FB这个功能,需要修改grub.cfg,添加如下内容
// load_video
// terminal_output gfxterm
#define ENABLE_FB 0
-#define ALIGN8 __attribute__((aligned(8)))
-
typedef struct ALIGN8 multiboot2_elf_header {
ALIGN8 struct multiboot_header header;
#if ENABLE_FB
#endif
#define __initdata __attribute__((__section__(".init.data")))
+
+#define ALIGN8 __attribute__((__aligned__(8)))
+#define ALIGN4 __attribute__((__aligned__(4)))
unsigned char DB : 1; // 0--16bits,1--32bits
unsigned char G : 1; // set to 1. We just need 4K size.
unsigned char baseH;
-} Seg, *pSeg;
+} seg_t;
//-------------------------------------------------------------------------
// TSS State,LDT
unsigned short eaddrH;
-} Gate, *pGate;
+} gate_t;
// just used for type...
typedef union {
- Seg seg;
- Gate gate;
-} Desc, *pDesc;
+ seg_t seg;
+ gate_t gate;
+} desc_t;
-#define NGDT 256
+#define NGDT 16
#define NIDT 256
-#define NLDT 5
-extern Desc idt[NIDT];
-extern Desc gdt[NGDT];
+
+extern desc_t idt[NIDT];
+extern desc_t gdt[NGDT];
//-------------------------------------------------------------------------
// Define Gate Types...
#define TRAP_GATE 0x0F // Keep 'IF' bit.
#define TSS_DESC 0x09
-static inline void _init_desc(pDesc desc) {
- memset((char*)desc, 0, sizeof(Desc));
+static inline void _init_desc(desc_t* desc) {
+ memset((void*)desc, 0, sizeof(desc_t));
}
-static inline Desc _create_seg(u8 type, u8 DPL) {
- Desc d;
- pSeg p = &d.seg;
+static inline desc_t _create_seg(u8 type, u8 DPL) {
+ desc_t d;
+ seg_t* p = &d.seg;
_init_desc(&d);
p->limitL = 0xFFFF;
return d;
}
-static inline Desc _create_gate(u32 handler, u8 type, u8 DPL) {
- Desc d;
- pGate p = &d.gate;
+static inline desc_t _create_gate(u32 handler, u8 type, u8 DPL) {
+ desc_t d;
+ gate_t* p = &d.gate;
_init_desc(&d);
u16 gs, _gs;
u16 ldt, _ldt;
u16 T : 1, _T : 15, iomap_base;
-} TSS_t;
+} tss_t;
-extern TSS_t tss;
+extern tss_t tss;
// CR0 含有控制处理器操作模式和状态的系统控制标志
#define CR0_PE (1 << 0) // R/W Protection Enabled
*/
#include <page.h>
+#include <types.h>
+#include <system.h>
+#include <processor.h>
+#include <linkage.h>
extern pde_t* ap_pre_pgd;
+#define AP_GDT_CNT 8
+#define AP_IDT_CNT 256
+
+desc_t ALIGN8 ap_idt[AP_IDT_CNT];
+uint8_t ALIGN8 ap_idtr[6];
+
+#define AP_CS_SELECTOR 0x08
+#define AP_DS_SELECTOR 0x10
+
+static inline desc_t _create_ap_gate(u32 handler, u8 type, u8 DPL) {
+ desc_t d;
+ gate_t* p = &d.gate;
+
+ _init_desc(&d);
+
+ p->eaddrL = 0xFFFF & handler;
+ p->eaddrH = 0xFFFF & (handler >> 16);
+ p->selector = AP_CS_SELECTOR;
+ p->type = type;
+ p->P = 0x1;
+ p->DPL = DPL;
+
+ return d;
+}
+
+static inline void set_ap_idt_gate(u32 vec, u32 handler, u8 type, u8 DPL) {
+ ap_idt[vec] = _create_ap_gate(handler, type, DPL);
+}
+
+#define set_ap_sys_int(vect, type, DPL, handler) \
+ do { \
+ void handler(); \
+ set_ap_idt_gate(vect, (u32)handler, type, DPL); \
+ } while (0)
+
void ap_kernel_entry() {
// 虽然ap_pre_pgd只做了一下跳板页目录看起来很可惜
// 不过可以把它拿来个AP的栈用
asm("mov %0, %%esp" : : "r"(pa2va(&ap_pre_pgd) + PAGE_SIZE));
+
+ // 进入内核空间后要加载原来已经在内核空间的ap_gdt
+ // 之前加载的被复制到1MB以下的ap_gdt需要废弃,因为它已经在内核地址空间之外了
+ // 虽然他们是同一个ap_gdt
+ extern char ap_gdtr;
+ asm("lgdt ap_gdtr");
+
+ // tss
+ // AP 暂时不服务用户特权级 所以暂时用不到tss
+
+ //
+ set_ap_sys_int(0x00, TRAP_GATE, PRIVILEGE_KRNL, APDivideError);
+ set_ap_sys_int(0x01, TRAP_GATE, PRIVILEGE_KRNL, APDebug);
+ set_ap_sys_int(0x02, INTR_GATE, PRIVILEGE_KRNL, APNMI);
+ set_ap_sys_int(0x03, TRAP_GATE, PRIVILEGE_USER, APBreakPoint);
+ set_ap_sys_int(0x04, TRAP_GATE, PRIVILEGE_USER, APOverFlow);
+ set_ap_sys_int(0x05, TRAP_GATE, PRIVILEGE_USER, APBoundsCheck);
+ set_ap_sys_int(0x06, TRAP_GATE, PRIVILEGE_KRNL, APInvalidOpcode);
+ set_ap_sys_int(0x07, TRAP_GATE, PRIVILEGE_KRNL, APDeviceNotAvailable);
+ set_ap_sys_int(0x08, TRAP_GATE, PRIVILEGE_KRNL, APDoubleFault);
+ set_ap_sys_int(0x09, TRAP_GATE, PRIVILEGE_KRNL, APCoprocSegOverRun);
+ set_ap_sys_int(0x0A, TRAP_GATE, PRIVILEGE_KRNL, APInvalidTss);
+ set_ap_sys_int(0x0B, TRAP_GATE, PRIVILEGE_KRNL, APSegNotPresent);
+ set_ap_sys_int(0x0C, TRAP_GATE, PRIVILEGE_KRNL, APStackFault);
+ set_ap_sys_int(0x0D, TRAP_GATE, PRIVILEGE_KRNL, APGeneralProtection);
+ set_ap_sys_int(0x0E, TRAP_GATE, PRIVILEGE_KRNL, APPageFault);
+ set_ap_sys_int(0x10, TRAP_GATE, PRIVILEGE_KRNL, APCoprocError);
+
+ // idt gates
+ for (int i = 0x11; i < 0x20; i++) {
+ set_ap_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, ap_no_irq_handler);
+ }
+
+ // irq gates
+ for (int i = 0x20; i < 256; i++) {
+ set_ap_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, ap_no_irq_handler);
+ }
+
+ // 加载 ap_idtr
+ *((unsigned short*)ap_idtr) = AP_IDT_CNT * sizeof(gate_t);
+ *((unsigned long*)(ap_idtr + 2)) = (unsigned long)ap_idt;
+ asm volatile("lidt ap_idtr");
+
+ asm("int $0x28");
+
while (1) {
asm("nop;");
+ asm("int $0x28");
}
}
+
+void do_ap_no_irq_handler() {
+ // do nothing
+ // printk("AP no irq handler\n");
+ uint8_t* p = (uint8_t*)0xC00B8000;
+ *p = *p == ' ' ? 'K' : ' ';
+}
extern char ap_boot_end;
uint32_t bytes = &ap_boot_end - &ap_boot_bgn;
- for(int i=0; i<bytes; i++) {
+ for (int i = 0; i < bytes; i++) {
((uint8_t*)paddr)[i] = ((uint8_t*)&ap_boot_bgn)[i];
}
extern uint8_t ap_code32_entry_address;
extern uint8_t ap_gdtr_base;
- uint32_t *dst = 0;
+ uint32_t* dst = 0;
//
- dst = (uint32_t *)(paddr + (uint32_t)(&ap_code32_entry_address) - (uint32_t)(&ap_boot_bgn));
+ dst = (uint32_t*)(paddr + (uint32_t)(&ap_code32_entry_address) - (uint32_t)(&ap_boot_bgn));
+ (*dst) -= (uint32_t)(&ap_boot_bgn);
(*dst) += (paddr - KERNEL_VADDR_BASE);
//
- dst = (uint32_t *)(paddr + (uint32_t)(&ap_gdtr_base) - (uint32_t)(&ap_boot_bgn));
+ dst = (uint32_t*)(paddr + (uint32_t)(&ap_gdtr_base) - (uint32_t)(&ap_boot_bgn));
+ (*dst) -= (uint32_t)(&ap_boot_bgn);
(*dst) += (paddr - KERNEL_VADDR_BASE);
}
*/
#define NOERRCODE(name) \
EC_ENTRY(name) \
- pushl $0; \
+ pushl $0; \
EC_CALLDO(name)
#define ERRORCODE(name) \
ERRORCODE (GeneralProtection)
ERRORCODE (_page_fault)
NOERRCODE (CoprocError)
+
+
+
+
+
+NOERRCODE (APDivideError)
+NOERRCODE (APDebug)
+NOERRCODE (APNMI)
+NOERRCODE (APBreakPoint)
+NOERRCODE (APOverFlow)
+NOERRCODE (APBoundsCheck)
+NOERRCODE (APInvalidOpcode)
+NOERRCODE (APDeviceNotAvailable)
+NOERRCODE (APDoubleFault)
+NOERRCODE (APCoprocSegOverRun)
+ERRORCODE (APInvalidTss)
+ERRORCODE (APSegNotPresent)
+ERRORCODE (APStackFault)
+ERRORCODE (APGeneralProtection)
+ERRORCODE (APPageFault)
+NOERRCODE (APCoprocError)
void doCoprocError(pt_regs_t regs) {
DIE_MSG();
}
+
+// TODO 把printk换掉
+#define AP_DIE_MSG() \
+ do { \
+ printk("AP Unsupport Now...[%s]\n", __FUNCTION__); \
+ printk("EFLAGS:%08x CS:%02x EIP:%08x ERRCODE:%x", regs.eflags, regs.cs, regs.eip, regs.errcode); \
+ asm("cli;hlt;"); \
+ } while (0);
+
+void doAPDivideError(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPDebug(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPNMI(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPBreakPoint(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPOverFlow(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPBoundsCheck(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPInvalidOpcode(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPDeviceNotAvailable(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPDoubleFault(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPCoprocSegOverRun(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPInvalidTss(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPSegNotPresent(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPStackFault(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+void doAPGeneralProtection(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+
+void doAPPageFault(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
+
+void doAPCoprocError(pt_regs_t regs) {
+ AP_DIE_MSG();
+}
_boot_kbd_irq_handler:
push $0x01;
jmp _boot_irq_handler
+
+
+
+.global ap_no_irq_handler
+ap_no_irq_handler:
+ SAVE_REGS
+
+ call do_ap_no_irq_handler
+
+ RESTORE_REGS
+ iret
#include <string.h>
#include <syscall.h>
#include <system.h>
+#include <linkage.h>
System system;
-TSS_t tss;
-Desc idt[NIDT] __attribute__((__aligned__(8)));
-Desc gdt[NGDT] __attribute__((__aligned__(8)));
-char gdtr[6] __attribute__((__aligned__(4)));
-char idtr[6] __attribute__((__aligned__(4)));
+tss_t tss;
-extern char _gdtr[6];
-extern char _idtr[6];
+desc_t ALIGN8 idt[NIDT];
+desc_t ALIGN8 gdt[NGDT];
+
+char ALIGN4 gdtr[6];
+char ALIGN4 idtr[6];
volatile int reenter = -1;
void setup_gdt() {
- pDesc pdesc;
+ desc_t* pdesc;
// change to new gdt.
asm volatile("sgdt gdtr");
// 复制旧的GDT
memcpy(gdt, (void*)pa2va(*((uint32_t*)(gdtr + 2))), *((uint16_t*)(gdtr + 0)));
- *((unsigned short*)gdtr) = NGDT * sizeof(Desc);
+ *((unsigned short*)gdtr) = NGDT * sizeof(desc_t);
*((unsigned long*)(gdtr + 2)) = (unsigned long)gdt;
asm volatile("lgdt gdtr");
- memcpy(gdt + INDEX_UCODE, gdt + INDEX_KCODE, sizeof(Desc));
- memcpy(gdt + INDEX_UDATA, gdt + INDEX_KDATA, sizeof(Desc));
+ memcpy(gdt + INDEX_UCODE, gdt + INDEX_KCODE, sizeof(desc_t));
+ memcpy(gdt + INDEX_UDATA, gdt + INDEX_KDATA, sizeof(desc_t));
pdesc = gdt + INDEX_UCODE;
pdesc->seg.DPL = 3;
pdesc = gdt + INDEX_UDATA;
// 通过中断门进入中断服务程序CPU会自动将中断关闭,也就是将EFLAGS的IF位清0
// 通过陷阱门进入服务程序时则维持IF标志位不变
void setup_idt() {
- *((unsigned short*)idtr) = NIDT * sizeof(Gate);
+ *((unsigned short*)idtr) = NIDT * sizeof(gate_t);
*((unsigned long*)(idtr + 2)) = (unsigned long)idt;
asm volatile("lidt idtr");
}
}
void set_tss_gate(u32 vec, u32 addr, u32 limit) {
- pSeg p = (pSeg)(gdt + vec);
- _init_desc((pDesc)p);
+ seg_t* p = (seg_t*)(gdt + vec);
+ _init_desc((desc_t*)p);
p->limitL = 0xFFFF & limit;
p->limitH = 0x0F & (limit >> 16);
p->baseL = 0xFFFF & addr;
}
void set_tss() {
- TSS_t* p = &tss;
- memset((void*)p, sizeof(TSS_t), 0);
+ tss_t* p = &tss;
+ memset((void*)p, 0, sizeof(tss_t));
p->esp0 = 0; // delay to init root_task
p->ss0 = SELECTOR_KRNL_DS;
p->ss = SELECTOR_KRNL_DS;
p->ds = SELECTOR_KRNL_DS;
p->cs = SELECTOR_KRNL_CS;
p->eflags = 0x1200;
- p->iomap_base = sizeof(TSS_t);
+ p->iomap_base = sizeof(tss_t);
- // tss的iomap_base=sizeof(TSS_t) > TSS_GATE.LIMIT - 1
+ // tss的iomap_base=sizeof(tss_t) > TSS_GATE.LIMIT - 1
// 因此表示没有I/O位图
- set_tss_gate(INDEX_TSS, (u32)p, sizeof(TSS_t));
+ set_tss_gate(INDEX_TSS, (u32)p, sizeof(tss_t));
asm("ltr %%ax" ::"a"((INDEX_TSS << 3) + 3));
}