Stack Swap
Stack Swap
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
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
Re:Stack Swap
Yes. The user stack pointer gets saved on the ring 0 stack.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 ?
The value that was in the esp0 field in the TSS.HardEnough wrote: so what does esp point to during entrancy of int ????
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: 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 ????? .
Don't bother to set them unless you're going to use hardware task switching.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 ?????
Pax tecum,
Qui te vexat.
Re:Stack Swap
So can tell me how the stack frame looks like during int ?Yes. The user stack pointer gets saved on the ring 0 stack.
assume i'm going to only use software switching.Don't bother to set them unless you're going to use hardware task switching.
what should i set the dpl of descriptor of tss ? 0 or 3 ?
should i set a gate descriptor ?
should i do ltr ?
Re:Stack Swap
It should look like what any kernel/Ring0 stack frame looks like... seperate from the interrupted Ring3 task's stack.HardEnough wrote: So can tell me how the stack frame looks like during int ?
As for the answer to this, use the forum search function... I know this has been answered beforeHardEnough 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 ?
Re:Stack Swap
userssHardEnough wrote: So can tell me how the stack frame looks like during int ?
useresp
eflags
cs
eip <= with current esp pointing here
Zero. I don't understand what you want in the second question.HardEnough wrote: what should i set the dpl of descriptor of tss ? 0 or 3 ?
should i set a gate descriptor ?
Yes. Indeed, you *must* before you plan on using it to supply esp0 and ss0.HardEnough wrote: should i do ltr ?
Pax tecum,
Qui te vexat.
Re:Stack Swap
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.Zero. I don't understand what you want in the second question.
Re:Stack Swap
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.
The process can't know what the CPL is, AFAIK. And it shouldn't need to either.
Re:Stack Swap
To ensure that the multitasking is working (the kernel is at ring 0 while process at ring 3).The process can't know what the CPL is, AFAIK. And it shouldn't need to either.
Another thing how can i change the task's ring from ring 3 to ring 1 or 2 ?? (ring 0 is done by ints)
Re:Stack Swap
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.
Re:Stack Swap
How can do it by ints?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.
DPL/RPL of which descriptor (code or tss) ?
Re:Stack Swap
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
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
Re:Stack Swap
Hi,
Random notes....
To figure out what CPL currently is, you'd need to look at the RPL field of CS:
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
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
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.
- Colonel Kernel
- Member
- Posts: 1437
- Joined: Tue Oct 17, 2006 6:06 pm
- Location: Vancouver, BC, Canada
- Contact:
Re:Stack Swap
I use this technique in my exception handlers to tell whether the kernel itself caused the exception. Linux does this as well, AFAIK.Brendan wrote:Normally this isn't necessary because you can guess what CPL should be depending on how the code is used.
Top three reasons why my OS project died:
- Too much overtime at work
- Got married
- My brain got stuck in an infinite loop while trying to design the memory manager