I have the GDT hard-coded in assembly, but with an open (and allocated) space for the TSS entry. It already has the granularity and permission flags set, because those are static:
Code: Select all
section .data
global gdt
gdt:
align 0x1000
dd 0x00000000, 0x00000000
dd 0x0000FFFF, 0x00CF9A00
dd 0x0000FFFF, 0x00CF9200
dd 0x0000FFFF, 0x00CFFA00
dd 0x0000FFFF, 0x00CFF200
dd 0x00000000, 0x0000E900 ; This will become the TSS
Code: Select all
struct tss {
u32int prev_tss;
u32int esp0;
u32int ss0;
u32int unused[15];
u32int es, cs, ss, ds, fs, gs;
u32int ldt;
u16int trap, iomap_base;
} __attribute__ ((packed)) tss;
extern u8int gdt[48];
__attribute__ ((section(".ttext")))
void init_tss() {
u32int base = (u32int) &tss;
u16int limit = sizeof(struct tss);
memclr(&tss, sizeof(struct tss));
tss.ss0 = 0x13;
extern u32int stack;
tss.esp0 = (u32int) &stack;
tss.cs = 0x0B;
tss.es = tss.ds = tss.fs = tss.gs = 0x13;
gdt[40] = (limit >> 8) & 0xFF;
gdt[41] = (limit) & 0xFF;
gdt[42] = (base >> 8) & 0xFF;
gdt[43] = base & 0xFF;
gdt[44] = (base >> 16) & 0xFF;
gdt[47] = (base >> 24) & 0xFF;
extern void tss_flush();
tss_flush();
}
EDIT: Also, the reason that init_tss() is in ELF section ".ttext" is because I have the kernel free all memory used by initialization code and data after it is done booting by lumping init code together. It usually only saves ~5 pages of memory, but who knows when that will come in handy? I also know this is not the part of the problem.
And here is the "tss_flush" function called by that C function:
Code: Select all
global tss_flush
tss_flush:
mov ax, 0x2B
ltr ax
ret
Any help would be appreciated!