I am following JamesM's tutorial to write my OS but I have a problem with switching from kernel to user mode.
The tutorial provides the following function for switching to user mode.
Code: Select all
void switch_to_user_mode()
{
asm volatile(" \
cli; \
mov $0x23, %ax; \
mov %ax, %ds; \
mov %ax, %es; \
mov %ax, %fs; \
mov %ax, %gs; \
\
mov %esp, %eax; \
push $0x23; \
push %eax; \
pushfl; \
push $0x1B; \
push $1f; \
iret; \
1: \
");
}
Code: Select all
switch_to_user_mode();
ConsoleWriteString("\nIn User MODE\n");
However the code is not working. On running it in bochs it keeps on restarting.
When I ran it in bochs debugger I found that control returns from switch_to_user_mode() to the main function
but then it hits a far jump instruction and stops there.
Code: Select all
<bochs:21> s
Next at t=148248984
(0) [0x00000000001000b3] 001b:001000b3 (kmain+a7): mov dword ptr ss:[esp], 0x0010277d ; c704247d271000
<bochs:22> s
(0).[148248984] [0x00000000001000b3] 001b:001000b3 (kmain+a7): mov dword ptr ss:[esp], 0x0010277d ; c704247d271000
Next at t=148248985
(0) [0x00000000fffffff0] f000:fff0 (no symbol): jmp far f000:e05b ; ea5be000f0
but after that strangely a far jump is encountered while there is no jump in the disassembly.
Here is the dissassembly of the instructions from main function shown above
Code: Select all
1000ae: e8 39 26 00 00 call 1026ec <switch_to_user_mode>
1000b3: c7 04 24 7d 27 10 00 movl $0x10277d,(%esp)
1000ba: e8 f7 04 00 00 call 1005b6 <ConsoleWriteString>
It can be seen that the instruction to move a pointer into esp -
Code: Select all
movl $0x10277d,(%esp)
I checked the GDT and it seemed fine. The segment registers also had the required user mode selectors. However
I found some difference in the segment registers after two different instructions.I checked the segment registers after the iret instruction in switch_to_user_mode and then after the ret instruction I checked them again
Here are the values after iret
Code: Select all
<bochs:17> s
Next at t=148248983
(0) [0x0000000000102707] 001b:00102707 (switch_to_user_mode+1b): ret ; c3
<bochs:18> sreg
es:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x001b, dh=0x00cffb00, dl=0x0000ffff, valid=1
Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Accessed, 32-bit
ss:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1 ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x00108020, limit=0x27
idtr:base=0x001080e0, limit=0x7ff
Code: Select all
<bochs:17> s
Next at t=149328457
(0) [0x00000000001000b3] 001b:001000b3 (kmain+a7): mov dword ptr ss:[esp], 0x0010277d ; c704247d271000
<bochs:18> sreg
es:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
cs:0x001b, dh=0x00cffb00, dl=0x0000ffff, valid=1
Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Accessed, 32-bit
ss:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=3 ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ds:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
fs:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
gs:0x0023, dh=0x00cff300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x00108020, limit=0x27
idtr:base=0x001080e0, limit=0x7ff
breaks just after the instruction which writes to stack.
I hope I am clear. Please help.
Thanks
Vaibhav Jain