Hi,
Combuster wrote:as for the entry numbers: thats entirely up to you. i use 0x1b and 0x23 for userspace selectors, and 0x8 and 0x10 for the kernel (mainly to support syscall)
Depending on your OS design, it's possible to use the same data segment descriptors for CPL=0 and CPL=3. The last version of my OS did this - DS and ES were constants (base = zero, limit = 4 GB) that never changed, FS was set to point to the kernel's CPU data structure and never changed (CPL=3 code couldn't use FS though). GS wasn't used and was set to NULL.
The idea is that the OS never does any (slow) data segment register loads. There are some corner cases that need to have some work-arounds - for e.g. there's nothing to prevent (faulty) CPL=3 code from setting FS or GS to the same value as DS. In this case when my kernel tried using FS it'd cause a page fault (because the CPU data structure was less than 4 KB, and the first 4 KB of all address spaces is "not present"), where the page fault handler would detect this and reset FS to it's correct value.
To write a 32-bit OS that can support both SYSENTER and SYSCALL, use the following order:
- Start+0, System code segment
Start+8, System data/stack segment
Start+16, User code segment
Start+24, User data/stack segment
To write a 64-bit OS that can support both SYSENTER and SYSCALL, I'd use the following order:
- Start+0, 64-bit system code segment
Start+8, 64-bit system data/stack segment
Start+16, 32-bit user code segment
Start+24, 32-bit user data/stack segment (also used for 64-bit stack when SYSRET is used)
Start+32, 64-bit user code segment (for 64-bit user code only)
Start+40, 64-bit user data segment (for SYSEXIT only)
This means that due to differences between SYSEXIT and SYSRET, the OS needs to be designed to handle different values for SS in 64-bit user mode (which is unlikely to be a problem anyway).
Cheers,
Brendan