TSS problem
Posted: Tue Jan 30, 2018 12:34 pm
I'm trying to switch to ring 3 and implement a TSS, but after i switched interrupts stop working. Even if I use cli to get a general protection fault, nothing happens. What's wrong with my code? The full source code is on https://github.com/MSathieu/Cernel, but I copied here the most important files.
tss.h:
gdt.c:
load_gdt.asm:
usermode.asm:
idt.c:
tss.h:
Code: Select all
#include <stdint.h>
struct tss_table {
uint32_t prev_tss;
uint32_t esp0;
uint32_t ss0;
uint32_t esp1;
uint32_t ss1;
uint32_t esp2;
uint32_t ss2;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint32_t es;
uint32_t cs;
uint32_t ss;
uint32_t ds;
uint32_t fs;
uint32_t gs;
uint32_t ldt;
uint16_t trap;
uint16_t iomap_base;
} __attribute__ ((packed));
struct tss_table tss;
Code: Select all
#include <tss.h>
extern void load_gdt(uint32_t);
extern void load_tss(void);
struct gdt_table {
uint16_t limit;
uint32_t base;
} __attribute__((packed));
struct gdt_entry {
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
} __attribute__((packed));
struct gdt_table gdt;
struct gdt_entry gdt_entry[6];
void add_gdt_segment(int i, uint32_t base, uint32_t limit, uint32_t access, uint32_t granularity) {
gdt_entry[i].base_low = (base & 0xffff);
gdt_entry[i].base_middle = (base >> 16) & 0xff;
gdt_entry[i].base_high = (base >> 24) & 0xff;
gdt_entry[i].limit_low = (limit & 0xffff);
gdt_entry[i].granularity = (limit >> 16) & 0x0f;
gdt_entry[i].granularity |= granularity & 0xf0;
gdt_entry[i].access = access;
}
void setup_tss(void) {
uint32_t base = (uint32_t) &tss;
uint32_t limit = sizeof(tss);
add_gdt_segment(5, base, limit, 0xE9, 0x00);
tss.ss0 = 0x10;
tss.esp0 = 0x0;
}
void setup_gdt(void) {
gdt.limit = sizeof(gdt_entry) * 6 - 1;
gdt.base = (uint32_t) &gdt_entry;
add_gdt_segment(0, 0, 0, 0, 0);
add_gdt_segment(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
add_gdt_segment(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
add_gdt_segment(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
add_gdt_segment(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
setup_tss();
load_gdt((uint32_t) &gdt);
load_tss();
}
Code: Select all
global load_gdt
global load_tss
load_gdt:
mov eax, [esp+4]
lgdt [eax]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush_gdt
flush_gdt:
ret
load_tss:
mov ax, 0x2B
ltr ax
ret
Code: Select all
global jump_to_usermode
jump_to_usermode:
mov ax, 0x23
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push 0x23
push eax
pushf
push 0x1B
push start_usermode
iret
start_usermode:
jmp $
Code: Select all
#include <ioports.h>
extern void load_idt();
extern void int0();
extern void int1();
extern void int2();
extern void int3();
extern void int4();
extern void int5();
extern void int6();
extern void int7();
extern void int8();
extern void int9();
extern void int10();
extern void int11();
extern void int12();
extern void int13();
extern void int14();
extern void int15();
extern void int16();
extern void int17();
extern void int18();
extern void int19();
extern void int20();
extern void int21();
extern void int22();
extern void int23();
extern void int24();
extern void int25();
extern void int26();
extern void int27();
extern void int28();
extern void int29();
extern void int30();
extern void int31();
extern void int32();
extern void int33();
extern void int34();
extern void int35();
extern void int36();
extern void int37();
extern void int38();
extern void int39();
extern void int40();
extern void int41();
extern void int42();
extern void int43();
extern void int44();
extern void int45();
extern void int46();
extern void int47();
struct idt_table {
uint16_t limit;
uint32_t base;
} __attribute__ ((packed));
struct idt_entry {
uint16_t base_low;
uint16_t select;
uint8_t type;
uint8_t flags;
uint16_t base_high;
} __attribute__((packed));
struct idt_entry idt_entry[256];
struct idt_table idt;
void add_idt_segment(int i, uint32_t base) {
idt_entry[i].base_low = (base & 0xFFFF);
idt_entry[i].base_high = (base >> 16) & 0xFFFF;
idt_entry[i].select = 0x08;
idt_entry[i].type = 0;
idt_entry[i].flags = 0x8E;
}
void setup_idt(void) {
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
idt.limit = (sizeof (struct idt_entry) * 256) - 1;
idt.base = (int) idt_entry;
add_idt_segment(0, (uint32_t) int0);
add_idt_segment(1, (uint32_t) int1);
add_idt_segment(2, (uint32_t) int2);
add_idt_segment(3, (uint32_t) int3);
add_idt_segment(4, (uint32_t) int4);
add_idt_segment(5, (uint32_t) int5);
add_idt_segment(6, (uint32_t) int6);
add_idt_segment(7, (uint32_t) int7);
add_idt_segment(8, (uint32_t) int8);
add_idt_segment(9, (uint32_t) int9);
add_idt_segment(10, (uint32_t) int10);
add_idt_segment(11, (uint32_t) int11);
add_idt_segment(12, (uint32_t) int12);
add_idt_segment(13, (uint32_t) int13);
add_idt_segment(14, (uint32_t) int14);
add_idt_segment(15, (uint32_t) int15);
add_idt_segment(16, (uint32_t) int16);
add_idt_segment(17, (uint32_t) int17);
add_idt_segment(18, (uint32_t) int18);
add_idt_segment(19, (uint32_t) int19);
add_idt_segment(20, (uint32_t) int20);
add_idt_segment(21, (uint32_t) int21);
add_idt_segment(22, (uint32_t) int22);
add_idt_segment(23, (uint32_t) int23);
add_idt_segment(24, (uint32_t) int24);
add_idt_segment(25, (uint32_t) int25);
add_idt_segment(26, (uint32_t) int26);
add_idt_segment(27, (uint32_t) int27);
add_idt_segment(28, (uint32_t) int28);
add_idt_segment(29, (uint32_t) int29);
add_idt_segment(30, (uint32_t) int30);
add_idt_segment(31, (uint32_t) int31);
add_idt_segment(32, (uint32_t) int32);
add_idt_segment(33, (uint32_t) int33);
add_idt_segment(34, (uint32_t) int34);
add_idt_segment(35, (uint32_t) int35);
add_idt_segment(36, (uint32_t) int36);
add_idt_segment(37, (uint32_t) int37);
add_idt_segment(38, (uint32_t) int38);
add_idt_segment(39, (uint32_t) int39);
add_idt_segment(40, (uint32_t) int40);
add_idt_segment(41, (uint32_t) int41);
add_idt_segment(42, (uint32_t) int42);
add_idt_segment(43, (uint32_t) int43);
add_idt_segment(44, (uint32_t) int44);
add_idt_segment(45, (uint32_t) int45);
add_idt_segment(46, (uint32_t) int46);
add_idt_segment(47, (uint32_t) int47);
load_idt();
}