OSDev.org

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

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Unable to set up GDT properly
PostPosted: Fri May 03, 2019 1:00 pm 
Offline

Joined: Tue Sep 11, 2018 9:42 am
Posts: 7
Hi!
In my Operating System i have just implemented a GDT, an IDT and some ISRs; however i'm stuck trying to get GDT working.
The only thing i can see is that the OS keeps rebooting forever; i know there are many other threads in this forum about problems similar to this case, but i can't find any reply that solve my problem.
This is the GitHub repository where the OS is located...the folder structure is based on this Meaty Skeleton and i'm following James Molloy's tutorial to implements the whole project.

What i'm doing wrong? I've already checked the code and i haven't seen any obvious bug.


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Fri May 03, 2019 1:33 pm 
Offline
Member
Member

Joined: Sun Nov 23, 2008 5:56 am
Posts: 42
Location: Russia, Saint-Petersburg
In gdt_set_gate limit_low is assigned twice in a row


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Fri May 03, 2019 4:55 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Quirck is correct. You have this line in gdt.c:
Code:
gdt_entries[num].limit_low = (limit >> 16) & 0x0F
when it should be
Code:
gdt_entries[num].gran = (limit >> 16) & 0x0F
Your bug actually ends up restricting the limit to 64KiB and when you do the FAR JMP to set CS the memory above 0x100000 is outside the CS limit and you tripe fault. Of course any memory address through the other affected descriptors will fault on any memory address above 0xFFFF for the same reason.


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Sat May 04, 2019 9:31 am 
Offline

Joined: Tue Sep 11, 2018 9:42 am
Posts: 7
Thanks for the replies!

...so it seems that i didn't gave enough time looking for typing errors :D

However now i have another "problem": i've also implemented IDT and ISRs, but when i try to fire some interrupts(from the kernel) this function does not print the related message(from the array). If i try to print only the interrupt number it gaves me strange symbols and not the correct number, so i think it's a problem with the IDT itself.


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Sat May 04, 2019 11:22 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5103
KSMb wrote:
when i try to fire some interrupts(from the kernel) this function does not print the related message(from the array).

Your isr_common_stub passes a pointer to a struct, but your isr_handler expects a struct. You won't get anything useful until you reconcile this difference. Keep in mind that the ABI allows C functions to clobber their arguments, so you probably want to use a pointer to a struct.

Also, there's no need for "call eax", the linker will ensure "call isr_handler" works correctly. (And while we're at it, save an instruction and use "push esp" to put the pointer on the stack.)

KSMb wrote:
If i try to print only the interrupt number it gaves me strange symbols and not the correct number, so i think it's a problem with the IDT itself.

Even after you fix the above issue, this still won't work since you're not converting the integer to a string. Don't you get a compiler warning about passing an integer type to a function expecting a pointer?


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Sat May 04, 2019 12:53 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Octo beat me to it, and you can find a discussion/solution about the issue here: viewtopic.php?f=1&t=33636&p=289580&hilit=+registers_t#p289580

Upon further review of your code there is a mixture of a fix already in place. The parameters to irs_handler is passed properly, just your delcaration and prototype in the C code are wrong. In kernel/include/kernel/isrs.h it should be:
Code:
void isr_handler(registers_t *regs);
and in kernel/arch/i386/isrs.c your isr_handler function should be:
Code:
void isr_handler(registers_t *regs) {
   terminal_writestring("Received interrupt: ");
   terminal_writestring(interrupts_messages[(uint8_t)regs->int_no]); // Print message associated to num
   // terminal_writestring(regs->int_no);
   terminal_writestring("\n");
}
As Octo points out to use terminal_writestring to print an integer you'd have to write a function to do that (ie: itoa).

There is one other significant issue even if you fix the code above will still prevent the right interrupt number from being accessed properly. In kernel/include/kernel/isrs.h you have:
Code:
// This struct will be used to store all registers we've pushed
typedef struct registers {
    uint32_t ds; // Data segment selector
    uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
    uint32_t int_no, err_code; // Interrupt number and error code
    uint32_t eip, cs, eflags, useresp, ss; // Pushed by the CPU itself
} registers_t;
The problem is that in kernel/arch/i386/boot.asm you do:
Code:
    pusha ; Pushes EDI, ESI, EBP, ESP, EBX, EDX, ECX and EAX registers
    push ds
    push es
    push fs
    push gs
What you push has to exactly match the registers_t structure (in reverse order). You push DS, ES, FS, and GS and not just DS. Because these two things don't match you will be accessing data in registers_t at incorrect offsets. registers_t should look like:
Code:
typedef struct registers {
    uint32_t gs, fs, es, ds; // Segment selectors
    uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
    uint32_t int_no, err_code; // Interrupt number and error code
    uint32_t eip, cs, eflags, useresp, ss; // Pushed by the CPU itself
} registers_t;


Last edited by MichaelPetch on Sat May 04, 2019 1:15 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Sat May 04, 2019 12:58 pm 
Offline

Joined: Tue Sep 11, 2018 9:42 am
Posts: 7
Octocontrabass wrote:
Your isr_common_stub passes a pointer to a struct, but your isr_handler expects a struct. You won't get anything useful until you reconcile this difference. Keep in mind that the ABI allows C functions to clobber their arguments, so you probably want to use a pointer to a struct.

Ok...i've changed but it fire the same interrupt every time.

Octocontrabass wrote:
Also, there's no need for "call eax", the linker will ensure "call isr_handler" works correctly. (And while we're at it, save an instruction and use "push esp" to put the pointer on the stack.)

I've tried to remove it, but
Code:
isr_handler
does no longer get called. :(

Octocontrabass wrote:
Even after you fix the above issue, this still won't work since you're not converting the integer to a string. Don't you get a compiler warning about passing an integer type to a function expecting a pointer?

I've imported a
Code:
atoi()
function and now i can see decimal outputs correctly(thanks osdev.org wiki).

As usual, this is the repository


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Sat May 04, 2019 1:16 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Please see the edit in my last post for other issues that need resolving.


Top
 Profile  
 
 Post subject: Re: Unable to set up GDT properly
PostPosted: Sat May 04, 2019 5:08 pm 
Offline

Joined: Tue Sep 11, 2018 9:42 am
Posts: 7
MichaelPetch wrote:
Octo beat me to it, and you can find a discussion/solution about the issue here: viewtopic.php?f=1&t=33636&p=289580&hilit=+registers_t#p289580

Upon further review of your code there is a mixture of a fix already in place. The parameters to irs_handler is passed properly, just your delcaration and prototype in the C code are wrong. In kernel/include/kernel/isrs.h it should be:
Code:
void isr_handler(registers_t *regs);
and in kernel/arch/i386/isrs.c your isr_handler function should be:
Code:
void isr_handler(registers_t *regs) {
   terminal_writestring("Received interrupt: ");
   terminal_writestring(interrupts_messages[(uint8_t)regs->int_no]); // Print message associated to num
   // terminal_writestring(regs->int_no);
   terminal_writestring("\n");
}
As Octo points out to use terminal_writestring to print an integer you'd have to write a function to do that (ie: itoa).

There is one other significant issue even if you fix the code above will still prevent the right interrupt number from being accessed properly. In kernel/include/kernel/isrs.h you have:
Code:
// This struct will be used to store all registers we've pushed
typedef struct registers {
    uint32_t ds; // Data segment selector
    uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
    uint32_t int_no, err_code; // Interrupt number and error code
    uint32_t eip, cs, eflags, useresp, ss; // Pushed by the CPU itself
} registers_t;
The problem is that in kernel/arch/i386/boot.asm you do:
Code:
    pusha ; Pushes EDI, ESI, EBP, ESP, EBX, EDX, ECX and EAX registers
    push ds
    push es
    push fs
    push gs
What you push has to exactly match the registers_t structure (in reverse order). You push DS, ES, FS, and GS and not just DS. Because these two things don't match you will be accessing data in registers_t at incorrect offsets. registers_t should look like:
Code:
typedef struct registers {
    uint32_t gs, fs, es, ds; // Segment selectors
    uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
    uint32_t int_no, err_code; // Interrupt number and error code
    uint32_t eip, cs, eflags, useresp, ss; // Pushed by the CPU itself
} registers_t;


Thanks for your time...now everything works fine! Really appreciated.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

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