Problems switching to user mode

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.
Post Reply
User avatar
ManOfSteel
Member
Member
Posts: 60
Joined: Tue Feb 01, 2005 12:00 am

Problems switching to user mode

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Problems switching to user mode

Post 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
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
ManOfSteel
Member
Member
Posts: 60
Joined: Tue Feb 01, 2005 12:00 am

Post 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)?
User avatar
ManOfSteel
Member
Member
Posts: 60
Joined: Tue Feb 01, 2005 12:00 am

Post 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?
User avatar
Combuster
Member
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:

Post 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)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post 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
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
ManOfSteel
Member
Member
Posts: 60
Joined: Tue Feb 01, 2005 12:00 am

Post by ManOfSteel »

Ok, thanks for the clarifications.
For the SS problem, it seems to be working now.
Post Reply