TSS woes
Posted: Tue Mar 01, 2005 10:34 am
Hi forum,
I've been reading this for a long time, but this is my first post. My toy OS is progressing nicely... I have virtual memory and paging set up, a decent console driver, interrupts working, a keyboard driver, and a floppy controller driver working. I'm trying to implement task switching with hardware, and the whole TSS thing giving me fits. I've read the Intel manuals over and over, and I understand the concepts well enough, it's just the implementation that's giving me fits. I was wondering if someone could tell me if I'm on the right track...
I have an initial TSS set up, so the first task switch has some place to store the current state. Then I have function, we'll call it idle(), that just prints a letter to the screen. I create a new TSS, and a descriptor for it, and put the descriptor in the GDT (which already has space allocated in it for it).
The TR register is initialized with the selector for the initial "dummy" TSS. Whenever I do the task switch, by ljmp'ing to the new task's selector, bochs dies, with the message "SS NULL".
My questions:
1. What fields in the TSS do I have to initialize before the first task switch to idle()? I'm leaving the intial TSS pretty much empty, since the CPU will fill it in on the first switch, right? I have the second TSS set up with the address of the idle() func for eip, and the kernel's DS, CS, SS, ES, GS, and FS. What value should I use for esp0? (This is all in the kernel right now, no privelidge level changes). Do I just use the current value of esp? All of my segment registers are base 0, spanning the whole 4 gig address space. I have one descriptor for kernel data, and one for kernel code. (0x10 and 0x8, respectively).
2. About the TSS descriptor. It's base and limit should be set to the location in memory of the TSS, and the exact size of it, correct? Like if my TSS is pointed to be the pointer *t, the base should be t, and the size 104 (or however big it is).
Is this right?
3. The selector I ljmp to is just the index into the GDT times 8, right? For a ring 0 task with no LDT being used anyway, I mean. I'm just saying something like asm("ljmp 0x30"), where 0x30 is the selector for the idle() task's TSS descriptor.
Any help would be appreciated. I think my problem lies somewhere in the descriptor, or in my questionable gcc inline assembly skills, but I wanted to make sure I'm following the right steps, conceptually.
Also, I wanted to say that this board totally rocks and I've learned more in the last month on this board than I could have imagined. You guys are awesome. Thanks in advance!
I've been reading this for a long time, but this is my first post. My toy OS is progressing nicely... I have virtual memory and paging set up, a decent console driver, interrupts working, a keyboard driver, and a floppy controller driver working. I'm trying to implement task switching with hardware, and the whole TSS thing giving me fits. I've read the Intel manuals over and over, and I understand the concepts well enough, it's just the implementation that's giving me fits. I was wondering if someone could tell me if I'm on the right track...
I have an initial TSS set up, so the first task switch has some place to store the current state. Then I have function, we'll call it idle(), that just prints a letter to the screen. I create a new TSS, and a descriptor for it, and put the descriptor in the GDT (which already has space allocated in it for it).
The TR register is initialized with the selector for the initial "dummy" TSS. Whenever I do the task switch, by ljmp'ing to the new task's selector, bochs dies, with the message "SS NULL".
My questions:
1. What fields in the TSS do I have to initialize before the first task switch to idle()? I'm leaving the intial TSS pretty much empty, since the CPU will fill it in on the first switch, right? I have the second TSS set up with the address of the idle() func for eip, and the kernel's DS, CS, SS, ES, GS, and FS. What value should I use for esp0? (This is all in the kernel right now, no privelidge level changes). Do I just use the current value of esp? All of my segment registers are base 0, spanning the whole 4 gig address space. I have one descriptor for kernel data, and one for kernel code. (0x10 and 0x8, respectively).
2. About the TSS descriptor. It's base and limit should be set to the location in memory of the TSS, and the exact size of it, correct? Like if my TSS is pointed to be the pointer *t, the base should be t, and the size 104 (or however big it is).
Is this right?
3. The selector I ljmp to is just the index into the GDT times 8, right? For a ring 0 task with no LDT being used anyway, I mean. I'm just saying something like asm("ljmp 0x30"), where 0x30 is the selector for the idle() task's TSS descriptor.
Any help would be appreciated. I think my problem lies somewhere in the descriptor, or in my questionable gcc inline assembly skills, but I wanted to make sure I'm following the right steps, conceptually.
Also, I wanted to say that this board totally rocks and I've learned more in the last month on this board than I could have imagined. You guys are awesome. Thanks in advance!