Page 1 of 1
Problems switching to user mode
Posted: Sun Dec 31, 2006 4:10 pm
by ManOfSteel
Hello,
I'm having problems while trying to switch to user mode. Everything is currently running in kernel mode (ring0).
the system code segment is set up as follows: base=0, limit=0xffff granular, ring 0, non-conforming (ffff.0000.009a.cf00) and the user code segment: base=0, limit=0xffff granular, ring 3, non-conforming (ffff.0000.00fa.cf00).
When I try:
Code: Select all
push dword user_data_selector
mov eax,esp
push eax
push dword 0
push dword user_code_selector
lea eax,[ring3]
push eax
iret
I get: "(mch) iret: Return with DPL != RPL. #GP(selector)"
When code segments are conforming, I get ">>PANIC<< iret: conforming, DPL > cs_selector.RPL"
Any help is appreciated.
Thank you.
Re: Problems switching to user mode
Posted: Sun Dec 31, 2006 5:10 pm
by Brendan
Hi,
The CPL is stored in the lower 2 bits of CS, and the RPL of the stack segment (stored in the lower 2 bits of SS) must match the CPL.
Try this:
Code: Select all
push dword user_data_selector | 0x0003
mov eax,esp
push eax
push dword 0
push dword user_code_selector | 0x0003
lea eax,[ring3]
push eax
iret
Cheers,
Brendan
Posted: Mon Jan 01, 2007 6:06 am
by ManOfSteel
Thank you. I discovered the error this morning.
ds, es, fs, gs and ss now contain 0x33 and cs contains 0x2b. Are they normal values (user code is GDT's 5th entry and data is 6th)?
Posted: Tue Jan 02, 2007 6:27 am
by ManOfSteel
So, are they normal values? Just want to be sure.
Also, interrupts worked fine under ring 0 but now Bochs says ">>PANIC<< interrupt(): SS selector null". So, how can I fix that up?
Posted: Tue Jan 02, 2007 8:10 am
by Combuster
for SS=null: have you set SS0 in the TSS to the correct value
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)
Posted: Wed Jan 03, 2007 2:29 am
by Brendan
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
Posted: Thu Jan 04, 2007 2:48 am
by ManOfSteel
Ok, thanks for the clarifications.
For the SS problem, it seems to be working now.