OSDev.org

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

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: IRET instruction causes invalid opcode interrupt
PostPosted: Sat Feb 23, 2019 5:21 pm 
Offline

Joined: Sat Feb 23, 2019 1:09 pm
Posts: 5
It seems that whenever the IRET instruction is called, when returning from my interrupt handlers, the invalid opcode interrupt is fired. I have no idea what could cause this, maybe I have messed up the stack? I believe I have set up the GDT and IDT correctly, as my error message pops up on the screen as a test for when any interrupt occurs.

The reason I think IRET causes this, is because when a IRQ is received, such as the PIT, my IRQ handler just says to print a message and IRET, and then immediately after the message appears the message for interrupt 0x6 shows up (invalid opcode). Some other ways I tested this was by removing the "while (1);" line (see code below) at the end of my interrupt handler for software interrupts, to stop it from halting. By doing this, it will call IRET next, which, causes the same exception to happen again (invalid opcode).

Here is the output (if I delete "while (1);")
Image
As you can see, "Interrupted 32" shows, which mean that IRQ0 was fired, which is the PIT. The handler for this interrupt calls IRET at the end, and then this causes the invalid opcode interrupt, and this interrupt calls IRET at the end, which again causes the same problem.

Here is the code for the parts that apply:
Code:
#include <stdint.h>

#include "system.h"

struct idt_entry
{
    uint16_t basel;
    uint16_t selector;
    uint8_t zero;
    uint8_t attrib;
    uint16_t baseh;
}__attribute__((packed));

struct idt_ptr
{
    uint16_t limit;
    uint32_t base;
}__attribute__((packed));

struct isr_reg {
    uint32_t di, si, bp, sp, bx, dx, cx, ax;
    uint32_t isr, error;
    uint32_t eip, cs, eflags, useresp, ss;
}__attribute__((packed));

const char *exception_names[] =
{
    "Division by zero",
    "Debug",
    "Non maskable interrupt",
    "Breakpoint",
    "Detected overflow",
    "Out of bounds",
    "Invalid opcode",
    "No coprocessor",
    "Double fault",
    "Coprocessor segment overrun",
    "Bad TSS",
    "Segment not present",
    "Stack fault",
    "General protection fault",
    "Page fault",
    "Unknown interrupt",
    "Coprocessor fault",
    "Alignment check",
    "Machine check",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved"
};

static struct idt_entry idt[256];
struct idt_ptr idtp;

extern void eoi();
extern void eoi_slave();

extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();

extern void isr32();
extern void isr33();
extern void isr34();
extern void isr35();
extern void isr36();
extern void isr37();
extern void isr38();
extern void isr39();
extern void isr40();
extern void isr41();
extern void isr42();
extern void isr43();
extern void isr44();
extern void isr45();
extern void isr46();
extern void isr47();

static void idt_add_gate(struct idt_entry *entry, uint32_t base, uint16_t selector, uint8_t attrib)
{
    entry->basel = base & 0x0000ffff;
    entry->selector = selector;
    entry->zero = 0;
    entry->attrib = attrib;
    entry->baseh = (base & 0xffff0000) >> 16;
}

void idt_load()
{
    memset(&idt[0], 0, sizeof(struct idt_entry) * 256);

    idt_add_gate(&idt[0], (unsigned) isr0, 0x08, 0x8e);
    idt_add_gate(&idt[1], (unsigned) isr1, 0x08, 0x8e);
    idt_add_gate(&idt[2], (unsigned) isr2, 0x08, 0x8e);
    idt_add_gate(&idt[3], (unsigned) isr3, 0x08, 0x8e);
    idt_add_gate(&idt[4], (unsigned) isr4, 0x08, 0x8e);
    idt_add_gate(&idt[5], (unsigned) isr5, 0x08, 0x8e);
    idt_add_gate(&idt[6], (unsigned) isr6, 0x08, 0x8e);
    idt_add_gate(&idt[7], (unsigned) isr7, 0x08, 0x8e);
    idt_add_gate(&idt[8], (unsigned) isr8, 0x08, 0x8e);
    idt_add_gate(&idt[9], (unsigned) isr9, 0x08, 0x8e);
    idt_add_gate(&idt[10], (unsigned) isr10, 0x08, 0x8e);
    idt_add_gate(&idt[11], (unsigned) isr11, 0x08, 0x8e);
    idt_add_gate(&idt[12], (unsigned) isr12, 0x08, 0x8e);
    idt_add_gate(&idt[13], (unsigned) isr13, 0x08, 0x8e);
    idt_add_gate(&idt[14], (unsigned) isr14, 0x08, 0x8e);
    idt_add_gate(&idt[15], (unsigned) isr15, 0x08, 0x8e);
    idt_add_gate(&idt[16], (unsigned) isr16, 0x08, 0x8e);
    idt_add_gate(&idt[17], (unsigned) isr17, 0x08, 0x8e);
    idt_add_gate(&idt[18], (unsigned) isr18, 0x08, 0x8e);
    idt_add_gate(&idt[19], (unsigned) isr19, 0x08, 0x8e);
    idt_add_gate(&idt[20], (unsigned) isr20, 0x08, 0x8e);
    idt_add_gate(&idt[21], (unsigned) isr21, 0x08, 0x8e);
    idt_add_gate(&idt[22], (unsigned) isr22, 0x08, 0x8e);
    idt_add_gate(&idt[23], (unsigned) isr23, 0x08, 0x8e);
    idt_add_gate(&idt[24], (unsigned) isr24, 0x08, 0x8e);
    idt_add_gate(&idt[25], (unsigned) isr25, 0x08, 0x8e);
    idt_add_gate(&idt[26], (unsigned) isr26, 0x08, 0x8e);
    idt_add_gate(&idt[27], (unsigned) isr27, 0x08, 0x8e);
    idt_add_gate(&idt[28], (unsigned) isr28, 0x08, 0x8e);
    idt_add_gate(&idt[29], (unsigned) isr29, 0x08, 0x8e);
    idt_add_gate(&idt[30], (unsigned) isr30, 0x08, 0x8e);
    idt_add_gate(&idt[31], (unsigned) isr31, 0x08, 0x8e);

    idt_add_gate(&idt[32], (unsigned) isr32, 0x08, 0x8e);
    idt_add_gate(&idt[33], (unsigned) isr33, 0x08, 0x8e);
    idt_add_gate(&idt[34], (unsigned) isr34, 0x08, 0x8e);
    idt_add_gate(&idt[35], (unsigned) isr35, 0x08, 0x8e);
    idt_add_gate(&idt[36], (unsigned) isr36, 0x08, 0x8e);
    idt_add_gate(&idt[37], (unsigned) isr37, 0x08, 0x8e);
    idt_add_gate(&idt[38], (unsigned) isr38, 0x08, 0x8e);
    idt_add_gate(&idt[39], (unsigned) isr39, 0x08, 0x8e);
    idt_add_gate(&idt[40], (unsigned) isr40, 0x08, 0x8e);
    idt_add_gate(&idt[41], (unsigned) isr41, 0x08, 0x8e);
    idt_add_gate(&idt[42], (unsigned) isr42, 0x08, 0x8e);
    idt_add_gate(&idt[43], (unsigned) isr43, 0x08, 0x8e);
    idt_add_gate(&idt[44], (unsigned) isr44, 0x08, 0x8e);
    idt_add_gate(&idt[45], (unsigned) isr45, 0x08, 0x8e);
    idt_add_gate(&idt[46], (unsigned) isr46, 0x08, 0x8e);
    idt_add_gate(&idt[47], (unsigned) isr47, 0x08, 0x8e);

    idtp.limit = (sizeof(struct idt_entry) * 256) - 1;
    idtp.base = (unsigned) &idt;
}

void isrh(struct isr_reg *r)
{
    kprint("\nburnsOS encountered a critical exception and needs to reset.\n", YELLOW, BLACK);
    kprint("Whoops!\n\n", WHITE, BLACK);
    kprint("    Exception: ", GREY, BLACK);
    kprint(exception_names[r->isr], WHITE, BLACK);
    kprint(" (0x", WHITE, BLACK);
    char buffer[10];
    itoa(r->isr, buffer, 16);
    kprint(buffer, WHITE, BLACK);
    kprint(")\n", WHITE, BLACK);
    kprint("    Error code: ", GREY, BLACK);
    kprint("0x", WHITE, BLACK);
    itoa(r->error, buffer, 16);
    kprint(buffer, WHITE, BLACK);
   
    kprint("\n\nIt is safe to reset or power down your PC.\n", GREY, BLACK);

    while (1);
}

void irqh(struct isr_reg *r)
{
    kprint("\nInterrupted: ", GREY, BLACK);
    char buffer[10];
    itoa(r->isr, buffer, 10);
    kprint(buffer, WHITE, BLACK);
    kprint("\n", WHITE, BLACK);

    if (r->isr >= 40) {
        eoi_slave();
    } else {
        eoi();
    }
}


----------- and here: -------------
Code:
bits 32

global isr0
global isr1
global isr2
global isr3
global isr4
global isr5
global isr6
global isr7
global isr8
global isr9
global isr10
global isr11
global isr12
global isr13
global isr14
global isr15
global isr16
global isr17
global isr18
global isr19
global isr20
global isr21
global isr22
global isr23
global isr24
global isr25
global isr26
global isr27
global isr28
global isr29
global isr30
global isr31

global isr32
global isr33
global isr34
global isr35
global isr36
global isr37
global isr38
global isr39
global isr40
global isr41
global isr42
global isr43
global isr44
global isr45
global isr46
global isr47

global eoi
global eoi_slave

extern isrh
extern irqh

section .text
align 8
eoi:
    mov    al, 0x20
    out    0x20, al
    ret

eoi_slave:
    mov    al, 0x20
    out    0xa0, al
    out    0x20, al
    ret

isr:
    pusha

    mov    eax, esp
    push   eax
    mov    eax, isrh
    call   eax
    pop    eax
    popa
    add    esp, 8
   
    iret

irq:
    pusha

    mov    eax, esp
    push   eax
    mov    eax, irqh
    call   eax
    pop    eax

    popa
    add    esp, 8
   
    iret

isr0: ; Divide by zero
    push   dword 0
    push   dword 0
    jmp    isr

isr1: ; Debug
    push   dword 0
    push   dword 1
    jmp    isr

isr2: ; NMI
    push   dword 0
    push   dword 2
    jmp    isr

isr3: ; Breakpoint
    push   dword 0
    push   dword 3
    jmp    isr

isr4: ; Detected overflow
    push   dword 0
    push   dword 4
    jmp    isr

isr5: ; Out of bounds
    push   dword 0
    push   dword 5
    jmp    isr

isr6: ; Invalid opcode
    push   dword 0
    push   dword 6
    jmp    isr

isr7: ; No coprocessor
    push   dword 0
    push   dword 7
    jmp    isr

isr8: ; Double fault
    push   dword 8
    jmp    isr
   
isr9: ; Coprocessor segment overrun
    push   dword 0
    push   dword 9
    jmp    isr

isr10: ; Bad TSS
    push   dword 10
    jmp    isr

isr11: ; Segment not present
    push   dword 11
    jmp    isr

isr12: ; Stack fault
    push   dword 12
    jmp    isr

isr13: ; General protection fault
    push   dword 13
    jmp    isr

isr14: ; Page fault
    push   dword 0
    push   dword 14
    jmp    isr

isr15: ; Unknown interrupt
    push   dword 0
    push   dword 15
    jmp    isr

isr16: ; Coprocessor fault
    push   dword 0
    push   dword 16
    jmp    isr

isr17: ; Alignment check
    push   dword 0
    push   dword 17
    jmp    isr

isr18: ; Machine check
    push   dword 0
    push   dword 18
    jmp    isr

isr19: ; Reserved
    push   dword 0
    push   dword 19
    jmp    isr

isr20: ; Reserved
    push   dword 0
    push   dword 20
    jmp    isr

isr21: ; Reserved
    push   dword 0
    push   dword 21
    jmp    isr

isr22: ; Reserved
    push   dword 0
    push   dword 22
    jmp    isr

isr23: ; Reserved
    push   dword 0
    push   dword 23
    jmp    isr

isr24: ; Reserved
    push   dword 0
    push   dword 24
    jmp    isr

isr25: ; Reserved
    push   dword 0
    push   dword 25
    jmp    isr

isr26: ; Reserved
    push   dword 0
    push   dword 26
    jmp    isr

isr27: ; Reserved
    push   dword 0
    push   dword 27
    jmp    isr

isr28: ; Reserved
    push   dword 0
    push   dword 28
    jmp    isr

isr29: ; Reserved
    push   dword 0
    push   dword 29
    jmp    isr

isr30: ; Reserved
    push   dword 0
    push   dword 30
    jmp    isr
   
isr31: ; Reserved
    push   dword 0
    push   dword 31
    jmp    isr


isr32:
    push   dword 0
    push   dword 32
    jmp    irq

isr33:
    push   dword 0
    push   dword 33
    jmp    irq

isr34:
    push   dword 0
    push   dword 34
    jmp    irq

isr35:
    push   dword 0
    push   dword 35
    jmp    irq

isr36:
    push   dword 0
    push   dword 36
    jmp    irq

isr37:
    push   dword 0
    push   dword 37
    jmp    irq

isr38:
    push   dword 0
    push   dword 38
    jmp    irq

isr39:
    push   dword 0
    push   dword 39
    jmp    irq

isr40:
    push   dword 0
    push   dword 40
    jmp    irq

isr41:
    push   dword 0
    push   dword 41
    jmp    irq

isr42:
    push   dword 0
    push   dword 42
    jmp    irq

isr43:
    push   dword 0
    push   dword 43
    jmp    irq

isr44:
    push   dword 0
    push   dword 44
    jmp    irq

isr45:
    push   dword 0
    push   dword 45
    jmp    irq

isr46:
    push   dword 0
    push   dword 46
    jmp    irq

isr47:
    push   dword 0
    push   dword 47
    jmp    irq


Or if it's easier, or you want to see everything, here is my git repo link: https://github.com/chez4/burnsOS/tree/master/x86/src
Please say if you need to know anything else. Also note that I am using qemu, and I have tried bochs too, but with the same result

What could be causing this problem?


Top
 Profile  
 
 Post subject: Re: IRET instruction causes invalid opcode interrupt
PostPosted: Sat Feb 23, 2019 5:50 pm 
Offline
Member
Member

Joined: Sun Nov 23, 2008 5:56 am
Posts: 42
Location: Russia, Saint-Petersburg
What happens when kmain returns? The "hlt" instruction halts execution only until an interrupt. Once the interrupt is serviced, the execution will continue at an instruction following the "hlt". To reenter the halt state, "hlt" must be executed again, so a loop must be used:
Code:
hang: hlt
      jmp hang


Top
 Profile  
 
 Post subject: Re: IRET instruction causes invalid opcode interrupt
PostPosted: Sat Feb 23, 2019 6:16 pm 
Offline

Joined: Sat Feb 23, 2019 1:09 pm
Posts: 5
Wow, I feel like a complete idiot for not realising this. It explains a lot.

This fixed the problem, thanks for pointing that out :D . I never would've thought to look there :roll:


Top
 Profile  
 
 Post subject: Re: IRET instruction causes invalid opcode interrupt
PostPosted: Sun Feb 24, 2019 11:17 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1604
For next time when something like this will inevitably happen, try printing the return IP address in the fault handler. Then you know exactly where the invalid opcode was.

_________________
Carpe diem!


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

All times are UTC - 6 hours


Who is online

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