OSDev.org

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

All times are UTC - 6 hours




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: Finding IOAPIC Base Address with MADT (Causes Triple Fault)
PostPosted: Thu Mar 09, 2023 10:19 pm 
Offline
Member
Member

Joined: Tue Sep 13, 2022 9:29 pm
Posts: 61
I have successfully accessed the RSDT and retrieved it's address. Now I am trying to pass that to the MADT in order to find the address of the IOAPIC. I had taken the function from the MADT article on the Wiki and modified it a bit so that it only retrieved the IOAPIC.

madt.c
Code:
#include "madt.h"

uint64_t detect_ioapic(RSDT *rsdt) {
    uint8_t *ptr, *ptr2;
    uint32_t len;
    uint64_t ioapic_ptr = 0;
    for(len = *((uint32_t*)(rsdt + 4)), ptr2 = rsdt + 36; ptr2 < rsdt + rsdt->h.Length; ptr2 += rsdt->h.Signature[0]=='X' ? 8 : 4) {
        ptr = (uint8_t*)(uintptr_t)(rsdt->h.Signature[0]=='X' ? *((uint64_t*)ptr2) : *((uint32_t*)ptr2));
        if(!memcmp(ptr, "APIC", 4)) {
            ptr2 = ptr + *((uint32_t*)(ptr + 4));
            for(ptr += 44; ptr < ptr2; ptr += ptr[1]) {
                if (ptr[0] == 1) {
                    ioapic_ptr = (uint64_t)*((uint32_t*)(ptr+4));
                    return ioapic_ptr;
                }
            }
            break;
        }
    }
}


However, any of the code within the first if statement triggers a triple fault (even only having the 'break;'). I am a little confused as to why this is happening. I know it may be a stupid mistake or error I am missing but help would be much appreciated.


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Thu Mar 09, 2023 10:33 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
FunnyGuy9796 wrote:
However, any of the code within the first if statement triggers a triple fault (even only having the 'break;').

It triggers some other fault, and your fault-handling (or lack thereof) triggers the triple fault. That "some other fault" will tell you what's going on.

Now would be a good time to set up exception handlers. They don't have to be too fancy - just dump the CPU registers to the screen or a serial port and halt.

If you don't want to do that right now, your virtual machine can give you that information. (For example, if you're using QEMU, add "-d int" to your command line.)


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Thu Mar 09, 2023 10:44 pm 
Offline
Member
Member

Joined: Tue Sep 13, 2022 9:29 pm
Posts: 61
Alright, thanks! I will definitely do that. I kind of just skipped implementing an exception handler mainly because I was being lazy :/

Thank you for the advice!


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 3:17 am 
Offline
Member
Member

Joined: Wed Oct 01, 2008 1:55 pm
Posts: 3191
I think the IOAPIC is at a fixed address, so no reason to search ACPI tables for it. :-)


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 6:13 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
rdos wrote:
I think the IOAPIC is at a fixed address, so no reason to search ACPI tables for it. :-)

Whilst that may be true in practice for current computers, I don't think it's a given. It's probably safer to future proof by specifically finding the address.


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 6:17 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
FunnyGuy9796 wrote:
I kind of just skipped implementing an exception handler mainly because I was being lazy :/

I'm afraid that's false laziness. It is so easy to implement trivial exception handlers (e.g. just "jmp ." which then allows you to investigate the machine state in your debugger), and the consequences of not doing so can be so baffling, that it should be the first thing that you implement.


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 9:03 am 
Offline
Member
Member

Joined: Wed Oct 01, 2008 1:55 pm
Posts: 3191
iansjack wrote:
rdos wrote:
I think the IOAPIC is at a fixed address, so no reason to search ACPI tables for it. :-)

Whilst that may be true in practice for current computers, I don't think it's a given. It's probably safer to future proof by specifically finding the address.


I think the chance of a buggy BIOS providing the wrong address actually is higher than the chance this will ever be changed. It's part of Intel's & AMD's chipsets, and not the motherboard build.


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 10:08 am 
Offline
Member
Member

Joined: Tue Sep 13, 2022 9:29 pm
Posts: 61
Ok, after some debugging I found that the reason the triple fault occurred was because the MADT could not be found. I am unsure as to why that is the case but it is at least a step in the right direction. Does anyone have any idea why the MADT could not be found for the APIC?

Here's the current code:
Code:
uint64_t detect_ioapic(uint8_t *rsdt) {
    if (rsdt == NULL) {
        terminal_write("RSDT not found\n");
    }
    uint8_t *ptr, *ptr2;
    uint32_t len;
    for(len = *((uint32_t*)(rsdt + 4)), ptr2 = rsdt + 36; ptr2 < rsdt + len; ptr2 += rsdt[0]=='X' ? 8 : 4) {
        ptr = (uint8_t*)(uintptr_t)(rsdt[0]=='X' ? *((uint64_t*)ptr2) : *((uint32_t*)ptr2));
        if(!memcmp(ptr, "APIC", 4)) {
            uint32_t *ptr32 = (uint32_t*)((uint8_t*)ptr + 0x24);
            uint32_t val32 = *ptr32;
            uint64_t lapic_ptr = (uint64_t)val32;
            ptr2 = ptr + *((uint32_t*)(ptr + 4));
            for(ptr += 44; ptr < ptr2; ptr += ptr[1]) {
                if (ptr[0] == 1) {
                    uint64_t ioapic_ptr = (uint64_t)*((uint32_t*)(ptr+4));
                    return ioapic_ptr;
                }
            }
            break;
        } else {
            terminal_write("Could not locate IOAPIC\n");
            return;
        }
    }
}


It is able to retrieve the RSDT but gets trapped in an infinite loop looking for the MADT.


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 10:25 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
You know, that doesn't work unless the MADT is the first table found. If the memcmp() returns nonzero, you will immediately return from the function. Without a value, so the caller will have no defined value telling them the MADT was not found. Also, if you do manage to find the MADT there, you overwrite "ptr2", so now the outer loop will no longer work. Might I suggest adding a few structures to make that mess more readable?

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 11:34 am 
Offline
Member
Member

Joined: Tue Sep 13, 2022 9:29 pm
Posts: 61
Thank you for the advice. I added the return instruction because without it the loop is infinite and therefore triggers a fault. I am really only using this function to locate the IOAPIC so exiting once it is found isn't really an issue in this situation. I did fix the rewriting of the variable. However, I am still stuck trying to figure out how to find the IOAPIC because, as I said, the loop seems to trigger a fault which makes me think I am searching for the MADT incorrectly or something along those lines.


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 11:56 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
rdos wrote:
iansjack wrote:
rdos wrote:
I think the IOAPIC is at a fixed address, so no reason to search ACPI tables for it. :-)

Whilst that may be true in practice for current computers, I don't think it's a given. It's probably safer to future proof by specifically finding the address.


I think the chance of a buggy BIOS providing the wrong address actually is higher than the chance this will ever be changed. It's part of Intel's & AMD's chipsets, and not the motherboard build.

If you don’t search, how do know there is only one?


Top
 Profile  
 
 Post subject: Re: Finding IOAPIC Base Address with MADT (Causes Triple Fau
PostPosted: Fri Mar 10, 2023 3:18 pm 
Offline
Member
Member

Joined: Tue Sep 13, 2022 9:29 pm
Posts: 61
Update: I found the address it is usually at and set that as a constant and now everything is working fine.

ioapic.c
Code:
#include "ioapic.h"

static inline uint32_t ioapic_read(uint32_t reg) {
    volatile uint32_t* ioapic = (uint32_t*)IOAPIC_BASE;
    *ioapic = reg;
    return *(ioapic + 4);
}

static inline void ioapic_write(uint32_t reg, uint32_t val) {
    volatile uint32_t* ioapic = (uint32_t*)IOAPIC_BASE;
    *ioapic = reg;
    *(ioapic + 4) = val;
}

void ioapic_init() {
    uint32_t id = ioapic_read(IOAPIC_REG_ID);
    uint32_t ver = ioapic_read(IOAPIC_REG_VER);
    for (int i = 0; i < 24; i++) {
        ioapic_write(IOAPIC_REG_REDTBL + i * 2, 0x10000);
        ioapic_write(IOAPIC_REG_REDTBL + i * 2 + 1, 0);
    }
    terminal_write("IOAPIC: Initialized\n");
}


ioapic.h
Code:
#ifndef IOAPIC_H_INCLUDED
#define IOAPIC_H_INCLUDED

#define IOAPICID          0x00
#define IOAPICVER         0x01
#define IOAPICARB         0x02
#define IOAPICREDTBL(n)   (0x10 + 2 * n)

#include <stdint.h>
#include "../terminal.h"

#define IOAPIC_BASE 0xFEC00000

#define IOAPIC_REG_ID     0x00
#define IOAPIC_REG_VER    0x01
#define IOAPIC_REG_ARB    0x02
#define IOAPIC_REG_REDTBL 0x10

typedef struct {
    uint32_t low;
    uint32_t high;
} ioapic_redtbl_entry_t;

void ioapic_init();

#endif


I know it's not the cleanest implementation and probably not the most efficient but at least it works.


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

All times are UTC - 6 hours


Who is online

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