Skip to content

Commit

Permalink
x86_64: register local APIC NMI structures
Browse files Browse the repository at this point in the history
  • Loading branch information
jewelcodes committed Oct 8, 2024
1 parent fadca39 commit a9550e8
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
20 changes: 20 additions & 0 deletions src/platform/x86_64/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,26 @@ int apicInit() {

overrideIRQRegister(irqor);
break;
case MADT_TYPE_LOCAL_NMI:
ACPIMADTLocalNMI *lnmiEntry = (ACPIMADTLocalNMI *) ptr;
KDEBUG("local APIC NMI on ACPI ID 0x%02X LINT#%d with flags 0x%04X (%s, %s)\n",
lnmiEntry->procID, lnmiEntry->lint & 1, lnmiEntry->flags,
lnmiEntry->flags & MADT_INTERRUPT_LEVEL ? "level" : "edge",
lnmiEntry->flags & MADT_INTERRUPT_LOW ? "low" : "high");

LocalNMI *lnmi = calloc(1, sizeof(LocalNMI));
if(!lnmi) {
KERROR("could not allocate memory for local APIC NMI\n");
while(1);
}

lnmi->procID = lnmiEntry->procID;
lnmi->lint = lnmiEntry->lint;
if(override->flags & MADT_INTERRUPT_LEVEL) lnmi->level = 1;
if(override->flags & MADT_INTERRUPT_LOW) lnmi->low = 0;

lnmiRegister(lnmi);
break;
default:
KWARN("unimplemented MADT entry type 0x%02X with length %d, skipping...\n", ptr[0], ptr[1]);
}
Expand Down
49 changes: 49 additions & 0 deletions src/platform/x86_64/apic/nmi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* lux - a lightweight unix-like operating system
* Omar Elghoul, 2024
*
* Platform-Specific Code for x86_64
*/

/* Non-Maskable Interrupt Implementation */

/* Intel Software Developer's Manual Volume 3A Part 1 Chapter 11.5.1:
*
* The trigger mode of local APIC NMIs is always set to be edge-sensitive, and
* that of local APIC ExtINTs is always set to level-sensitive. LINT1 is always
* hardwired to level-sensitive, and only LINT0 can be configured to use either
* edge or level according to the information from the ACPI MADT.
*/

#include <platform/apic.h>
#include <platform/smp.h>
#include <kernel/logger.h>

static LocalNMI *lnmis = NULL;
static BusNMI *bnmis = NULL;
static int nlnmi = 0, nbnmi = 0;

/* lnmiRegister(): registers a local APIC NMI
* params: lnmi - local APIC NMI structure
* returns: count of local APIC NMIs
*/

int lnmiRegister(LocalNMI *lnmi) {
if(!lnmis) lnmis = lnmi;
else {
LocalNMI *list = lnmis;
while(list->next) list = list->next;
list->next = lnmi;
}

return nlnmi++;
}

/* lnmiCount(): returns the number of local APIC NMIs
* params: none
* returns: number of local APIC NMIs
*/

int lnmiCount() {
return nlnmi;
}
7 changes: 5 additions & 2 deletions src/platform/x86_64/include/platform/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,14 @@ typedef struct IRQOverride {

typedef struct BusNMI {
uint8_t source;
uint16_t flags;
int level, low;
uint32_t gsi;
struct BusNMI *next;
} BusNMI;

typedef struct LocalNMI {
uint8_t procID;
uint16_t flags;
int level, low;
uint8_t lint;
struct LocalNMI *next;
} LocalNMI;
Expand All @@ -217,6 +217,9 @@ void ioapicWrite(IOAPIC *, uint32_t, uint32_t);
uint32_t ioapicRead(IOAPIC *, uint32_t);
int ioapicMask(int, int);

int lnmiRegister(LocalNMI *);
int lnmiCount();

int overrideIRQRegister(IRQOverride *);
int overrideIRQCount();
IRQOverride *findOverrideIRQ(uint64_t);

0 comments on commit a9550e8

Please sign in to comment.