From 32cda7d7e9374b805ccd5b00ef9e1a28a3f68532 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Sun, 28 Mar 2021 17:03:18 +1100 Subject: 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> --- i386/i386/apic.c | 35 ++++++++++++++------ i386/i386/apic.h | 75 ++++++++++++++++++++++++++++++++++++++++--- i386/i386at/acpi_parse_apic.c | 15 +++++---- i386/i386at/acpi_parse_apic.h | 2 +- 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 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__)); /* -- cgit v1.2.3