Stack Swap

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.
HardEnough

Stack Swap

Post by HardEnough »

i know that during interrupt (when cpu moves from dpl3->dpl0) its uses the ss0:esp0 from tss abd use it as stack frame during interrupt, but if the cpu does so then esp on the entry of interrupt isnot pointing to the actual esp of the currently running process, is that's right ?
so what does esp point to during entrancy of int ???? is it the actual stack pointer of the running process or the value of esp0 in tss ?????

another thing how can i setup the initial tss ? i know that i need tss struct and gdt descriptor in gdt, but should i initially set its fields, and also should i set the dpl of its descriptor to dpl0 or dpl3 ????? .
the ds, ss , * segment register entries in tss - if i uses flat memory model - should they point to descriptor with dpl0 or dpl3 ?????

please can any one thankfully answer my question :)

thank you very much
QuiTeVexat

Re:Stack Swap

Post by QuiTeVexat »

HardEnough wrote: but if the cpu does so then esp on the entry of interrupt isnot pointing to the actual esp of the currently running process, is that's right ?
Yes. The user stack pointer gets saved on the ring 0 stack.
HardEnough wrote: so what does esp point to during entrancy of int ????
The value that was in the esp0 field in the TSS.
HardEnough wrote: another thing how can i setup the initial tss ? i know that i need tss struct and gdt descriptor in gdt, but should i initially set its fields, and also should i set the dpl of its descriptor to dpl0 or dpl3 ????? .
Yes, you should initialize it, although you should only need to set ss0 and esp0, unless you intend to use hardware task switching or the port by port IO protection.
HardEnough wrote: the ds, ss , * segment register entries in tss - if i uses flat memory model - should they point to descriptor with dpl0 or dpl3 ?????
Don't bother to set them unless you're going to use hardware task switching.

Pax tecum,
Qui te vexat.
HardEnough

Re:Stack Swap

Post by HardEnough »

Yes. The user stack pointer gets saved on the ring 0 stack.
So can tell me how the stack frame looks like during int ?
Don't bother to set them unless you're going to use hardware task switching.
assume i'm going to only use software switching.
what should i set the dpl of descriptor of tss ? 0 or 3 ?
should i set a gate descriptor ?
should i do ltr ?
DynatOS

Re:Stack Swap

Post by DynatOS »

HardEnough wrote: So can tell me how the stack frame looks like during int ?
It should look like what any kernel/Ring0 stack frame looks like... seperate from the interrupted Ring3 task's stack.
HardEnough wrote: assume i'm going to only use software switching.
what should i set the dpl of descriptor of tss ? 0 or 3 ?
should i set a gate descriptor ?
should i do ltr ?
As for the answer to this, use the forum search function... I know this has been answered before ;)
QuiTeVexat

Re:Stack Swap

Post by QuiTeVexat »

HardEnough wrote: So can tell me how the stack frame looks like during int ?
userss
useresp
eflags
cs
eip <= with current esp pointing here
HardEnough wrote: what should i set the dpl of descriptor of tss ? 0 or 3 ?
should i set a gate descriptor ?
Zero. I don't understand what you want in the second question.
HardEnough wrote: should i do ltr ?
Yes. Indeed, you *must* before you plan on using it to supply esp0 and ss0.

Pax tecum,
Qui te vexat.
HardEnough

Re:Stack Swap

Post by HardEnough »

How can a process know the cpu privilage level it's running at ?
HardEnough

Re:Stack Swap

Post by HardEnough »

Zero. I don't understand what you want in the second question.
I meant what is the privilage level (0 or 3) that i should use in the descriptor DPL bits, where this descriptor is the system descriptor of the tss.
AR

Re:Stack Swap

Post by AR »

The TSS is a segment, it requires a segment descriptor to be placed in the GDT, LTR takes the selector, all of which should be DPL0 since only the kernel modifies the TSS.

The process can't know what the CPL is, AFAIK. And it shouldn't need to either.
HardEnough

Re:Stack Swap

Post by HardEnough »

The process can't know what the CPL is, AFAIK. And it shouldn't need to either.
To ensure that the multitasking is working (the kernel is at ring 0 while process at ring 3).

Another thing how can i change the task's ring from ring 3 to ring 1 or 2 ?? (ring 0 is done by ints)
AR

Re:Stack Swap

Post by AR »

It is generally not really useful to use any rings other than 0 and 3 but interrupts can transition between rings, to run code in the ring you just set the DPL/RPL to Ring X.
HardEnough

Re:Stack Swap

Post by HardEnough »

It is generally not really useful to use any rings other than 0 and 3 but interrupts can transition between rings, to run code in the ring you just set the DPL/RPL to Ring X.
How can do it by ints?
DPL/RPL of which descriptor (code or tss) ?
HardEnough

Re:Stack Swap

Post by HardEnough »

ah i got it, the RPL of the int itself, right ?
JoeKayzA

Re:Stack Swap

Post by JoeKayzA »

The idt-entry for the corresponding interrupt has a reference for a code segment (where the isr is located). When the interrupt is triggered, the cpu will switch to the CPL of this code segment, AFAIK.

The interrupt gate's PL has a different meaning. IIRC, it says from which CPL the interrupt can be triggered - just as with call gates. (I'm not completely sure about the last statement, so please correct me here)

cheers Joe
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Stack Swap

Post by Brendan »

Hi,

Random notes....

To figure out what CPL currently is, you'd need to look at the RPL field of CS:

Code: Select all

   push cs
   pop ax
   and eax,3          ;<- eax = CPL
AFAIK this always works (regardless of what CPL the code is running at, or if conforming code segments are used).

Normally this isn't necessary because you can guess what CPL should be depending on how the code is used.

For a simple check (for the purpose of making sure your multitasking is working), you could try doing "CLI; STI". At CPL=0 this should work fine but you'll get a general protection fault at CPL=3 (assuming your IOPL is set correctly).

Interrupts can cause CPL transitions, but for IRQ handlers and exceptions the CPU ignores the IDT entry's DPL. In this case you'd need to use a conforming code segment (where the IRQ handler or exception handler runs at the same CPL that was interrupted), or use a normal CPL=0 IRQ or exception handler.

Conforming code segments aren't very useful because if CPL=3 code is interrupted then the IRQ or exception handler will also run at CPL=3 (everyone uses normal CPL=0 interrupt handlers).

Because of this you can't have device drivers at CPL=1 containing IRQ handlers that are also at CPL=1 (it would work until CPL=0 code is interrupted and you get a general protection exception). To get around this you'd need IRQ handlers in the kernel at CPL=0 which pass control to the CPL=1 device drivers.

For software interrupts it's a little different - the CPU doesn't allow control to be passed to less privileged code. This means you can have a CPL=0 software interrupt that can be used by any code, but you can't have a CPL=3 software interrupt that is used by CPL=0 code. The same applies to call gates.

It's also possible to have conforming software interrupts, where the interrupt handler runs at the same CPL as the code that is using the software interrupt. In this case CPL must be less than or equal to the interrupt handler's DPL. For e.g. if DPL=2 then code at CPL= 2 or CPL=3 could use the conforming software interrupt, but if code at CPL=1 or CPL=0 tried to use it then it'd cause a general protection fault.

For all privilege level transitions (regardless of the reason), if the CPU is changing to more privileged code then the CPU will get SS:ESP from the TSS (e.g. the SS0:ESP0 field) and the old less privileged SS:ESP will be pushed on the stack. If the CPU is changing to less privileged code, then the less privileged SS:ESP will be popped from stack and the previous more privileged values for SS:ESP will be discarded.

All privilege levels for the stack must match the CPL. For example, if CPL=2 then then descriptor for SS must use DPL=2. This means you can't use the same segment descriptor for all stacks.

Data segment descriptors are different - in general DPL must be numerically equal to or higher than CPL. For example, if the descriptor's DPL=3 then the segment can be used by all code, regardless of what CPL is, or if the descriptor's DPL=1 then code running at CPL=0 and CPL=1 can use it.

All of this was originally intended for a system that uses up to 4 privilege levels to protect different types of code from each other. Most OS's use paging instead (rather than using segmentation only or using segmentation and paging).

For a "flat" paging OS, you'd only need 1 data segment descriptor (DPL=3) that's used by all code. This same data segment descriptor would also be used for CPL=3 SS. Then you'd need a descriptor for CPL=0 SS, a CPL=3 code segment and a CPL=0 code segment. All IRQ and exception handlers should use DPL=0 to prevent CPL=3 code trying to use them with a software interrupt (e.g. trying to pretend a page fault occured with "int 0x0E"). All software interrupts (if any) would have DPL=3 to allow CPL=3 code to use them. For software task switching, you'd need a single TSS and a TSS descriptor with DPL=0 (you do not need a TSS gate descriptor).

This is the "minimum requirements" to get a "flat" paging OS to work. You may or may not want other segments for other things (like using the protected mode interfaces for VBE or APM, or using FS or GS to point to a specific kernel data structure).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Stack Swap

Post by Colonel Kernel »

Brendan wrote:Normally this isn't necessary because you can guess what CPL should be depending on how the code is used.
I use this technique in my exception handlers to tell whether the kernel itself caused the exception. Linux does this as well, AFAIK.
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
Post Reply