OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Apr 24, 2024 9:53 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Thu Jan 23, 2020 2:14 pm 
Offline

Joined: Thu Oct 24, 2019 7:01 am
Posts: 10
Jumping to module adress in multiboot header in GRUB causes load_seg_reg(SS): rpl != CPL. I don`t have userspace now and of course it is kernel space. Paging is disabled, if I enable it I have page fault. Obviously, rpl != CPL and not jumping to garbage exception means I reach that code. But why doesn`t it work? Module is compiled using nasm -fbin and just sets eax to 0xDEADBEEF. I believe that gdt and idt are doing fine to since everything else is working.
source: https://github.com/nergzd723/ethanium


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Fri Jan 24, 2020 2:11 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5145
nergzd723 wrote:
Module is compiled using nasm -fbin and just sets eax to 0xDEADBEEF.

Does it do anything else? The CPU isn't going to stop when it reaches the end of the file unless you tell it to.


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Fri Jan 24, 2020 6:34 am 
Offline

Joined: Thu Oct 24, 2019 7:01 am
Posts: 10
Yes, jmp $ intended to stop the cpu. It seems like it`s something wrong with segments but I am sure that my GDT is okay


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Fri Jan 24, 2020 7:39 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,

nergzd723 wrote:
Yes, jmp $ intended to stop the cpu. It seems like it`s something wrong with segments but I am sure that my GDT is okay
From the Multiboot specification:
Quote:
the OS image must not load any segment registers (even just reloading the same values!) until it sets up its own ‘GDT’.

I think you should set up GDT here and the segment registers before you make a call to kmain (even if that's just a temporary hardcoded GDT and not the final one). Thay way you'll have a known-to-be-good segment registers, regardless what the loader passed to you. According to the spec, Multiboot does not guarantee anything about privileges (for instance that RPL and CPL will match), it only guarantees base of 0 and limit of 0xFFFFFFFF, but that's all. As a matter of fact, the Multiboot spec states: "The exact values are all undefined".

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Fri Jan 24, 2020 7:49 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
I believe your multiboot boot module should be an elf object file rather than a raw binary.


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Fri Jan 24, 2020 8:58 am 
Offline
Member
Member
User avatar

Joined: Sun Apr 05, 2015 3:15 pm
Posts: 31
After taking a quick look, this doesn't seem right: https://github.com/nergzd723/ethanium/b ... ty.asm#L20

_________________
osdev project, goal is to run wasm as userspace: https://github.com/kwast-os/kwast


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Fri Jan 24, 2020 11:02 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
Your jmp_tomod function references GDT descriptors four and five, but you only have three in the GDT.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 2:56 am 
Offline

Joined: Thu Oct 24, 2019 7:01 am
Posts: 10
Thank you all for replies!
Quote:
I think you should set up GDT here and the segment registers before you make a call to kmain (even if that's just a temporary hardcoded GDT and not the final one).

If I do that, the multiboot info would be wrong somewhy, magic is bad.
Then, I tried initializing GDT and IDT and set up syscall handler and nothing more, then jumping to app. I got error:
Code:
check_cs: confronting code seg descriptor dpl > cpl, dpl=3, cpl=2

Does it mean that kernel runs at cpl2? It should be zero. Qemu just throw GPF.
And if I don`t have user code and user data segs, I get loading null selector error. I have no idea why is it wrong.


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 6:38 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
Hi,
nergzd723 wrote:
Thank you all for replies!
Quote:
I think you should set up GDT here and the segment registers before you make a call to kmain (even if that's just a temporary hardcoded GDT and not the final one).

If I do that, the multiboot info would be wrong somewhy, magic is bad.
Don't do anything complex that changes registers. Just a single "lgdt" instruction with a static GDT. Then you can use segments in your jmp_tomod.

Calling a function uses SS register, don't do that until you're sure you have a valid one. For example:
Code:
; hardcoded temporary GDT until we set it up properly
            align       16
GDT_table:  dd          0, 0                ;null descriptor
            dd          0000FFFFh,008F9200h ;32 bit prot mode flat ds
            dd          0000FFFFh,00CF9A00h ;32 bit prot mode ring0 cs
GDT_value:  dw          GDT_value-GDT_table
            dd          GDT_table

start:
    cld                             ; Clear the direction flag for string operations
    mov esp, eax                    ; save eax in esp register which we will set anyway
    lgdt  [GDT_value]               ; set up segment registers
    mov ax, 8
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov eax, esp                    ; restore eax with magic
    mov esp, kernel_stack_top       ; Set up the stack
    ; ...
(note: this is just a simple example I wrote from memory, could be typos in it. You also need to tailor it to your needs. Some assembler needs "$8" etc. To set up CS as well, you'll need a far call to 16:kmain.)

nergzd723 wrote:
Then, I tried initializing GDT and IDT and set up syscall handler and nothing more
Don't complicate your life, it's enough if you set up IDT later. Just focus on GDT.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 8:56 am 
Offline

Joined: Thu Oct 24, 2019 7:01 am
Posts: 10
Thank you, bzt! I`ve done something like that:
Code:
start:
    cld                             ; Clear the direction flag for string operations
    call gdt_setup
    mov esp, kernel_stack_top       ; Set up the stack
    push eax;                       ; Push multiboot header
    push ebx;                       ; Push multiboot magic
    extern kmain
    call kmain                      ; Jump to kmain (never to return)

    cli                             ; We should not return here, but if we do:
    hlt
    jmp $                            ;   clear all interrupts and halt
gdt_setup:
    mov esp, eax ; save eax
    lgdt[GDT_V] ; set up hardcoded GDT
    mov ax, 8
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov eax, esp ; restore it
    jmp 0x10:.fl
.fl:
    ret
align 16
GDT_T:
    dd 0, 0 ;null descriptor
    dd 0000FFFFh, 008F9200h
    dd 0000FFFFh, 00CF9A00h
GDT_V:
    dw GDT_V-GDT_T
    dd GDT_T

Now I have triple fault, but I am sure that it even doesn`t reach kmain because COM1 is not initialized. QEMU says that I am trying to execute code outside of the RAM or the ROM. Ooops, forgot about ESP, where EAX is stored: it is 2BADB006, and eax originaly was 2BADB002.


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 10:46 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
nergzd723 wrote:
Now I have triple fault
No wonder. I told you not to use "call". Inline the whole gdt_setup thing! Calling a function requires accessing SS as well as ESP, neither is at a known state, you should not rely on them. Also you're saving EAX in ESP inside the function body, so you lost the return address for sure.

Inlining that function will remove the stack dependency and with that it will solve your issue.
Code:
start:
    cld                             ; Clear the direction flag for string operations
    mov esp, eax ; save eax
    lgdt[GDT_V] ; set up hardcoded GDT
    mov ax, 8
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov eax, esp ; restore it
    mov esp, kernel_stack_top       ; Set up the stack
    push eax;                       ; Push multiboot header
    push ebx;                       ; Push multiboot magic
    call 0x10:kmain                 ; Far call to kmain (never to return) sets up CS as well

I think far call works just like that (depends on Assembler). If not, then you have to use "db" to manually construct the instruction, or to show you a neat trick, you could also use
Code:
    push eax;                       ; Push multiboot header
    push ebx;                       ; Push multiboot magic
    push .retaddr
    jmp 0x10:kmain
.retaddr:
But your assembler should have no problem with far call, so this workaround should not be needed.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 12:42 pm 
Offline

Joined: Thu Oct 24, 2019 7:01 am
Posts: 10
Oops, forgot to say that I actually tried inlining that, but it just loops.
According to bochs:
Code:
push ebp
mov ebp, esp
sub esp, 0x0000004
mov eax, dword ptr ss:[ebp+8]
mov word ptr ss:[ebp-20], ax
mov eax, dword ptr ss:[ebp-20]
mov edx, eax
in al, dx
mov byte ptr ss:[ebp-1], al
mov al, byte ptr ss:[ebp-1]
leave
ret
add esp, 0x00000004
movzx eax, al
and eax, 0x00000020
leave
ret
test eax, eax
jz .-9 (0x00100540)
call .-42 (0x0010051b)
push ebp
mov ebp, esp
push 0x000003fd
call .-469(0x00100353)

Why does it just loop that? call -469 returns execution to beginning of it. But now we are running in 0010: selector according to bochs.


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 2:53 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 693
Can you update your git repo with the exact version of your code that is giving you troubles. The version you have in Git has missing build directory, usr.o seems to be in the wrong place and can't be found and even when linked there are a bunch of undefined references. I'd like to build your project and take a look.

Some of what bzt has told you is inaccurate about what you can do without loading your own GDT. He seems to be under the mistaken impression that you can't put things on the stack without setting your own SS (it is correct you do need to set ESP).

Although the GDTR may be invalid per the Multiboot spec you are able to use CS, DS, ES, SS, FS, and GS for all types of memory accesses as long as you don't attempt to reload any of those segment registers. You can't assume the selectors in those segment registers are a particular value (that is true). You are able to continue using the Multiboot segment registers because the CPU uses the value in the hidden descriptor cache which is only changed when a segment is reloaded with new values. If the CPU is using an invalid GDTR and you do load a value into a segment register the processor will likely fault.

Without your own GDT you can't reliably do FAR calls; FAR jmp; FAR Returns; POP to segment registers; IRET; or any mov instruction that updates a segment register etc. A side effect is without your own GDT you can't reliably do interrupts which would severely limit your OS.


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sat Jan 25, 2020 3:19 pm 
Offline

Joined: Thu Oct 24, 2019 7:01 am
Posts: 10
Quote:
missing build directory

The build directory is empty, just create it. Also to build it you'll need my toolchain in home directory.
https://github.com/nergzd723/i686-elf
You'll also need nasm. Have fixed usr.o location. And then it should build well. Bochsrc.txt in git repo isn't valid, but it just loads os.iso as cdrom.
But actually, at the time I am calling module I have a GDT. It loads gdt table and returns with new segment descriptor 0x10. Maybe GRUB puts the module where the GDT thinks data segment is located. So i need to move it to code segment? Thank you all for help!


Top
 Profile  
 
 Post subject: Re: Jumping to GRUB module adress causes rpl !=CPL in bochs
PostPosted: Sun Jan 26, 2020 2:55 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 693
nergzd723 wrote:
Oops, forgot to say that I actually tried inlining that, but it just loops.
According to bochs:
Code:
push ebp
mov ebp, esp
sub esp, 0x0000004
mov eax, dword ptr ss:[ebp+8]
mov word ptr ss:[ebp-20], ax
mov eax, dword ptr ss:[ebp-20]
mov edx, eax
in al, dx
mov byte ptr ss:[ebp-1], al
mov al, byte ptr ss:[ebp-1]
leave
ret
add esp, 0x00000004
movzx eax, al
and eax, 0x00000020
leave
ret
test eax, eax
jz .-9 (0x00100540)
call .-42 (0x0010051b)
push ebp
mov ebp, esp
push 0x000003fd
call .-469(0x00100353)

Why does it just loop that? call -469 returns execution to beginning of it. But now we are running in 0010: selector according to bochs.

The sequence of code that is looping repeatedly is the while statement here:
Code:
void put_serial(char a) {
   while (is_transmit_empty() == 0);   // Stall while transit is filled

   outb(COM1_BASE,a);
}


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 216 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