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.
If I were you, I'd try to enter usermode without the interrupt flag set, and the usermode code would be just a jmp $ or while(1) for testing.
The error code of the fault says the cause is descriptor 0x42 of the LDT, and I assume you don't have an LDT.
Have you tried running in Bochs? What does the log say? What does your usermode code do? Use Bochs' debugger to dump the GDT and take a look if your usermode descriptors contain what they should.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
omarrx024 wrote:If I were you, I'd try to enter usermode without the interrupt flag set, and the usermode code would be just a jmp $ or while(1) for testing.
The error code of the fault says the cause is descriptor 0x42 of the LDT, and I assume you don't have an LDT.
Have you tried running in Bochs? What does the log say? What does your usermode code do? Use Bochs' debugger to dump the GDT and take a look if your usermode descriptors contain what they should.
Okay I will remove the flag. My usermode code does not do anything it is just a while(1) loop that halts the CPU. I do not have an LDT. I have a problem with Bochs it uses my entire CPU power and makes my system unstable. It takes around 5-10 seconds for anything to draw, loading BIOS screen (Bochs default) takes around one minute to load.
Update: without that flag being set:
Attachments
NoFlagErrorGPF.png (7.19 KiB) Viewed 4908 times
Last edited by Octacone on Sat Nov 26, 2016 7:11 am, edited 2 times in total.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Bochs is easy to set up. Try using the default options; there shouldn't be anything CPU intensive to the degree you describe. It's the easiest way to debug such low-level code.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
In Enter_User_Mode, you forget to push the actual address to jump to. There is also another problem: The user mode code is using the kernel mode stack.
omarrx024 wrote:Bochs is easy to set up. Try using the default options; there shouldn't be anything CPU intensive to the degree you describe. It's the easiest way to debug such low-level code.
I am using default options. It is just like line by line, really really really slow. Can't debug with something that runs at 0.05 FPS.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Gigasoft wrote:In Enter_User_Mode, you forget to push the actual address to jump to. There is also another problem: The user mode code is using the kernel mode stack.
Enough people have already mentioned that trying to get into userspace without doing a context switch (i.e. staying on the kernel stack and continue using the kernel state of the registers) is unlikely to result in anything useful, but it shouldn't be in the way of getting into usermode and crashing or hanging there.
The problem with hlt is probably that it's a privileged instruction. So you were in usermode, but the transition back to kernel mode to handle the GPF didn't work.
I have no idea what is going on. I checked everything twice. I just don't get it. Other people have entered user mode without any problem, every tutorial I've ever seen just magically works.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
octacone wrote:I have no idea what is going on. I checked everything twice. I just don't get it. Other people have entered user mode without any problem, every tutorial I've ever seen just magically works.
I understand the feeling. Took me about 5 days of banging my head on the wall to get it working. And it was because I wasn't using a separate user-access paged stack.
To use this, allocate a new physical page for the user-level stack. Map that physical page to some address and make sure that you set the user-accessible flag in the page table entry. enter_usermode(address_of_function, user_stack). Remember that the stack grows down, so if for instance, you chose to map 0x0-0x1000 for your user stack, pass the function 0xF00 as a test.
if you read what's inside your instruction pointer you will see that it is set jusy after some instruction it was normal to do.. But in user land, it is not!
HLT is a ring0 only instruction.
You should for now do nothing, then later call a yield syscall of sorts.
The reason HLT is privileged is because you can lock a CPU if interrupts are disabled ( which can happen sometimes right after context switch, because sti takes some times before action )
Boris wrote:if you read what's inside your instruction pointer you will see that it is set jusy after some instruction it was normal to do.. But in user land, it is not!
HLT is a ring0 only instruction.
You should for now do nothing, then later call a yield syscall of sorts.
The reason HLT is privileged is because you can lock a CPU if interrupts are disabled ( which can happen sometimes right after context switch, because sti takes some times before action )
I figured as much. Forgot that "hlt" was privileged instruction.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader