i have a failure() function that halts the processor so I used it for debugging. Before I loaded the TSS, everything worked fine. I found out the reboot happens AFTER the load - DIRECTLY after. Here's all code required:
init_gdt()
Code: Select all
static void init_gdt()
{
gdt_pointer.limit = (sizeof(struct gdt_entry) * 5) - 1;
gdt_pointer.base = (u32int)&gdt_entries;
gdt_set_gate(0, 0, 0, 0, 0); // Null segment
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment
write_tss(5, 0x10, 0);
gdt_flush((u32int)&gdt_pointer);
tss_flush();
failure("Force stop after TSS load");
};
Code: Select all
static void write_tss(s32int num, u16int ss0, u32int esp0)
{
u32int base = (u32int) &tss;
u32int limit = base + sizeof(struct tss_entry);
gdt_set_gate(num, base, limit, 0xE9, 0x00);
memset(&tss, 0, sizeof(struct tss_entry));
tss.ss0 = ss0;
tss.esp0 = esp0;
}
Code: Select all
[GLOBAL tss_flush]
tss_flush:
mov ax, 0x2B ; TSS index
ltr ax
ret
Code: Select all
struct tss_entry
{
u32int link; // Unused
u32int esp0; // Kernel stack pointer (loaded on task-switch)
u32int ss0; // Kernel stack segment (0x10, u32int to avoid the resv. 16-bit high word)
u32int esp1; // Unused....
u32int ss1;
u32int esp2;
u32int ss2;
u32int cr3;
u32int eip;
u32int eflags;
u32int eax;
u32int ecx;
u32int edx;
u32int ebx;
u32int esp;
u32int ebp;
u32int esi;
u32int edi;
u32int es;
u32int cs;
u32int ss;
u32int ds;
u32int fs;
u32int gs;
u32int ldtr;
u16int iopb; // Please do not use this value, because no programs will have access to I/O ports directly
u16int resv;
} __attribute__ ((packed));
P.S. failure() did not halt - there was a reboot. That means the problem happens directly after the load. Please note, that without KVM, the system crashes instead of reboots.