OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 2:56 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 28 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: Usermode Triple Fault
PostPosted: Mon Nov 28, 2016 9:42 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
crunch wrote:
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.

Code:
enter_usermode:
   ;push ebp
   mov ebp, esp
   cli

   mov ax, 0x20 | 3
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   push 0x20 | 3   ; push ss3

   mov ecx, [ebp+8]
   push ecx ; push esp3

   pushf  ; push flags onto stack
   pop eax ; pop into eax
   or eax, 0x200 ; set IF (enable interrupts)
   push eax ; push eflags
   push 0x18 | 3 ; push CS, requested priv. level = 3

   xor eax, eax  ; Clear eax
   mov eax, [ebp+4] ; Load new IP into eax
   push eax ; Push EIP onto stack

   iret



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.


I have never heard of this concept before. I am still getting triple faults. What am I doing wrong?
Code:
uint32_t user_stack;
Map_Physical_Virtual(user_stack, 0x1000, 4096, Page_Writeable | Page_Present | Page_User);
Enter_User_Mode(0xF00, user_stack);


Bochs log: (unk. ctxt): mov eax, dword ptr ds:0xcf1f0013 ; a113001fcf
Also why did you uncomment "push ebp"?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 11:14 am 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
He just told you that a stack is growing downwards (in terms of addresses)
Your func even only accepts 1 parameter, how do you expect this to work?

Code:
Enter_User_Mode(user_stack + 0xFFC);


This is what he told you to do.

Push EBP is useless since you dont restore it anyways.
Anyways you should use a location which is greater then 0x1000 for the stack.
Pick some random one but dont be too low or too high

Also whats user_stack for in your example? Its some random uninitialized stack data.

TIP: Download IDA and reverse your own binary


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 11:25 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Ch4ozz wrote:
He just told you that a stack is growing downwards (in terms of addresses)
Your func even only accepts 1 parameter, how do you expect this to work?

Code:
Enter_User_Mode(user_stack + 0xFFC);


This is what he told you to do.

Push EBP is useless since you dont restore it anyways.
Anyways you should use a location which is greater then 0x1000 for the stack.
Pick some random one but dont be too low or too high

Also whats user_stack for in your example? Its some random uninitialized stack data.

TIP: Download IDA and reverse your own binary


I know... Assembly is not my language...
When I use values greater than 0x1000 my restarts are very rapid, when I use something like 0x900 for e.g, restarts are really space out like every 2-4 seconds. user_stack is something random that I have no use for since it was suggested to me. :|

Also, nothing has changed.
Code:
Map_Physical_Virtual(& user_stack, 0x2000, 16384, Page_Writeable | Page_Present | Page_User);
Enter_User_Mode(user_stack + 0xFFC);


Bochs keeps reporting: (unk. ctxt): add byte ptr ds:[eax], al ; 0000

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 11:45 am 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
Code:
add byte ptr ds:[eax], al ; 0000

That means the code you executed was just a bunch of zeros.
Use Qemu, log the values on triple fault, download IDA and start understanding the code your compiler generated.


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 12:19 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Ch4ozz wrote:
Code:
add byte ptr ds:[eax], al ; 0000

That means the code you executed was just a bunch of zeros.
Use Qemu, log the values on triple fault, download IDA and start understanding the code your compiler generated.


Qemu log:
Code:
CPU Reset (CPU 0)
EAX=00000032 EBX=00000000 ECX=00000000 EDX=00000001
ESI=0000000a EDI=00100000 EBP=00000000 ESP=00000fc8
EIP=000f04ad EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000f6ae0 00000037
IDT=     000f6b1e 00000000
CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=00000001 CCO=LOGICL 
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000


I can't download IDA on Linux, there are bunch of dependencies missing and errors and such. Even if I manage to install a debugger what am I going to do with it? I do not understand machine language as you do. Btw, your all zero theory seems correct they are all bunch of zeros. Also why is DPL=0?

Update: I managed to run IDA and there are like 1000 million lines of something. What am I supposed to do with all that? There are like memory addresses and weird assembly instructions.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 12:35 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
octacone wrote:
Even if I manage to install a debugger what am I going to do with it? I do not understand machine language as you do.

That's nature's way of telling you to do a little more studying before trying to write advanced code.


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 1:02 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
iansjack wrote:
octacone wrote:
Even if I manage to install a debugger what am I going to do with it? I do not understand machine language as you do.

That's nature's way of telling you to do a little more studying before trying to write advanced code.


It is easier to ask people that know the answer, than search yourself without knowing what to search for. Manuals are useless to me, they are overcomplicated. It is a lot easier when people try to describe you their experiences. This was a bit off-topic, anyways I am speechless. :| Do you think that user mode is something that I shouldn't do and is too complicated? If yes, I have an entire list of things that need to be done. :) Never quit, except when you have to.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 2:00 pm 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
Qemu log gave you EIP (000f04ad) you simply go to that address now in IDA and check the assembly.
Honestly, if you cant read asm you wont get that far because you need to know atleast the basics to write some routines like the scheduler and (in your case now) the context switch.
Oh and btw, my bunch of zeros was no theory, I know most of the standard opcodes by heart ;)


Last edited by Ch4ozz on Mon Nov 28, 2016 2:09 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 2:08 pm 
Offline
Member
Member
User avatar

Joined: Wed Aug 31, 2016 9:53 pm
Posts: 81
Location: San Diego, CA
You should make sure that you understand what the code I gave you is doing. You need to pass the location of the instructions you want executed first, and then the stack location.
Open up the qemu console and make sure that the code is in the right location, and not just a bunch of 0's. Make sure that your code and data pages are in your page table, and mapped as user accessible.

I suggest just a simple jmp $ loop, so that you can look at the register states and verify that you're executing in Ring3. You could, for example do the following.. in psuedo code

Code:
/* Allocate pages for code and stack */
uint32_t* address-of-user-code = map_page(allocate_physical_page(), virtual_address = 0x1000, PTE_PRESENT | PTE_WRITE | PTE_USER);
uint32_t* address-of-user-stack = map_page(allocate_physical_page(), virtual_address = 0x0000, PTE_PRESENT | PTE_WRITE | PTE_USER);

/* EBFE is the opcode for jmp $
address-of-user-code should point to the memory location 0x00001000
and that memory location should now contain the instruction for jmp 0x1000 */
*address-of-user-code = 0x000FEEB

/* Remember that stack grows down, so we need to start somewhere above 0x0000 and somewhere below 0x1000 */
enter_usermode(address-of-user-code, address-of-user-stack + 0xF00);

_________________
Some of my open-source projects:
Ext2/ELF32 bootloader
Lightweight x86 assembler, designed to be portable for osdev
Scheme in under 1000 lines of C


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 2:16 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5103
octacone wrote:
It is easier to ask people that know the answer, than search yourself without knowing what to search for. Manuals are useless to me, they are overcomplicated. It is a lot easier when people try to describe you their experiences.

Manuals are useless to you because you haven't narrowed down your problem to something that the manual can tell you how to solve. Right now, you only know that switching to user mode is failing, but not the specific point where the CPU stops doing what you think it should be doing. Once you have a specific problem, like "IRET jumps to the wrong location", then you can read the relevant parts of the manual (the section describing IRET) and see if what you're doing is correct (by checking the stack, GDT, page tables, etc. with your debugger).

Even if you can't figure out the problem that way, it'll give you more information you can include in your posts to get better answers from us.

octacone wrote:
Do you think that user mode is something that I shouldn't do and is too complicated?

That's up to you. Do you think you should be able to do this? You can always work on something easier and come back once you have more debugging experience.


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 2:36 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
octacone wrote:
anyways I am speechless.

Not, I can assure you, as speechless as I was to see someone giving the fact that they don't understand assembler as an excuse to avoid debugging.


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 4:31 pm 
Offline
Member
Member
User avatar

Joined: Thu Mar 10, 2016 7:35 am
Posts: 167
Location: Lancaster, England, Disunited Kingdom
OK. Here's a challenge.

Take a break.
Stay in Ring 0.

Have you written an assembler 'Hello World' program yet? This is the most sensible suggestion as a starting point ever made! Simple and satisfying.

When you've done that have a go at this:

Write a routine that is given an address in memory and then places on screen a representation of the 256 memory bytes starting at that address in 16 rows of 16 columns of hexadecimal representation of each successive byte. Each row could start with the address of the first byte being decoded in that row, but you might choose to add that feature as an enhancement. This actually replicates a well-known early MSDos program called 'debug' and will prove a useful routine in the future, but you will be using straightforward ordinary instructions to give you a feel for assembler and a confidence in its use.

Output might look something like this (for the first row starting at, say, address 00004000:

00004000 B7 01 B8 02 03 04 05 B6 06 B9 07 08 09 0A B5 0B

Total code length for the exercise (at a guess) about 128-256 bytes and may be 40-60 instructions.

The line shown above is actually a genuine sequence of machine code for 5 very simple assembler instructions (32 bit mode). So as a preliminary exercise you could have a go at working out what the 5 instructions are using a table of Intel opcodes. They are easy instructions to understand and the pattern of the bytes does give a pretty strong clue as to where one instruction ends and the next begins. The five instructions are very similar to each other.

From this you may take it that my belief is that unless you can work out how an assembler has produced the sequence of machine code bytes from the instruction you entered then you don't really understand assembler! The assembler is just a tool to save you flapping about with the tedious job of working out the numbers - rather like a chef having someone to wash up for him. But the point is that the chef does actually know how to wash up if he needs to.

If you manage the exercise you can then write a little extra code to call your routine asking it to to start display at the very start of the routine itself. Your routine will then have displayed on screen the machine code representation of itself.

I'm guessing that this is a challenging but not impossible problem. Difficult to know because I've been writing in assembler languages, on and off, since 1982 so a lot of stuff now seems fairly obvious to me. If you're up for it, share your progress here or PM me. If it's too hard or too easy I'd be happy to offer alternative problems. The secret to success is to try and break the problem down into the most minute stages, testing each one, however simple, one at a time. For example, start by testing that you can write the letter 'A' on screen wherever you want. Next, see if you can write byte values of 0 up to 15 on the screen in the standard hexadecimal symbols 0-9 and A-F. The second secret is not to give up. The third secret is that when it goes wrong spend time thinking how it could go wrong, then, if stuck, go to bed, then think again. The fourth secret is not to ask for help until you have been stuck for at least 8 hours, but you can be excused that one at present.


Top
 Profile  
 
 Post subject: Re: Usermode GPF
PostPosted: Mon Nov 28, 2016 5:49 pm 
Offline
Member
Member

Joined: Sun Feb 01, 2009 6:11 am
Posts: 1070
Location: Germany
octacone wrote:
It is easier to ask people that know the answer, than search yourself

Easier for you or easier for the people who you demand to teach you and all the other beginners for free?

Don't think it's their duty to debug your code for you, they probably have enough code of their own. Most of us are happy to help even though we don't have to, but most of us also don't like it if it becomes apparent that our time is wasted just because wasting it is the easier option for the lazy.

_________________
Developer of tyndur - community OS of Lowlevel (German)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 28 posts ]  Go to page Previous  1, 2

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 149 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group