What should I actually set ESP0 to in my TSS entry?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
j4cobgarby
Member
Member
Posts: 64
Joined: Fri Jan 26, 2018 11:43 am

What should I actually set ESP0 to in my TSS entry?

Post by j4cobgarby »

I'm probably going to have only one TSS entry since I don't think my operating will be supporting multiple processors, and I'm going to implement software multitasking. I've set up the TSS descriptor in my GDT, and now I'm actually defining the TSS entry itself. I've set SS0 to 2, since that's the GDT entry for my kernel data, but I can't work out what to set ESP0 to. I know it's supposed to be the kernel's stack pointer, but that of course will not be a constant value. So, do I have to update this value in the TSS entry whenever I change from kernel mode to userspace mode?

(A related but less important question I have, which I'll probably put as a seperate thread if it doesn't get answered here, is: why do I need a TSS at all if I'm implementing software task switching? I don't see the purpose of it.)

Thanks!
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: What should I actually set ESP0 to in my TSS entry?

Post by alexfru »

j4cobgarby wrote:I've set SS0 to 2, since that's the GDT entry for my kernel data
I doubt it is. 2 is effectively a NULL selector. See the bit layout in selectors.
j4cobgarby wrote:but I can't work out what to set ESP0 to. I know it's supposed to be the kernel's stack pointer, but that of course will not be a constant value. So, do I have to update this value in the TSS entry whenever I change from kernel mode to userspace mode?

(A related but less important question I have, which I'll probably put as a seperate thread if it doesn't get answered here, is: why do I need a TSS at all if I'm implementing software task switching? I don't see the purpose of it.)
There are two main reasons for having a TSS:
  • hardware-assisted task switching
  • switching between privilege levels/rings
When there's a transition to a higher privilege level/ring (lower CPL), SS:ESP is pulled from the TSS.
If you're already in ring 0, there's no any more privileged level (-1?), so, everything keeps using the current SS:ESP (all exception and interrupt handlers).
But if ring 3 code needs to go to ring 0 to handle an exception or hardware interrupt, then SS0:ESP0 is used.
You typically should set SS0:ESP0 to point to the end of the buffer for interrupt/exception handlers to use as their stack.

Read the CPU manual.
j4cobgarby
Member
Member
Posts: 64
Joined: Fri Jan 26, 2018 11:43 am

Re: What should I actually set ESP0 to in my TSS entry?

Post by j4cobgarby »

alexfru wrote:
j4cobgarby wrote:I've set SS0 to 2, since that's the GDT entry for my kernel data
I doubt it is. 2 is effectively a NULL selector. See the bit layout in selectors.
j4cobgarby wrote:but I can't work out what to set ESP0 to. I know it's supposed to be the kernel's stack pointer, but that of course will not be a constant value. So, do I have to update this value in the TSS entry whenever I change from kernel mode to userspace mode?

(A related but less important question I have, which I'll probably put as a seperate thread if it doesn't get answered here, is: why do I need a TSS at all if I'm implementing software task switching? I don't see the purpose of it.)
There are two main reasons for having a TSS:
  • hardware-assisted task switching
  • switching between privilege levels/rings
When there's a transition to a higher privilege level/ring (lower CPL), SS:ESP is pulled from the TSS.
If you're already in ring 0, there's no any more privileged level (-1?), so, everything keeps using the current SS:ESP (all exception and interrupt handlers).
But if ring 3 code needs to go to ring 0 to handle an exception or hardware interrupt, then SS0:ESP0 is used.
You typically should set SS0:ESP0 to point to the end of the buffer for interrupt/exception handlers to use as their stack.

Read the CPU manual.
Okay got it, thanks! I tried reading the manual and got some information from it, but I find it difficult to find exact pieces of information I'm looking for.
j4cobgarby
Member
Member
Posts: 64
Joined: Fri Jan 26, 2018 11:43 am

Re: What should I actually set ESP0 to in my TSS entry?

Post by j4cobgarby »

alexfru wrote:
j4cobgarby wrote:I've set SS0 to 2, since that's the GDT entry for my kernel data
I doubt it is. 2 is effectively a NULL selector. See the bit layout in selectors.
j4cobgarby wrote:but I can't work out what to set ESP0 to. I know it's supposed to be the kernel's stack pointer, but that of course will not be a constant value. So, do I have to update this value in the TSS entry whenever I change from kernel mode to userspace mode?

(A related but less important question I have, which I'll probably put as a seperate thread if it doesn't get answered here, is: why do I need a TSS at all if I'm implementing software task switching? I don't see the purpose of it.)
There are two main reasons for having a TSS:
  • hardware-assisted task switching
  • switching between privilege levels/rings
When there's a transition to a higher privilege level/ring (lower CPL), SS:ESP is pulled from the TSS.
If you're already in ring 0, there's no any more privileged level (-1?), so, everything keeps using the current SS:ESP (all exception and interrupt handlers).
But if ring 3 code needs to go to ring 0 to handle an exception or hardware interrupt, then SS0:ESP0 is used.
You typically should set SS0:ESP0 to point to the end of the buffer for interrupt/exception handlers to use as their stack.

Read the CPU manual.
Another quick clarification, when you say I should set SS0:ESP0 to the end of the buffer, by buffer do you mean the kernel's stack memory?
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Re: What should I actually set ESP0 to in my TSS entry?

Post by JAAman »

you are making it harder than it needs to be:

ESP0 rarely needs to change (and never outside of task switching)

ESP does change as you use the stack... but when in ring3, the kernel stack isn't being used


think about this:
when the ring0 code returns to ring3, where is ESP?

of course it must be in exactly the same place it was when it first started, because that is where the CPU stored the return information!

therefore, ESP0 never changes, because ESP0 is not in use, and thus never changes, while in ring3, and when returning to ring3 it is always in the same place it was when switching from ring3 to ring0

a simple way to think about it:
the stack is for temporary local storage, therefore, when kernel code isn't running, it is always empty



there is only 1 exception to this:
when you switch threads within a single process, most OSes create a kernel stack for each thread, placing all of them at different addresses in the same address space, therefore, if you follow this system you must patch ESP0 when switching threads, otherwise the thread might overwrite the in-use stack from another thread in the same address space
Post Reply