I have made some progress in switching to user mode. I have followed the
http://wiki.osdev.org/Getting_to_Ring_3 tutorial. I push user-mode code and data selectors to stack, push the address of module loaded by GRUB and do "iret" (code:
https://pastebin.com/pS3VyAVU). The module is plain 32-bin binary which makes a few system calls via "int 0x80", which just print the value of
%eax to the screen (module:
https://pastebin.com/Ps8KgH4R). You can see the line
"[INFO] syscall: number 123" at the screenshot to be sure that it works. The modules also tries to call system call "exit()", but it also just prints the line
"[WARN] syscall: process try to exit with error code 0, haha". Then the module tries to return doing "ret", however stack is not configured, so general protection fault occurs. GRUB have loaded multiple modules, but I can execute the first only.
Now I have to answer a conceptual question. In UNIX the only way to create a process is a
fork() system call. Kernel runs the init process, which then forks itself into all other processes, which also can fork and so on. If init process exits, kernel panics. There is no such a thing as "kernel process" or "kernel thread".
The problem is that I'm trying to implement microkernel, which has no filesystem driver built in, so there are only two ways:
1. Make init process a "god", which has filesystem driver, process manager, memory manager, etc built into it.
2. Tell the init process about other modules and implement an API in kernel to switch to them.
I only accept the second solution. It is fully consistent with the idea of microkernel which only implements IPC (as I said in the first post, I want my kernel to have API similar to L4).
However, I still have to implement something like
fork() system call in kernel, and also some system call to replace child's process memory with other module or just jump to it. I'm stuck on this. What I have to implement in kernel to fork the process? I have implemented task state segment, paging, page frame allocator. As I understand, I should copy the kernel's page directory and allocate a stack for each process (code and data are already loaded in memory by GRUB). I haven't found any tutorials or articles about this.