74 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdint.h>
 | |
| #include <cpu.h>
 | |
| #include <memory.h>
 | |
| 
 | |
| #define GDT_CODE      (3<<11)
 | |
| #define GDT_DPL(lvl)  ((lvl)<<13)
 | |
| #define GDT_PRESENT   (1<<15)
 | |
| #define GDT_LONG      (1<<21)
 | |
| #define GDT_TSS       (1<<8)
 | |
| 
 | |
| struct gdt
 | |
| {
 | |
|   uint32_t addr;
 | |
|   uint32_t flags;
 | |
| }__attribute__((packed));
 | |
| 
 | |
| struct gdtp
 | |
| {
 | |
|   uint16_t len;
 | |
|   struct gdt *gdt;
 | |
| }__attribute__((packed));
 | |
| 
 | |
| struct tss
 | |
| {
 | |
|   uint32_t r1;
 | |
|   uint64_t rsp0;
 | |
|   uint64_t rsp1;
 | |
|   uint64_t rsp2;
 | |
|   uint64_t r2;
 | |
|   uint64_t ist1;
 | |
|   uint64_t ist2;
 | |
|   uint64_t ist3;
 | |
|   uint64_t ist4;
 | |
|   uint64_t ist5;
 | |
|   uint64_t ist6;
 | |
|   uint64_t ist7;
 | |
|   uint64_t r3;
 | |
|   uint16_t r4;
 | |
|   uint16_t io_mba;
 | |
| }__attribute__((packed));
 | |
| 
 | |
| 
 | |
| struct gdt BootGDT[] = {
 | |
|   {0, 0},
 | |
|   {0, GDT_PRESENT | GDT_DPL(0) | GDT_CODE | GDT_LONG},
 | |
|   {0, GDT_PRESENT | GDT_DPL(3) | GDT_CODE | GDT_LONG},
 | |
|   {0, 0},
 | |
|   {0, 0},
 | |
| };
 | |
| 
 | |
| struct gdtp GDTp = {2*8-1, BootGDT};
 | |
| 
 | |
| 
 | |
| void gdt_init(uint64_t *_gdt, void *_tss)
 | |
| {
 | |
|   struct gdt *gdt = (struct gdt *)_gdt;
 | |
|   memcpy(gdt, BootGDT, sizeof(BootGDT));
 | |
| 
 | |
|   uint32_t tss_limit = sizeof(struct tss);
 | |
|   uint64_t tss_base = (uint64_t)_tss;
 | |
|   gdt[3].flags = GDT_PRESENT | GDT_TSS;
 | |
|   gdt[3].flags |= (((tss_base >> 24) & 0xFF) << 24);
 | |
|   gdt[3].flags |= ((tss_base >> 16) & 0xFF);
 | |
|   gdt[3].flags |= (((tss_limit >> 16) & 0xF) << 16);
 | |
|   gdt[3].addr = ((tss_base & 0xFFFF) << 16) | (tss_limit & 0xFFFF);
 | |
|   gdt[4].flags = 0;
 | |
|   gdt[4].addr = ((tss_base >> 32) & 0xFFFF);
 | |
| 
 | |
|   GDTp.len = 5*8 - 1;
 | |
|   GDTp.gdt = gdt;
 | |
| 
 | |
|   load_gdt(&GDTp);
 | |
| }
 |