Intel Manual Questions
Intel Manual Questions
...
Thanks everyone,
Lster
Thanks everyone,
Lster
Last edited by Lprogster on Tue Oct 23, 2007 11:05 am, edited 1 time in total.
#PF is an exception, specifically the page fault exception (number 14). When an exception is triggered (jn pmode), the processor looks up the exception handler in the IDT. The exact mechanism is described in 3A:5.12.1. Certain exceptions, however, have what is called an error code. Specifically, these are numbers 8, 10, 11, 12, 13, 14 and 17.Lprogster wrote:1. What is the idea with #PF(0) and #PF(fault code)? What do they represent - I found the intel manual a bit unclear...
When an exception with an error code is triggered, then the last thing pushed onto the stack is the error code (after the return EIP). Your exception handlers for the exceptions described above need to expect this error code to be there, the others need to assume it isn't there.
In the case of the page fault exception, the error code is used in conjunction with the cr2 register. The CR2 register contains the address that, in trying to be accessed, triggered the page fault. The error code describes whether the fault was by a PL3 or PL0 task, whether it was a read or a write and certain other bits. See 3A:5.15 - Interrupt 14.
#PF(0) means trigger a page fault, push 0x00000000 as the error code.
Generally not, although some people do use them and I have no problem with that. Segmentation is pretty much obsolete in 64-bit long mode, however.Lprogster wrote:2. LDTs aren't used generally any more are they? Are TSSs used in software task-switching?
In software task switching you need a single TSS. When an interrupt or exception is triggered in PL3 (user mode) and the IDT points to a PL0 interrupt handler, then the processor needs to switch its stack from the user process one to one in PL0 for the interrupt handler. It gets the values for SS and ESP from the current TSS. The fields it gets them from are ss0 and esp0 respectively. See 3A:5.12.1 again.
To create a TSS you need to fill out the structure in memory (actually, you only need to set ss0 and esp0 for software task switching), create an entry in the gdt for it (hint, set the system segment flag - see 3A:3.5 - you need a '32-bit TSS (available)'. Then, move the segment selector for the TSS to ax and execute a 'LTR ax' command to set the current TSS.
Only code segments can be conforming.Lprogster wrote:3. What is a conforming segment?
Non-conforming segments cannot be accessed directly from a less privileged segment (i.e. numerically higher - PL3 cannot access a PL0 non-conforming segment through a JMP or CALL) unless it is through a call gate, task gate or interrupt handler. On the other hand you can directly access a PL0 conforming code segment from PL3, although execution continues at CPL3.
You cannot, however, directly jump to either a conforming or non-conforming code segment at a lower privilege level, i.e. your kernel cannot JMP to PL3 code directly, you need to use another means, typically IRET.
See 3A:3.4.5.1.
Regards,
John.
1. PF is just a page fault. It is called when the code that is running does something like accessing a not present page. You can look in 5-15 in the system programming guide for more information on the page fault. PF(0) is just the notation used to say that the error code for the page fault is 0 since all page faults push an error code on the stack.
2.a No I don't think that many people use LDTs anymore. Most people just set their GDTs to reference all memory and use paging for protection.
2.b One TSS is used per processor in software task switching. The only fields that need to be filled out usually are the ss0 and esp0 fields. These values are used when the processor switches from a less privileged code segment to a more privileged code segment though a call gate or interrupt for example.
3. This is all I can say about conforming code segments. I have never used them myself:
[quote]
Code segments can be either conforming or nonconforming. A transfer of execution
into a more-privileged conforming segment allows execution to continue at the
current privilege level. A transfer into a nonconforming segment at a different privilege
level results in a general-protection exception (#GP), unless a call gate or task
gate is used (see Section 4.8.1, “Direct Calls or Jumps to Code Segmentsâ€
2.a No I don't think that many people use LDTs anymore. Most people just set their GDTs to reference all memory and use paging for protection.
2.b One TSS is used per processor in software task switching. The only fields that need to be filled out usually are the ss0 and esp0 fields. These values are used when the processor switches from a less privileged code segment to a more privileged code segment though a call gate or interrupt for example.
3. This is all I can say about conforming code segments. I have never used them myself:
[quote]
Code segments can be either conforming or nonconforming. A transfer of execution
into a more-privileged conforming segment allows execution to continue at the
current privilege level. A transfer into a nonconforming segment at a different privilege
level results in a general-protection exception (#GP), unless a call gate or task
gate is used (see Section 4.8.1, “Direct Calls or Jumps to Code Segmentsâ€
Yes, the user/supervisor bit in a page table entry merely defines access rights for that page - whether currently running code can access it depends on the CPL.Lprogster wrote:When using paging, are segments still used to determine the PL of the current application?
The CPL is almost always equal to the DPL of the current code segment. The only time when this is not the case is when a less privileged piece of code executes code in a higher privilege conforming code segment, when the CPL is not changed and therefore remains that of the less privileged segment.
Regards,
John.
Segments are of two types, either code/data segments or system segments. If S is clear (unlike what I said aboveLprogster wrote:1. (In 3.4.5.1) Could you explain the S flag - I found the intel manual a bit confusing here...
![Embarassed :oops:](./images/smilies/icon_redface.gif)
System segments are described in 3A:3.5, they include TSS segments (of which you'll need one). Code/data segments are described in 3A:3.4.5.1 - just copy the type nibble from the docs for the particular segment you wish.
The D/B flag tells the processor what type of code or data to expect in a segment. If you set it for a code segment, then it expects 32-bit code (e.g. references to ax actually refer to eax), such as the code produced by gcc. If it is clear for a code segment, then the processor expects 16-bit code such that references to ax do point to ax - if you want to use eax from a 16-bit pmode code segment you need to use a register size prefix, which is described (I think) at the start of the second volume (the assembly bit).Lprogster wrote:2. (Also in 3.4.5.1) I really don't understand the D/ B flag. It appears that I should just set it (to 1) and forget about it - would this be OK or will I need to use it for more advance things?
For a stack segment, setting D/B means that calls to push, pop and the like will increment/decrement ESP, whereas if it is clear, then they increment/decrement SP. D/B also has relevance for expand-down segments, but I doubt you use them.
Regards,
John.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Close. A selectors RPL is made up by the lowest two bits of that selector value. This includes code selectors(yes you can use a CS with different values for RPL/CPL and DPL). Since a segment selector contains separate fields for descriptor index and RPL you can mix them at will. That includes having two selectors pointing to the same descriptor with different RPLs.The RPL is the first two bits of a segment register (except cs?). Does that mean there can be many different RPLs at once? (for example: ds = 11h and es = 12h.)
In addition to checking segment limits, the processor also checks descriptor table
limits. The GDTR and IDTR registers contain 16-bit limit values that the processor
uses to prevent programs from selecting a segment descriptors outside the respec-
tive descriptor tables. The LDTR and task registers contain 32-bit segment limit value
(read from the segment descriptors for the current LDT and TSS, respectively). The
processor uses these segment limits to prevent accesses beyond the bounds of the
current LDT and TSS. See Section 3.5.1, “Segment Descriptor Tables,â€