[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC 19/35] ACPI / GICv2: Add GIC specific ACPI boot support
On 4 February 2015 at 20:13, G Gregory <graeme.gregory@xxxxxxxxxx> wrote: > On 4 February 2015 at 14:02, <parth.dixit@xxxxxxxxxx> wrote: >> From: Naresh Bhat <naresh.bhat@xxxxxxxxxx> >> >> ACPI on Xen hypervisor uses MADT table for proper GIC initialization. >> It needs to parse GIC related subtables, collect CPU interface and >> distributor >> addresses and call driver initialization function (which is hardware >> abstraction agnostic). In a similar way, FDT initialize GICv1/2. >> >> NOTE: This commit allow to initialize GICv1/2 only. >> >> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@xxxxxxxxxx> >> Signed-off-by: Graeme Gregory <graeme.gregory@xxxxxxxxxx> > > I do not recognise any of the code here and I'm pretty sure I have not > worked on any of it. I am unsure what the rules on Signed-off-by: is > but I think this one is wrong. > > Graeme I will remove it. I inherited this patch from naresh with your signoff , so i did not removed it. Thanks for alerting me. Policy is to not remove the previous signoff's in a patch and add signoff only in case some logical change is made to the patch. Parth >> Signed-off-by: Hanjun Guo <hanjun.guo@xxxxxxxxxx> >> Signed-off-by: Naresh Bhat <naresh.bhat@xxxxxxxxxx> >> Signed-off-by: Parth Dixit <parth.dixit@xxxxxxxxxx> >> >> Conflicts: >> >> xen/arch/arm/irq.c >> --- >> xen/arch/arm/gic-v2.c | 271 >> +++++++++++++++++++++++++++++++++++++++++++++ >> xen/arch/arm/setup.c | 3 +- >> xen/include/asm-arm/acpi.h | 2 + >> 3 files changed, 275 insertions(+), 1 deletion(-) >> >> diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c >> index faad1ff..cb1d205 100644 >> --- a/xen/arch/arm/gic-v2.c >> +++ b/xen/arch/arm/gic-v2.c >> @@ -777,6 +777,277 @@ DT_DEVICE_START(gicv2, "GICv2:", DEVICE_GIC) >> .init = gicv2_init, >> DT_DEVICE_END >> >> +#if defined(CONFIG_ARM_64) && defined(CONFIG_ACPI) >> + >> +#include <xen/acpi.h> >> +#include <xen/errno.h> >> +#include <xen/vmap.h> >> +#include <asm/acpi.h> >> + >> +/* >> + * Hard code here, we can not get memory size from MADT (but FDT does), >> + * this size can be inferred from GICv2 spec >> + */ >> + >> +#define ACPI_GIC_DIST_MEM_SIZE 0x00010000 // (SZ_64K) >> +#define ACPI_GIC_CPU_IF_MEM_SIZE 0x00002000 // (SZ_8K) >> + >> +static DEFINE_PER_CPU(u64, gic_percpu_cpu_base); >> +static cpumask_t gic_acpi_cpu_mask; >> +static u64 dist_phy_base; >> + >> +static int __init >> +gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, >> + const unsigned long end) >> +{ >> + struct acpi_madt_generic_interrupt *processor; >> + unsigned int cpu; >> + >> + processor = (struct acpi_madt_generic_interrupt *)header; >> + >> + if (BAD_MADT_ENTRY(processor, end)) >> + return -EINVAL; >> + for_each_possible_cpu(cpu) { >> + /* >> + * FIXME: This condition is failing. >> + * In Xen we first want to bring/initialize the GIC in hypervisor >> with single CPU >> + * if (processor->mpidr == cpu_logical_map(cpu)) >> + */ >> + goto find; >> + } >> + >> + printk("\nUnable to find CPU corresponding to GIC CPU entry [mpdir >> %lx]\n", >> + (long)processor->mpidr); >> + >> + return 0; >> + >> +find: >> + /* Read from APIC table and fill up the GIC variables */ >> + gicv2.dbase = processor->redist_base_address; >> + gicv2.cbase = processor->base_address; >> + gicv2.hbase = processor->gich_base_address; >> + gicv2.vbase = processor->gicv_base_address; >> + gicv2_info.maintenance_irq = processor->vgic_maintenance_interrupt; >> + if( processor->flags & ACPI_MADT_ENABLED ) >> + { >> + if( processor->flags & ACPI_MADT_VGIC ) >> + acpi_set_irq(gicv2_info.maintenance_irq, >> DT_IRQ_TYPE_EDGE_BOTH); >> + else >> + acpi_set_irq(gicv2_info.maintenance_irq, >> DT_IRQ_TYPE_LEVEL_MASK); >> + } >> + >> + /* >> + * Do not validate CPU i/f base, we can still use "Local Interrupt >> + * Controller Address" from MADT header instead. >> + */ >> + per_cpu(gic_percpu_cpu_base, cpu) = processor->base_address; >> + cpumask_set_cpu(cpu, &gic_acpi_cpu_mask); >> + >> + return 0; >> +} >> + >> +static int __init >> +gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, >> + const unsigned long end) >> +{ >> + struct acpi_madt_generic_distributor *dist; >> + >> + dist = (struct acpi_madt_generic_distributor *)header; >> + >> + if (BAD_MADT_ENTRY(dist, end)) >> + return -EINVAL; >> + >> + dist_phy_base = dist->base_address; >> + >> + return 0; >> +} >> + >> +static int gic_acpi_validate_init(u64 madt_cpu_addr) >> +{ >> + void __iomem *cpu_base, *dist_base; >> + u64 gic_cpu_base = 0; >> + unsigned int cpu; >> + >> + /* Process all GICC entries delivered by MADT */ >> + if (!cpumask_empty(&gic_acpi_cpu_mask)) { >> + /* >> + * If MADT contains at least one GICC entry, it must be BSP >> + * dedicated. >> + */ >> + if (!cpumask_test_cpu(0, &gic_acpi_cpu_mask)) { >> + printk("GICC entries exist but unable to find BSP >> GICC " >> + "address\n"); >> + goto madt_cpu_base; >> + } >> + >> + /* >> + * There is no support for non-banked GICv1/2 register in >> ACPI >> + * spec. All CPU interface addresses have to be the same. >> + */ >> + gic_cpu_base = per_cpu(gic_percpu_cpu_base, 0); >> + for_each_cpu (cpu, &gic_acpi_cpu_mask) { >> + if (gic_cpu_base != per_cpu(gic_percpu_cpu_base, >> cpu)) { >> + printk("GICC addresses are different, no >> support" >> + "for non-banked GICC registers >> !!!\n"); >> + gic_cpu_base = 0; >> + goto madt_cpu_base; >> + } >> + } >> + } >> + >> +madt_cpu_base: >> + /* If no GICC address provided, use address from MADT header */ >> + if (!gic_cpu_base) { >> + if (!madt_cpu_addr) { >> + printk("Unable to find GICC address\n"); >> + return -EINVAL; >> + } >> + >> + printk("Attempt to use Local Interrupt Controller Address" >> + "as GICC base address\n"); >> + gic_cpu_base = madt_cpu_addr; >> + } >> + >> + cpu_base = ioremap(gic_cpu_base, ACPI_GIC_CPU_IF_MEM_SIZE); >> + if (!cpu_base) { >> + printk("Unable to map GICC registers\n"); >> + return -ENOMEM; >> + } >> + >> + dist_base = ioremap(dist_phy_base, ACPI_GIC_DIST_MEM_SIZE); >> + if (!dist_base) { >> + printk("Unable to map GICD registers\n"); >> + iounmap(cpu_base); >> + return -ENOMEM; >> + } >> + >> + /* >> + * FIXME: Initialize zero GIC instance (no multi-GIC support) based >> on >> + * addresses obtained from MADT. Also, set GIC as default IRQ domain >> + * to allow for GSI registration and GSI to IRQ number translation >> + * (see acpi_register_gsi() and acpi_gsi_to_irq()). >> + * >> + * gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL); >> + * irq_set_default_host(gic_data[0].domain); >> + */ >> + >> + /* TODO: Add check on distributor, cpu size */ >> + >> + printk("GICv2 initialization from ACPI MADT table :\n" >> + " gic_dist_addr=%"PRIpaddr"\n" >> + " gic_cpu_addr=%"PRIpaddr"\n" >> + " gic_hyp_addr=%"PRIpaddr"\n" >> + " gic_vcpu_addr=%"PRIpaddr"\n" >> + " gic_maintenance_irq=%u\n", >> + gicv2.dbase, gicv2.cbase, gicv2.hbase, gicv2.vbase, >> + gicv2_info.maintenance_irq); >> + >> + if ( (gicv2.dbase & ~PAGE_MASK) || (gicv2.cbase & ~PAGE_MASK) || >> + (gicv2.hbase & ~PAGE_MASK) || (gicv2.vbase & ~PAGE_MASK) ) >> + panic("GICv2 interfaces not page aligned"); >> + >> + gicv2.map_dbase = ioremap_nocache(gicv2.dbase, PAGE_SIZE); >> + if ( !gicv2.map_dbase ) >> + panic("GICv2: Failed to ioremap for GIC distributor\n"); >> + >> + gicv2.map_cbase[0] = ioremap_nocache(gicv2.cbase, PAGE_SIZE); >> + >> + if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) ) >> + gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE * 0x10, >> + PAGE_SIZE); >> + else >> + gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE, >> PAGE_SIZE); >> + >> + if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] ) >> + panic("GICv2: Failed to ioremap for GIC CPU interface\n"); >> + >> + gicv2.map_hbase = ioremap_nocache(gicv2.hbase, PAGE_SIZE); >> + if ( !gicv2.map_hbase ) >> + panic("GICv2: Failed to ioremap for GIC Virtual interface\n"); >> + >> + /* Global settings: interrupt distributor */ >> + spin_lock_init(&gicv2.lock); >> + spin_lock(&gicv2.lock); >> + >> + gicv2_dist_init(); >> + gicv2_cpu_init(); >> + gicv2_hyp_init(); >> + >> + spin_unlock(&gicv2.lock); >> + >> + gicv2_info.hw_version = GIC_V2; >> + register_gic_ops(&gicv2_ops); >> + >> + return 0; >> +} >> + >> +int __init >> +gic_v2_acpi_init(struct acpi_table_header *table) >> +{ >> + struct acpi_table_madt *madt; >> + int count; >> + >> + /* Collect CPU base addresses */ >> + count = acpi_parse_entries(sizeof(struct acpi_table_madt), >> + gic_acpi_parse_madt_cpu, table, >> + ACPI_MADT_TYPE_GENERIC_INTERRUPT, >> + MAX_GIC_CPU_INTERFACE); >> + if (count <= 0) { >> + printk("Error during GICC entries parsing\n"); >> + return -EINVAL; >> + } >> + >> + /* >> + * Find distributor base address. We expect one distributor entry >> since >> + * ACPI 5.0 spec neither support multi-GIC instances nor GIC >> cascade. >> + */ >> + count = acpi_parse_entries(sizeof(struct acpi_table_madt), >> + gic_acpi_parse_madt_distributor, table, >> + ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, >> + MAX_GIC_DISTRIBUTOR); >> + if (count <= 0) { >> + printk("Error during GICD entries parsing\n"); >> + return -EINVAL; >> + } >> + >> + madt = (struct acpi_table_madt *)table; >> + return gic_acpi_validate_init((u64)madt->address); >> +} >> + >> +static int __init acpi_parse_madt(struct acpi_table_header *table) >> +{ >> + struct acpi_table_madt *madt = NULL; >> + madt = (struct acpi_table_madt *)table; >> + >> + if (!madt) >> + return 1; >> + else >> + printk("Local APIC address 0x%08x\n", madt->address); >> + >> + return 0; >> +} >> + >> +int __init acpi_gic_init() >> +{ >> + acpi_status status; >> + int err; >> + >> + status = acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt); >> + >> + if (ACPI_FAILURE(status)) { >> + const char *msg = acpi_format_exception(status); >> + printk("\nFailed to get MADT table, %s\n", msg); >> + return 1; >> + } >> + >> + err = acpi_table_parse(ACPI_SIG_MADT, gic_v2_acpi_init); >> + if (err) >> + printk("\nFailed to initialize GIC IRQ controller\n"); >> + >> + return 0; >> +} >> +#endif >> + >> /* >> * Local variables: >> * mode: C >> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c >> index 317b985..93c8a8a 100644 >> --- a/xen/arch/arm/setup.c >> +++ b/xen/arch/arm/setup.c >> @@ -784,11 +784,12 @@ void __init start_xen(unsigned long boot_phys_offset, >> /* Comment for now take it after GIC initialization */ >> #if defined(CONFIG_ACPI) && defined(CONFIG_ARM_64) >> init_xen_acpi_time(); >> + acpi_gic_init(); >> #else >> init_xen_time(); >> + gic_init(); >> #endif >> >> - gic_init(); >> >> p2m_vmid_allocator_init(); >> >> diff --git a/xen/include/asm-arm/acpi.h b/xen/include/asm-arm/acpi.h >> index c2d25db..01ce28d 100644 >> --- a/xen/include/asm-arm/acpi.h >> +++ b/xen/include/asm-arm/acpi.h >> @@ -106,5 +106,7 @@ static inline void acpi_disable_pci(void) >> #endif >> >> #define MAX_GIC_CPU_INTERFACE 65535 >> +#define MAX_GIC_DISTRIBUTOR 1 /* should be the same as >> MAX_GIC_NR */ >> +extern int __init acpi_gic_init(void); >> >> #endif /*_ASM_ARM_ACPI_H*/ >> -- >> 1.9.1 >> _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |