OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 4:07 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Implementing IDT in long mode
PostPosted: Sat Nov 27, 2021 7:59 am 
Offline
Member
Member

Joined: Wed Oct 20, 2021 6:00 pm
Posts: 102
Location: Paraguay
Hi,
I've been stuck in this problem for quite a while (specifically 3 days :D). Can anyone give me advice? Here is the code, please fix it for me:

In idt.h
Code:
#ifndef IDT_H
#define IDT_H

#include <stdint.h>
#include <stddef.h>

/**
* @brief 64-bit IDT entry, 16 byte wise
*
*/
typedef struct idt_entry {
    uint16_t base_low;
    uint16_t segment_selector;
    uint8_t ist;     
    uint8_t gate_type           : 4;
    uint8_t reserved1           : 1;
    uint8_t dpl                 : 2;
    uint8_t present             : 1;
    uint16_t base_middle;
    uint32_t base_high;
    uint32_t reserved2;
}__attribute__((packed)) idt_entry_t;

typedef struct idt_descriptor {
    uint16_t size;
    uint64_t base;
}__attribute__((packed)) idt_descriptor_t;

void idt_init();

#endif


In idt.c:
Code:
#include "idt.h"

/** We have 256 interrupt gate, entry from 0..31 are
* reserved for CPU, 32..47 will reserved for IRQ,
* all gates from 48..255 are free for our OS
*/
static idt_entry_t idt_table[256];

/**
* @brief IDT descriptor, use for load IDT
*/
static idt_descriptor_t idtr;

static inline
void idt_set_gate(uint8_t num, uint64_t base, uint16_t seg_sel,
                    uint8_t gate_type, uint8_t dpl)
{
    idt_entry_t *this = &idt_table[num];
    this->base_low = base & 0xFFFFFFFF;
    this->base_middle = (base >> 16) & 0xFFFFFFFF;
    this->base_high = (base >> 32) & 0xFFFFFFFF;
    this->segment_selector = seg_sel;
    this->gate_type = gate_type;
    this->dpl = dpl;
    this->present = 1;

    this->reserved1 = 0;
    this->reserved2 = 0;
    this->ist = 0;
}

#include "isr.h"
#include "../memory/gdt.h"

void
idt_init()
{
    asm volatile("cli");
    idtr.base = (uint64_t) &idt_table;
    idtr.size = sizeof(idt_entry_t) * 256;
    memset(&idt_table, 0, sizeof(idt_entry_t) * 256);


    idt_set_gate(0, (uint64_t) isr_0, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(1, (uint64_t) isr_1, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(2, (uint64_t) isr_2, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(3, (uint64_t) isr_3, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(4, (uint64_t) isr_4, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(5, (uint64_t) isr_5, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(6, (uint64_t) isr_6, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(7, (uint64_t) isr_7, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(8, (uint64_t) isr_8, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(9, (uint64_t) isr_9, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(10, (uint64_t) isr_10, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(11, (uint64_t) isr_11, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(12, (uint64_t) isr_12, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(13, (uint64_t) isr_13, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(14, (uint64_t) isr_14, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(15, (uint64_t) isr_15, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(16, (uint64_t) isr_16, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(17, (uint64_t) isr_17, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(18, (uint64_t) isr_18, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(19, (uint64_t) isr_19, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(20, (uint64_t) isr_20, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(21, (uint64_t) isr_21, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(22, (uint64_t) isr_22, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(23, (uint64_t) isr_23, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(24, (uint64_t) isr_24, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(5, (uint64_t) isr_25, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(26, (uint64_t) isr_26, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(27, (uint64_t) isr_27, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(28, (uint64_t) isr_28, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(29, (uint64_t) isr_29, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(30, (uint64_t) isr_30, SEGMENT_KCODE_OFFSET, 0xE, 0);
    idt_set_gate(31, (uint64_t) isr_31, SEGMENT_KCODE_OFFSET, 0xE, 0);

    asm volatile("sti");
}


In isr-stub.asm:
Code:
section .text

%macro ISR_NOERR 1
global isr_%1
isr_%1:
    push qword 0
    push qword %1
    jmp isr_handler_stub
%endmacro

%macro ISR_ERR 1
global isr_%1
isr_%1:
    push qword %1
    jmp isr_handler_stub
%endmacro

%macro pushaq 1
    push rax
    push rcx
    push rdx
    push rbx
    push rbp
    push rsi
    push rdi
%endmacro

%macro popaq 1
    pop rdi
    pop rsi
    pop rbp
    pop rbx
    pop rdx
    pop rcx
    pop rax
%endmacro

ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_ERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_NOERR 30
ISR_NOERR 31

extern isr_handler
isr_handler_stub:
    ;push rax
    ;push rcx
    ;push rdx
    ;push rbx
    ;push rsp
    ;push rbp
    ;push rsi
    ;push rdi
    ;push r8
    ;push r9
    ;push r10
    ;push r11
    ;push r12
    ;push r13
    ;push r14
    ;push r15
    pushaq 1

    mov word ax, ds
    push rax

    mov rax, rsp
    push rax

    mov word ax, 0x10
    mov word ds, ax
    mov word es, ax
    mov word fs, ax
    mov word gs, ax

    call isr_handler

    add qword rsp, 8

    pop rax
    mov word ds, ax
    mov word es, ax
    mov word fs, ax
    mov word gs, ax

    ;pop r15
    ;pop r14
    ;pop r13
    ;pop r12
    ;pop r11
    ;pop r10
    ;pop r9
    ;pop r8
    ;pop rdi
    ;pop rsi
    ;pop rbp
    ;pop rsp
    ;pop rbx
    ;pop rdx
    ;pop rcx
    ;pop rax
    popaq 1

    add qword rsp, 16

    iret


In isr.h:
Code:
#ifndef ISR_H
#define ISR_H

#include <stdint.h>

#include "../common/printf.h"

typedef struct interrupt_state {
    uint64_t ds;                                            /** Pushed by isr_handler_stub */
    //uint64_t r15, r14, r13, r12, r11, r10, r9, r8;          /** Pushed by isr_handler_stub */
    uint64_t rdi, rsi, rbp, useless, rbx, rdx, rcx, rax;    /** Pushed by isr_handler_stub */
    uint64_t int_no, err_code;                              /** Pushed by CPU when interrupt fired */
    uint64_t rip, cs, rflags, rsp, ss;                      /** Pushed by CPU when interrupt fired */
}__attribute__((packed)) interrupt_state_t;


typedef void (*isr_t)(interrupt_state_t *);

void isr_register(uint8_t int_no, isr_t handler);

void isr_handler(interrupt_state_t *state);

extern void isr_0();
extern void isr_1();
extern void isr_2();
extern void isr_3();
extern void isr_4();
extern void isr_5();
extern void isr_6();
extern void isr_7();
extern void isr_8();
extern void isr_9();
extern void isr_10();
extern void isr_11();
extern void isr_12();
extern void isr_13();
extern void isr_14();
extern void isr_15();
extern void isr_16();
extern void isr_17();
extern void isr_18();
extern void isr_19();
extern void isr_20();
extern void isr_21();
extern void isr_22();
extern void isr_23();
extern void isr_24();
extern void isr_25();
extern void isr_26();
extern void isr_27();
extern void isr_28();
extern void isr_29();
extern void isr_30();
extern void isr_31();

#endif


In isr.c:
Code:
#include "isr.h"

static isr_t isr_table[256] = { NULL };

inline void
isr_register(uint8_t int_no, isr_t handler)
{
    if (isr_table[int_no] != NULL) {
        cprintf(VGA_COLOR_RED, "ERROR: isr_register: handler for interrupt %#x already registered", int_no);
        return;
    }
    isr_table[int_no] = handler;
}


void
isr_handler(interrupt_state_t *state)
{
    uint8_t num = state->int_no;

    cprintf(VGA_COLOR_CYAN, "INFO: isr_handler: caught interrupt %#x", num);
}


Thank you everyone!

NeonLightions


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Sat Nov 27, 2021 11:29 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
Can I suggest that you make your source code available on an online repository, rather than posting large amounts of code here. It makes the forum less cluttered and provides anyone who is inclined to debug your code all the information they need.


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Sat Nov 27, 2021 1:30 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
NeonLightions wrote:
I've been stuck in this problem for quite a while (specifically 3 days :D). Can anyone give me advice? Here is the code, please fix it for me:
No, I won't, if you ask like that. Your question is not indicative of what is wrong or what you have done to rectify the issue. Rather, you dump a whole lot of source code on me and expect me to read it in my off time. No, not happening. Maybe the others are feeling more charitable, but I won't do your homework for you.

Besides, IDT? Just read the CPU manuals, that tells you all about how to fill the IDT correctly.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Sat Nov 27, 2021 2:58 pm 
Offline
Member
Member
User avatar

Joined: Sun Feb 18, 2007 7:28 pm
Posts: 1564
Hi,

Looks like you reached the point where you need to learn how to use a debugger to proceed. I personally use Bochs (..but plan to switch to a custom one hopefully soon.) Most use GDB since it supports source level debugging. Pick a debugger that you prefer, learn its basic functions (Break, Continue, Watch, Regs, Read/Write memory) and learn to work with it (Using memory maps to jump to function entry points, loading symbolic information etc.)

As for this thread...it would for sure be helpful to put your code in a repository (I use BitBucket but most use Github) and provide detail about the expected output and what is happening and your efforts to debug. 3 days is not a long time. Honestly am not convinced its in long mode.

Out of interest, why are you enabling hardware interrupts still? If you are getting or testing the IDT, keep hardware interrupts disabled until you have remapped hardware IRQ's via the PIC or APIC and the timer IRQ's are in place.

_________________
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Mon Dec 20, 2021 1:40 am 
Offline
Member
Member

Joined: Wed Oct 20, 2021 6:00 pm
Posts: 102
Location: Paraguay
Hi,
like you said, I have used debugger and debug patiently. But I still can't debug it, now it causes General Protection Fault. Can you help me fix it?

Here is my repo: https://github.com/NeonLightions/Amore-OS-x64

Sorry everyone for being so hasty.


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Mon Dec 20, 2021 2:37 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
NeonLightions wrote:
But I still can't debug it, now it causes General Protection Fault.
What does? When does it fault? What is, say, QEMU saying when you crank up the debug options?

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Mon Dec 20, 2021 5:54 am 
Offline
Member
Member

Joined: Wed Oct 20, 2021 6:00 pm
Posts: 102
Location: Paraguay
nullplan wrote:
NeonLightions wrote:
But I still can't debug it, now it causes General Protection Fault.
What does? When does it fault? What is, say, QEMU saying when you crank up the debug options?

It faults after handling 1 interrupt (Interrupt 0, for example)


Top
 Profile  
 
 Post subject: Re: Implementing IDT in long mode
PostPosted: Mon Dec 20, 2021 5:26 pm 
Offline
Member
Member

Joined: Wed Oct 20, 2021 6:00 pm
Posts: 102
Location: Paraguay
Oh, sorry to bother. I just realized that IDT causes GPF because I added 8 to rsp when I didn't push anything to stack :D. Sorry to bother you.


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

All times are UTC - 6 hours


Who is online

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