mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 23:13:26 +00:00
hv: Enumerate IOAPIC info from MADT
IOAPIC info, specifically ID, is needed to map the IOAPIC to corresponding DMAR. DMAR table in ACPI has a field that has IOAPIC ID, that matches the info provided in MADT. Both (IOAPIC info from MADT and from DMAR) is needed for remapping IOAPIC interrupts. Tracked-On: #2426 Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
parent
fb6e9267f3
commit
4ff9f5dfb2
@ -324,6 +324,11 @@ config RELOC
|
|||||||
wherever appropriate. Without relocation the bootloader must put the
|
wherever appropriate. Without relocation the bootloader must put the
|
||||||
image to RAM_START, otherwise the hypervisor will not start up.
|
image to RAM_START, otherwise the hypervisor will not start up.
|
||||||
|
|
||||||
|
config MAX_IOAPIC_NUM
|
||||||
|
int "Maximum number of IO-APICs"
|
||||||
|
range 1 8
|
||||||
|
default 1
|
||||||
|
|
||||||
config IOMMU_BUS_NUM
|
config IOMMU_BUS_NUM
|
||||||
hex "Highest PCI bus ID used during IOMMU initialization"
|
hex "Highest PCI bus ID used during IOMMU initialization"
|
||||||
default 0x10 if PLATFORM_SBL
|
default 0x10 if PLATFORM_SBL
|
||||||
|
@ -87,6 +87,7 @@ uint64_t get_active_pcpu_bitmap(void)
|
|||||||
void init_cpu_pre(uint16_t pcpu_id_args)
|
void init_cpu_pre(uint16_t pcpu_id_args)
|
||||||
{
|
{
|
||||||
uint16_t pcpu_id = pcpu_id_args;
|
uint16_t pcpu_id = pcpu_id_args;
|
||||||
|
int32_t ret;
|
||||||
|
|
||||||
if (pcpu_id == BOOT_CPU_ID) {
|
if (pcpu_id == BOOT_CPU_ID) {
|
||||||
start_tsc = rdtsc();
|
start_tsc = rdtsc();
|
||||||
@ -114,6 +115,11 @@ void init_cpu_pre(uint16_t pcpu_id_args)
|
|||||||
early_init_lapic();
|
early_init_lapic();
|
||||||
|
|
||||||
init_percpu_lapic_id();
|
init_percpu_lapic_id();
|
||||||
|
|
||||||
|
ret = init_ioapic_id_info();
|
||||||
|
if (ret != 0) {
|
||||||
|
panic("System IOAPIC info is incorrect!");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Switch this CPU to use the same page tables set-up by the
|
/* Switch this CPU to use the same page tables set-up by the
|
||||||
* primary/boot CPU
|
* primary/boot CPU
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <hypervisor.h>
|
#include <hypervisor.h>
|
||||||
#include <ioapic.h>
|
#include <ioapic.h>
|
||||||
|
#include <acpi.h>
|
||||||
|
|
||||||
#define IOAPIC_MAX_PIN 240U
|
#define IOAPIC_MAX_PIN 240U
|
||||||
|
|
||||||
@ -14,13 +15,13 @@
|
|||||||
* The usable RTEs may be a subset of the total on a per IO APIC basis.
|
* The usable RTEs may be a subset of the total on a per IO APIC basis.
|
||||||
*/
|
*/
|
||||||
#define IOAPIC_MAX_LINES 120U
|
#define IOAPIC_MAX_LINES 120U
|
||||||
#define NR_MAX_GSI (NR_IOAPICS * IOAPIC_MAX_LINES)
|
#define NR_MAX_GSI (CONFIG_MAX_IOAPIC_NUM * IOAPIC_MAX_LINES)
|
||||||
|
|
||||||
static struct gsi_table gsi_table_data[NR_MAX_GSI];
|
static struct gsi_table gsi_table_data[NR_MAX_GSI];
|
||||||
static uint32_t ioapic_nr_gsi;
|
static uint32_t ioapic_nr_gsi;
|
||||||
static spinlock_t ioapic_lock;
|
static spinlock_t ioapic_lock;
|
||||||
|
|
||||||
static union ioapic_rte saved_rte[NR_IOAPICS][IOAPIC_MAX_PIN];
|
static union ioapic_rte saved_rte[CONFIG_MAX_IOAPIC_NUM][IOAPIC_MAX_PIN];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the irq to ioapic pin mapping should extract from ACPI MADT table
|
* the irq to ioapic pin mapping should extract from ACPI MADT table
|
||||||
@ -83,6 +84,9 @@ static const uint32_t pic_ioapic_pin_map[NR_LEGACY_PIN] = {
|
|||||||
15U, /* pin15*/
|
15U, /* pin15*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct ioapic_info ioapic_array[CONFIG_MAX_IOAPIC_NUM];
|
||||||
|
static uint16_t ioapic_num;
|
||||||
|
|
||||||
uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index)
|
uint32_t get_pic_pin_from_ioapic_pin(uint32_t pin_index)
|
||||||
{
|
{
|
||||||
uint32_t pin_id = INVALID_INTERRUPT_PIN;
|
uint32_t pin_id = INVALID_INTERRUPT_PIN;
|
||||||
@ -152,10 +156,8 @@ ioapic_write_reg32(void *ioapic_base, const uint32_t offset, const uint32_t valu
|
|||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
get_ioapic_base(uint8_t apic_id)
|
get_ioapic_base(uint8_t apic_id)
|
||||||
{
|
{
|
||||||
const uint64_t addr[2] = {IOAPIC0_BASE, IOAPIC1_BASE};
|
|
||||||
|
|
||||||
/* the ioapic base should be extracted from ACPI MADT table */
|
/* the ioapic base should be extracted from ACPI MADT table */
|
||||||
return addr[apic_id];
|
return ioapic_array[apic_id].addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ioapic_get_rte_entry(void *ioapic_addr, uint32_t pin, union ioapic_rte *rte)
|
void ioapic_get_rte_entry(void *ioapic_addr, uint32_t pin, union ioapic_rte *rte)
|
||||||
@ -368,6 +370,18 @@ ioapic_nr_pins(void *ioapic_base)
|
|||||||
return nr_pins;
|
return nr_pins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t init_ioapic_id_info(void)
|
||||||
|
{
|
||||||
|
int32_t ret = 0;
|
||||||
|
|
||||||
|
ioapic_num = parse_madt_ioapic(&ioapic_array[0]);
|
||||||
|
if (ioapic_num > (uint16_t)CONFIG_MAX_IOAPIC_NUM) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void ioapic_setup_irqs(void)
|
void ioapic_setup_irqs(void)
|
||||||
{
|
{
|
||||||
uint8_t ioapic_id;
|
uint8_t ioapic_id;
|
||||||
@ -377,16 +391,16 @@ void ioapic_setup_irqs(void)
|
|||||||
spinlock_init(&ioapic_lock);
|
spinlock_init(&ioapic_lock);
|
||||||
|
|
||||||
for (ioapic_id = 0U;
|
for (ioapic_id = 0U;
|
||||||
ioapic_id < NR_IOAPICS; ioapic_id++) {
|
ioapic_id < ioapic_num; ioapic_id++) {
|
||||||
void *addr;
|
void *addr;
|
||||||
uint32_t pin, nr_pins;
|
uint32_t pin, nr_pins;
|
||||||
|
|
||||||
addr = map_ioapic(get_ioapic_base(ioapic_id));
|
addr = map_ioapic(ioapic_array[ioapic_id].addr);
|
||||||
hv_access_memory_region_update((uint64_t)addr, PAGE_SIZE);
|
hv_access_memory_region_update((uint64_t)addr, PAGE_SIZE);
|
||||||
|
|
||||||
nr_pins = ioapic_nr_pins(addr);
|
nr_pins = ioapic_nr_pins(addr);
|
||||||
for (pin = 0U; pin < nr_pins; pin++) {
|
for (pin = 0U; pin < nr_pins; pin++) {
|
||||||
gsi_table_data[gsi].ioapic_id = ioapic_id;
|
gsi_table_data[gsi].ioapic_id = ioapic_array[ioapic_id].id;
|
||||||
gsi_table_data[gsi].addr = addr;
|
gsi_table_data[gsi].addr = addr;
|
||||||
|
|
||||||
if (gsi < NR_LEGACY_IRQ) {
|
if (gsi < NR_LEGACY_IRQ) {
|
||||||
@ -432,7 +446,7 @@ void suspend_ioapic(void)
|
|||||||
uint8_t ioapic_id;
|
uint8_t ioapic_id;
|
||||||
uint32_t ioapic_pin;
|
uint32_t ioapic_pin;
|
||||||
|
|
||||||
for (ioapic_id = 0U; ioapic_id < NR_IOAPICS; ioapic_id++) {
|
for (ioapic_id = 0U; ioapic_id < ioapic_num; ioapic_id++) {
|
||||||
void *addr;
|
void *addr;
|
||||||
uint32_t nr_pins;
|
uint32_t nr_pins;
|
||||||
|
|
||||||
@ -450,7 +464,7 @@ void resume_ioapic(void)
|
|||||||
uint8_t ioapic_id;
|
uint8_t ioapic_id;
|
||||||
uint32_t ioapic_pin;
|
uint32_t ioapic_pin;
|
||||||
|
|
||||||
for (ioapic_id = 0U; ioapic_id < NR_IOAPICS; ioapic_id++) {
|
for (ioapic_id = 0U; ioapic_id < ioapic_num; ioapic_id++) {
|
||||||
void *addr;
|
void *addr;
|
||||||
uint32_t nr_pins;
|
uint32_t nr_pins;
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#define RSDP_CHECKSUM_LENGTH 20
|
#define RSDP_CHECKSUM_LENGTH 20
|
||||||
#define ACPI_NAME_SIZE 4U
|
#define ACPI_NAME_SIZE 4U
|
||||||
#define ACPI_MADT_TYPE_LOCAL_APIC 0U
|
#define ACPI_MADT_TYPE_LOCAL_APIC 0U
|
||||||
|
#define ACPI_MADT_TYPE_IOAPIC 1U
|
||||||
#define ACPI_MADT_ENABLED 1U
|
#define ACPI_MADT_ENABLED 1U
|
||||||
#define ACPI_OEM_TABLE_ID_SIZE 8
|
#define ACPI_OEM_TABLE_ID_SIZE 8
|
||||||
|
|
||||||
@ -100,6 +101,14 @@ struct acpi_madt_local_apic {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct acpi_table_rsdp *acpi_rsdp;
|
static struct acpi_table_rsdp *acpi_rsdp;
|
||||||
|
struct acpi_madt_ioapic {
|
||||||
|
struct acpi_subtable_header header;
|
||||||
|
/* IOAPIC id */
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t rsvd;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t gsi_base;
|
||||||
|
};
|
||||||
|
|
||||||
static struct acpi_table_rsdp*
|
static struct acpi_table_rsdp*
|
||||||
found_rsdp(char *base, int32_t length)
|
found_rsdp(char *base, int32_t length)
|
||||||
@ -245,6 +254,40 @@ local_parse_madt(struct acpi_table_madt *madt, uint32_t lapic_id_array[CONFIG_MA
|
|||||||
return pcpu_num;
|
return pcpu_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
ioapic_parse_madt(void *madt, struct ioapic_info *ioapic_id_array)
|
||||||
|
{
|
||||||
|
struct acpi_madt_ioapic *ioapic;
|
||||||
|
struct acpi_table_madt *madt_ptr;
|
||||||
|
void *first, *end, *iterator;
|
||||||
|
struct acpi_subtable_header *entry;
|
||||||
|
uint16_t ioapic_idx = 0U;
|
||||||
|
|
||||||
|
madt_ptr = (struct acpi_table_madt *)madt;
|
||||||
|
|
||||||
|
first = madt_ptr + 1;
|
||||||
|
end = (void *)madt_ptr + madt_ptr->header.length;
|
||||||
|
|
||||||
|
for (iterator = first; (iterator) < (end); iterator += entry->length) {
|
||||||
|
entry = (struct acpi_subtable_header *)iterator;
|
||||||
|
if (entry->length < sizeof(struct acpi_subtable_header)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->type == ACPI_MADT_TYPE_IOAPIC) {
|
||||||
|
ioapic = (struct acpi_madt_ioapic *)iterator;
|
||||||
|
if (ioapic_idx < CONFIG_MAX_IOAPIC_NUM) {
|
||||||
|
ioapic_id_array[ioapic_idx].id = ioapic->id;
|
||||||
|
ioapic_id_array[ioapic_idx].addr = ioapic->addr;
|
||||||
|
ioapic_id_array[ioapic_idx].gsi_base = ioapic->gsi_base;
|
||||||
|
}
|
||||||
|
ioapic_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ioapic_idx;
|
||||||
|
}
|
||||||
|
|
||||||
/* The lapic_id info gotten from madt will be returned in lapic_id_array */
|
/* The lapic_id info gotten from madt will be returned in lapic_id_array */
|
||||||
uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM])
|
uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM])
|
||||||
{
|
{
|
||||||
@ -261,6 +304,19 @@ uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM])
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array)
|
||||||
|
{
|
||||||
|
void *madt;
|
||||||
|
|
||||||
|
acpi_rsdp = get_rsdp();
|
||||||
|
ASSERT(acpi_rsdp != NULL, "fail to get rsdp");
|
||||||
|
|
||||||
|
madt = get_acpi_tbl(ACPI_SIG_MADT);
|
||||||
|
ASSERT(madt != NULL, "fail to get madt");
|
||||||
|
|
||||||
|
return ioapic_parse_madt(madt, ioapic_id_array);
|
||||||
|
}
|
||||||
|
|
||||||
void *get_dmar_table(void)
|
void *get_dmar_table(void)
|
||||||
{
|
{
|
||||||
return get_acpi_tbl(ACPI_SIG_DMAR);
|
return get_acpi_tbl(ACPI_SIG_DMAR);
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
#define ACPI_H
|
#define ACPI_H
|
||||||
|
|
||||||
uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM]);
|
uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM]);
|
||||||
|
uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array);
|
||||||
|
|
||||||
#endif /* !ACPI_H */
|
#endif /* !ACPI_H */
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
/* APIC */
|
/* APIC */
|
||||||
#define LAPIC_BASE 0xFEE00000UL
|
#define LAPIC_BASE 0xFEE00000UL
|
||||||
|
|
||||||
#define NR_IOAPICS 1U
|
|
||||||
#define IOAPIC0_BASE 0xFEC00000UL
|
#define IOAPIC0_BASE 0xFEC00000UL
|
||||||
#define IOAPIC1_BASE 0UL
|
#define IOAPIC1_BASE 0UL
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <io_req.h>
|
#include <io_req.h>
|
||||||
#include <io_emul.h>
|
#include <io_emul.h>
|
||||||
|
#include <ioapic.h>
|
||||||
#include <vmtrr.h>
|
#include <vmtrr.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <vlapic.h>
|
#include <vlapic.h>
|
||||||
|
@ -9,10 +9,18 @@
|
|||||||
|
|
||||||
#define NR_LEGACY_IRQ 16U
|
#define NR_LEGACY_IRQ 16U
|
||||||
#define NR_LEGACY_PIN NR_LEGACY_IRQ
|
#define NR_LEGACY_PIN NR_LEGACY_IRQ
|
||||||
|
|
||||||
|
struct ioapic_info {
|
||||||
|
uint8_t id;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t gsi_base;
|
||||||
|
};
|
||||||
|
|
||||||
void ioapic_setup_irqs(void);
|
void ioapic_setup_irqs(void);
|
||||||
|
|
||||||
bool ioapic_irq_is_gsi(uint32_t irq);
|
bool ioapic_irq_is_gsi(uint32_t irq);
|
||||||
uint32_t ioapic_irq_to_pin(uint32_t irq);
|
uint32_t ioapic_irq_to_pin(uint32_t irq);
|
||||||
|
int32_t init_ioapic_id_info(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get irq num from pin num
|
* @brief Get irq num from pin num
|
||||||
|
Loading…
Reference in New Issue
Block a user