[Closed]How to prepare and enter the first user program?
Posted: Wed Dec 18, 2024 5:31 am
I'm developing a simple OS kernel. Now, I want my kernel can "load and execute" my userspace programs.
Github: https://github.com/stskyblade/StarOS
At branch: dev-process
I have a userspace programs "testadd". (https://github.com/stskyblade/StarOS/bl ... estadd.cpp)
The code loads userspace program:
https://github.com/stskyblade/StarOS/bl ... ss.cpp#L10
What I want:
I want my kernel to execute program "testadd". And I can observe the execution of "testadd" by GDB debugging, like EIP and general registers changing.
What I encounter:
It triggers a Interrupt 9(Coprocessor Segment Overrun) when I use an "iret" instruction to switch control flow to userspace programs. I think this is because I didn't prepare the environment of userspace program right.
Simplely describe the logic in function "execv":
- read the executable file to memory in kernel
- prepare a new paging directory for the program
- parse ELF structure of the file: add memory mappings, copy .text section
- prepare process LDT, one code segment, one data segment
- set a TSS(Task State Segment), and set fields
- add a TSS(Task State Segment) descriptor in GDT
- set NT(nested task) bit
- to simulate the stack content when a userspace program is interrupted, I push SS, ESP, EFLAGS, CS, EIP to the kernel stack
- use IRET to return to the process, https://github.com/stskyblade/StarOS/bl ... s.cpp#L233
- IRET triggers Interrupt 9 immediately
Background:
My kernel executes in Protected and Paging-enabled environment in ring 0 I think.
I want my userspace program to run in ring 3.
Memory mapping in kernel:
Segment selectors all points to 0x0, so virtual address is identical to linear address.
Only used memory pages is mapped to the same physical address in kernel page directory, so linear address is same as physical address.
Memory mapping in process space:
Only .text section is mapped to the virtual address according to the ELF file. Other address space is not been used yet.
Github: https://github.com/stskyblade/StarOS
At branch: dev-process
I have a userspace programs "testadd". (https://github.com/stskyblade/StarOS/bl ... estadd.cpp)
The code loads userspace program:
https://github.com/stskyblade/StarOS/bl ... ss.cpp#L10
What I want:
I want my kernel to execute program "testadd". And I can observe the execution of "testadd" by GDB debugging, like EIP and general registers changing.
What I encounter:
It triggers a Interrupt 9(Coprocessor Segment Overrun) when I use an "iret" instruction to switch control flow to userspace programs. I think this is because I didn't prepare the environment of userspace program right.
Simplely describe the logic in function "execv":
- read the executable file to memory in kernel
- prepare a new paging directory for the program
- parse ELF structure of the file: add memory mappings, copy .text section
- prepare process LDT, one code segment, one data segment
- set a TSS(Task State Segment), and set fields
- add a TSS(Task State Segment) descriptor in GDT
- set NT(nested task) bit
- to simulate the stack content when a userspace program is interrupted, I push SS, ESP, EFLAGS, CS, EIP to the kernel stack
- use IRET to return to the process, https://github.com/stskyblade/StarOS/bl ... s.cpp#L233
- IRET triggers Interrupt 9 immediately
Background:
My kernel executes in Protected and Paging-enabled environment in ring 0 I think.
I want my userspace program to run in ring 3.
Memory mapping in kernel:
Segment selectors all points to 0x0, so virtual address is identical to linear address.
Only used memory pages is mapped to the same physical address in kernel page directory, so linear address is same as physical address.
Memory mapping in process space:
Only .text section is mapped to the virtual address according to the ELF file. Other address space is not been used yet.