summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2021-03-28 17:03:18 +1100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-03-28 23:20:05 +0200
commit32cda7d7e9374b805ccd5b00ef9e1a28a3f68532 (patch)
tree074e9056025d2a928f1cff62a6f55dfb8b900455
parent0bdb36b86e2a1917e43886dca1fdf5ae98da2f1b (diff)
Existing SMP apic code improvements
* i386/i386/apic.c (acpi_get_irq_override): New function. (apic_get_ioapic): Make it return IoApicData* rather than IoApicData. (apic_print_info): Manage IoApicData* rather than IoApicData. * i386/i386/apic.h (struct ApicReg): Use uint32_t instead of unsigned. (struct ioapic_route_entry): New structure. (union ioapic_route_entry_union): New union. (ApicLocalUnit): Rename base to gsi_base. Add ioapic field. (APIC_IRQ_OVERRIDE_POLARITY_MASK, APIC_IRQ_OVERRIDE_TRIGGER_MASK): New macros. (acpi_get_irq_override, ): New prototype. (apic_get_ioapic): Update prototype. (lapic): New declaration. (IMCR_SELECT, IMCR_DATA, MODE_IMCR, IMCR_USE_PIC, IMCR_USE_APIC, LAPIC_ENABLE, LAPIC_NMI, LAPIC_DISABLE, LAPIC_TIMER_PERIODIC, LAPIC_TIMER_DIVIDE_2, LAPIC_TIMER_DIVIDE_4, LAPIC_TIMER_DIVIDE_8, LAPIC_TIMER_DIVIDE_16, LAPIC_TIMER_BASEDIV, NINTR, IOAPIC_FIXED, IOAPIC_PHYSICAL, IOAPIC_LOGICAL, IOAPIC_NMI, IOAPIC_EXTINT, IOAPIC_ACTIVE_HIGH, IOAPIC_ACTIVE_LOW, IOAPIC_EDGE_TRIGGERED, IOAPIC_LEVEL_TRIGGERED, IOAPIC_MASK_ENABLED, IOAPIC_MASK_DISABLED): New macros. * i386/i386at/acpi_parse_apic.h (struct acpi_apic_ioapic): Rename base field to gsi_base. * i386/i386at/acpi_parse_apic.c (acpi_apic_add_ioapic): Update to gsi_base new name. Set ioapic field. (acpi_apic_setup): Rename lapic to lapic_unit. Message-Id: <20210328060320.36194-5-damien@zamaudio.com>
-rw-r--r--i386/i386/apic.c35
-rw-r--r--i386/i386/apic.h75
-rw-r--r--i386/i386at/acpi_parse_apic.c15
-rw-r--r--i386/i386at/acpi_parse_apic.h2
4 files changed, 106 insertions, 21 deletions
diff --git a/i386/i386/apic.c b/i386/i386/apic.c
index f0b4a153..2e0c1776 100644
--- a/i386/i386/apic.c
+++ b/i386/i386/apic.c
@@ -95,6 +95,19 @@ apic_add_irq_override(IrqOverrideData irq_over)
apic_data.nirqoverride++;
}
+IrqOverrideData *
+acpi_get_irq_override(uint8_t pin)
+{
+ int i;
+
+ for (i = 0; i < apic_data.nirqoverride; i++) {
+ if (apic_data.irq_override_list[i].irq == pin) {
+ return &apic_data.irq_override_list[i];
+ }
+ }
+ return NULL;
+}
+
/*
* apic_get_cpu_apic_id: returns the apic_id of a cpu.
* Receives as input the kernel ID of a CPU.
@@ -118,16 +131,14 @@ apic_get_lapic(void)
/*
* apic_get_ioapic: returns the IOAPIC identified by its kernel ID.
* Receives as input the IOAPIC's Kernel ID.
- * Returns a ioapic_data structure with the IOAPIC's data.
+ * Returns a ioapic_data structure pointer with the IOAPIC's data.
*/
-struct IoApicData
+struct IoApicData *
apic_get_ioapic(int kernel_id)
{
- IoApicData io_apic = {};
-
if (kernel_id < MAX_IOAPICS)
- return apic_data.ioapic_list[kernel_id];
- return io_apic;
+ return &apic_data.ioapic_list[kernel_id];
+ return NULL;
}
/* apic_get_numcpus: returns the current number of cpus. */
@@ -204,18 +215,22 @@ void apic_print_info(void)
uint16_t lapic_id;
uint16_t ioapic_id;
- IoApicData ioapic;
+ IoApicData *ioapic;
printf("CPUS:\n");
for (i = 0; i < ncpus; i++) {
lapic_id = apic_get_cpu_apic_id(i);
- printf(" CPU %d - APIC ID %x\n", i, lapic_id);
+ printf(" CPU %d - APIC ID %x - addr=0x%p\n", i, lapic_id, apic_get_lapic());
}
printf("IOAPICS:\n");
for (i = 0; i < nioapics; i++) {
ioapic = apic_get_ioapic(i);
- ioapic_id = ioapic.apic_id;
- printf(" IOAPIC %d - APIC ID %x\n", i, ioapic_id);
+ if (!ioapic) {
+ printf("ERROR: invalid IOAPIC ID %x\n", i);
+ } else {
+ ioapic_id = ioapic->apic_id;
+ printf(" IOAPIC %d - APIC ID %x - addr=0x%p\n", i, ioapic_id, ioapic->ioapic);
+ }
}
}
diff --git a/i386/i386/apic.h b/i386/i386/apic.h
index e2d2c508..54ccda5b 100644
--- a/i386/i386/apic.h
+++ b/i386/i386/apic.h
@@ -28,8 +28,8 @@
#include <stdint.h>
typedef struct ApicReg {
- unsigned r; /* the actual register */
- unsigned p[3]; /* pad to the next 128-bit boundary */
+ uint32_t r; /* the actual register */
+ uint32_t p[3]; /* pad to the next 128-bit boundary */
} ApicReg;
typedef struct ApicIoUnit {
@@ -37,6 +37,27 @@ typedef struct ApicIoUnit {
ApicReg window;
} ApicIoUnit;
+struct ioapic_route_entry {
+ uint32_t vector : 8,
+ delvmode : 3, /* 000=fixed 001=lowest 111=ExtInt */
+ destmode : 1, /* 0=physical 1=logical */
+ delvstatus : 1,
+ polarity : 1, /* 0=activehigh 1=activelow */
+ irr : 1,
+ trigger : 1, /* 0=edge 1=level */
+ mask : 1, /* 0=enabled 1=disabled */
+ reserved1 : 15;
+ uint32_t reserved2 : 24,
+ dest : 8;
+} __attribute__ ((packed));
+
+union ioapic_route_entry_union {
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ };
+ struct ioapic_route_entry both;
+};
typedef struct ApicLocalUnit {
ApicReg reserved0; /* 0x000 */
@@ -82,11 +103,14 @@ typedef struct ApicLocalUnit {
typedef struct IoApicData {
uint8_t apic_id;
uint32_t addr;
- uint32_t base;
+ uint32_t gsi_base;
+ ApicIoUnit *ioapic;
} IoApicData;
#define APIC_IRQ_OVERRIDE_ACTIVE_LOW 2
+#define APIC_IRQ_OVERRIDE_POLARITY_MASK 1
#define APIC_IRQ_OVERRIDE_LEVEL_TRIGGERED 8
+#define APIC_IRQ_OVERRIDE_TRIGGER_MASK 4
typedef struct IrqOverrideData {
uint8_t bus;
@@ -112,14 +136,28 @@ void apic_add_cpu(uint16_t apic_id);
void apic_lapic_init(ApicLocalUnit* lapic_ptr);
void apic_add_ioapic(struct IoApicData);
void apic_add_irq_override(struct IrqOverrideData irq_over);
+IrqOverrideData *acpi_get_irq_override(uint8_t gsi);
uint16_t apic_get_cpu_apic_id(int kernel_id);
volatile ApicLocalUnit* apic_get_lapic(void);
-struct IoApicData apic_get_ioapic(int kernel_id);
+struct IoApicData *apic_get_ioapic(int kernel_id);
uint8_t apic_get_numcpus(void);
uint8_t apic_get_num_ioapics(void);
uint16_t apic_get_current_cpu(void);
void apic_print_info(void);
int apic_refit_cpulist(void);
+void picdisable(void);
+void lapic_eoi(void);
+void ioapic_irq_eoi(int pin);
+void lapic_enable_timer(void);
+void ioapic_mask_irqs(void);
+void ioapic_toggle(int pin, int mask);
+void ioapic_configure(void);
+
+extern int timer_pin;
+extern void intnull(int unit);
+extern volatile ApicLocalUnit* lapic;
+extern inline void mask_irq (unsigned int irq_nr);
+extern inline void unmask_irq (unsigned int irq_nr);
#endif
@@ -128,6 +166,35 @@ int apic_refit_cpulist(void);
#define APIC_IO_REDIR_LOW(int_pin) (0x10+(int_pin)*2)
#define APIC_IO_REDIR_HIGH(int_pin) (0x11+(int_pin)*2)
+#define IMCR_SELECT 0x22
+#define IMCR_DATA 0x23
+#define MODE_IMCR 0x70
+# define IMCR_USE_PIC 0
+# define IMCR_USE_APIC 1
+
+#define LAPIC_ENABLE 0x100
+#define LAPIC_NMI 0x400
+#define LAPIC_DISABLE 0x10000
+#define LAPIC_TIMER_PERIODIC 0x20000
+#define LAPIC_TIMER_DIVIDE_2 0
+#define LAPIC_TIMER_DIVIDE_4 1
+#define LAPIC_TIMER_DIVIDE_8 2
+#define LAPIC_TIMER_DIVIDE_16 3
+#define LAPIC_TIMER_BASEDIV 0x100000
+
+#define NINTR 24
+#define IOAPIC_FIXED 0
+#define IOAPIC_PHYSICAL 0
+#define IOAPIC_LOGICAL 1
+#define IOAPIC_NMI 4
+#define IOAPIC_EXTINT 7
+#define IOAPIC_ACTIVE_HIGH 0
+#define IOAPIC_ACTIVE_LOW 1
+#define IOAPIC_EDGE_TRIGGERED 0
+#define IOAPIC_LEVEL_TRIGGERED 1
+#define IOAPIC_MASK_ENABLED 0
+#define IOAPIC_MASK_DISABLED 1
+
/* Set or clear a bit in a 255-bit APIC mask register.
These registers are spread through eight 32-bit registers. */
#define APIC_SET_MASK_BIT(reg, bit) \
diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c
index 23edd032..3cf6f042 100644
--- a/i386/i386at/acpi_parse_apic.c
+++ b/i386/i386at/acpi_parse_apic.c
@@ -326,8 +326,10 @@ acpi_apic_add_ioapic(struct acpi_apic_ioapic *ioapic_entry)
/* Fill IOAPIC structure with its main fields */
io_apic.apic_id = ioapic_entry->apic_id;
io_apic.addr = ioapic_entry->addr;
- io_apic.base = ioapic_entry->base;
-
+ io_apic.gsi_base = ioapic_entry->gsi_base;
+ io_apic.ioapic = (ApicIoUnit *)kmem_map_aligned_table(ioapic_entry->addr,
+ sizeof(ApicIoUnit),
+ VM_PROT_READ | VM_PROT_WRITE);
/* Insert IOAPIC in the list. */
apic_add_ioapic(io_apic);
}
@@ -447,7 +449,7 @@ static int
acpi_apic_setup(struct acpi_apic *apic)
{
int apic_checksum;
- ApicLocalUnit* lapic;
+ ApicLocalUnit* lapic_unit;
uint8_t ncpus, nioapics;
/* Check the checksum of the APIC */
@@ -457,12 +459,13 @@ acpi_apic_setup(struct acpi_apic *apic)
return ACPI_BAD_CHECKSUM;
/* map common lapic address */
- lapic = kmem_map_aligned_table(apic->lapic_addr, sizeof(ApicLocalUnit), VM_PROT_READ);
+ lapic_unit = kmem_map_aligned_table(apic->lapic_addr, sizeof(ApicLocalUnit),
+ VM_PROT_READ | VM_PROT_WRITE);
- if (lapic == NULL)
+ if (lapic_unit == NULL)
return ACPI_NO_LAPIC;
- apic_lapic_init(lapic);
+ apic_lapic_init(lapic_unit);
acpi_apic_parse_table(apic);
ncpus = apic_get_numcpus();
diff --git a/i386/i386at/acpi_parse_apic.h b/i386/i386at/acpi_parse_apic.h
index d071da4f..97a59a2e 100644
--- a/i386/i386at/acpi_parse_apic.h
+++ b/i386/i386at/acpi_parse_apic.h
@@ -139,7 +139,7 @@ struct acpi_apic_ioapic {
uint8_t apic_id;
uint8_t reserved;
uint32_t addr;
- uint32_t base;
+ uint32_t gsi_base;
} __attribute__((__packed__));
/*