How to enter userspace

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
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

How to enter userspace

Post by austanss »

I've been working on my kernel for a bit now, and I really want to enter userspace.

I have a few functions down, and I believe my OS would last... at least a reasonable amount of time in userspace.

So, I know in order for me to return to ring 0 from ring 3, I need a TSS.

I don't plan on doing that quite yet, I just want to get into userspace.

I know I need entries in my GDT for user code/data. I don't know what the entries should look like, or differ from the kernel entries, or what order the GDT needs to be laid out in.

And then finally, what do I do to officiate my entry into userspace?
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: How to enter userspace

Post by AndrewAPrice »

rizxt wrote:So, I know in order for me to return to ring 0 from ring 3, I need a TSS.

I don't plan on doing that quite yet, I just want to get into userspace.
You probably want a way to syscall back into the kernel unless you map 0xb8000 to usermode. Are you in protected mode or long mode?

I found the TSS straight foward to work with in long mode. The most difficult part is splitting up the TSS's address + size to write it into the GDT. The only thing you'd need in the actual TSS right now is the stack pointer to use for when you enter an interrupt. But, I don't know if you actually need a TSS if you keep interrupts disabled.
rizxt wrote:I know I need entries in my GDT for user code/data. I don't know what the entries should look like, or differ from the kernel entries, or what order the GDT needs to be laid out in.
This is for long mode. I have 5 segments in my GDT (kernel + userspace, code + data), and a reference to the TSS.

Code: Select all

[GLOBAL Gdt64]
Gdt64:
	; Invalid segment
	DQ 0x0000000000000000 ; 0x0
	; Kernel code: RW, executable, code/data segment, present, 64-bit, ring 0
	DQ 0x00209A0000000000 ; 0x8
	; Kernel data: RW, data, code/data segment, present, ring 0
	DQ 0x0000920000000000 ; 0x10
	; User data: RW, data, code/data segment, present, ring 3
	DQ 0x0020F20000000000 ; 0x18
	; User code: RW, executable, code/data segment, present, 64-bit, ring 3
	DQ 0x0020FA0000000000 ; 0x20
[GLOBAL TSSEntry]
TSSEntry:
	DQ 0x0000000000000000 ; 0x28
	DQ 0x0000000000000000
rizxt wrote:And then finally, what do I do to officiate my entry into userspace?
Set your segments, then jump into it. See Getting to Ring 3#Entering_Ring_3
My OS is Perception.
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: How to enter userspace

Post by austanss »

AndrewAPrice wrote:
rizxt wrote:So, I know in order for me to return to ring 0 from ring 3, I need a TSS.

I don't plan on doing that quite yet, I just want to get into userspace.
You probably want a way to syscall back into the kernel unless you map 0xb8000 to usermode. Are you in protected mode or long mode?

I found the TSS straight foward to work with in long mode. The most difficult part is splitting up the TSS's address + size to write it into the GDT. The only thing you'd need in the actual TSS right now is the stack pointer to use for when you enter an interrupt. But, I don't know if you actually need a TSS if you keep interrupts disabled.
rizxt wrote:I know I need entries in my GDT for user code/data. I don't know what the entries should look like, or differ from the kernel entries, or what order the GDT needs to be laid out in.
This is for long mode. I have 5 segments in my GDT (kernel + userspace, code + data), and a reference to the TSS.

Code: Select all

[GLOBAL Gdt64]
Gdt64:
	; Invalid segment
	DQ 0x0000000000000000 ; 0x0
	; Kernel code: RW, executable, code/data segment, present, 64-bit, ring 0
	DQ 0x00209A0000000000 ; 0x8
	; Kernel data: RW, data, code/data segment, present, ring 0
	DQ 0x0000920000000000 ; 0x10
	; User data: RW, data, code/data segment, present, ring 3
	DQ 0x0020F20000000000 ; 0x18
	; User code: RW, executable, code/data segment, present, 64-bit, ring 3
	DQ 0x0020FA0000000000 ; 0x20
[GLOBAL TSSEntry]
TSSEntry:
	DQ 0x0000000000000000 ; 0x28
	DQ 0x0000000000000000
rizxt wrote:And then finally, what do I do to officiate my entry into userspace?
Set your segments, then jump into it. See Getting to Ring 3#Entering_Ring_3
Long mode. Also, reading that article, I noticed it uses IRET. The difference between x86 and x86_64 IRET is important, I believe. And it appears that article is written for x86.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: How to enter userspace

Post by kzinti »

rizxt wrote:Long mode. Also, reading that article, I noticed it uses IRET. The difference between x86 and x86_64 IRET is important, I believe. And it appears that article is written for x86.
It's pretty much the same thing, but you use "iretq" instead of "iret", Also you don't need to set %fs and %gs (and likely don't want to).

x86_64:

Code: Select all

JumpToUserMode:

    # rdi = user args
    # rsi = entry point in user space
    # rdx = user space stack

    movq $0x1b, %rax    # Selector 0x18 (User Data) + RPL 3
    movw %ax, %ds
    movw %ax, %es

    # Build a fake iret frame
    pushq %rax          # Selector 0x18 (User Data) + RPL 3
    pushq %rdx          # User space stack
    pushq $0x202        # rflags = interrupt enable + reserved bit
    pushq $0x23         # Selector 0x20 (User Code) + RPL 3
    pushq %rsi          # Entry point in user space

    iretq
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: How to enter userspace

Post by austanss »

Right, so with your help I managed to get CPL to 3, and iret to my userspace entrypoint. I now simply need to align my userspace code to it's own page, and then I can easily set it's page to user privileges.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
foliagecanine
Member
Member
Posts: 148
Joined: Sun Aug 23, 2020 4:35 pm

Re: How to enter userspace

Post by foliagecanine »

Just curious, is this the kernel, a program, or test code that you are trying to execute in userspace?
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: How to enter userspace

Post by austanss »

foliagecanine wrote:Just curious, is this the kernel, a program, or test code that you are trying to execute in userspace?
This is part of the kernel executable. I'm trying to get to userspace so I can implement syscalls + test them, and also implement a UI outside of ring 0.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
thewrongchristian
Member
Member
Posts: 426
Joined: Tue Apr 03, 2018 2:44 am

Re: How to enter userspace

Post by thewrongchristian »

rizxt wrote:
foliagecanine wrote:Just curious, is this the kernel, a program, or test code that you are trying to execute in userspace?
This is part of the kernel executable. I'm trying to get to userspace so I can implement syscalls + test them, and also implement a UI outside of ring 0.
Just don't do what I did, which was to return via iret having first pushed 0 for the eflags value. Ended up with no interrupts when running in user mode and didn't even notice until I started running CPU heavy user code :)
Post Reply