Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Shanker, Julien, On 2016/4/11 23:25, Shanker Donthineni wrote: Hi Julien, On 04/11/2016 09:27 AM, Julien Grall wrote: Hello Hanjun, On 11/04/16 06:27, Hanjun Guo wrote: On 2016/4/4 19:37, Julien Grall wrote: +static void __init gic_acpi_setup_kvm_info(void) +{ +int irq; + +if (!gic_acpi_collect_virt_info()) { +pr_warn("Unable to get hardware information used for virtualization\n"); +return; +} + +gic_v3_kvm_info.type = GIC_V3; + +irq = acpi_register_gsi(NULL, acpi_data.maint_irq, +acpi_data.maint_irq_mode, +ACPI_ACTIVE_HIGH); +if (irq <= 0) +return; + +gic_v3_kvm_info.maint_irq = irq; + +if (acpi_data.vcpu_base) { Sorry, I'm not familiar with KVM, but I got a question here, will KVM works without valid vcpu_base in GICv3 mode? Yes, KVM works without vcpu_base in GICv3 mode. The vcpu_base will be used for emulatingvGICv2 feature. The vGICv3 emulation isdone through the system registers. vcpu_base is only required for supporting GICv2 on GICv3. Yes, you are right, Thanks for the clarify. Hanjun
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Shanker, Julien, On 2016/4/11 23:25, Shanker Donthineni wrote: Hi Julien, On 04/11/2016 09:27 AM, Julien Grall wrote: Hello Hanjun, On 11/04/16 06:27, Hanjun Guo wrote: On 2016/4/4 19:37, Julien Grall wrote: +static void __init gic_acpi_setup_kvm_info(void) +{ +int irq; + +if (!gic_acpi_collect_virt_info()) { +pr_warn("Unable to get hardware information used for virtualization\n"); +return; +} + +gic_v3_kvm_info.type = GIC_V3; + +irq = acpi_register_gsi(NULL, acpi_data.maint_irq, +acpi_data.maint_irq_mode, +ACPI_ACTIVE_HIGH); +if (irq <= 0) +return; + +gic_v3_kvm_info.maint_irq = irq; + +if (acpi_data.vcpu_base) { Sorry, I'm not familiar with KVM, but I got a question here, will KVM works without valid vcpu_base in GICv3 mode? Yes, KVM works without vcpu_base in GICv3 mode. The vcpu_base will be used for emulatingvGICv2 feature. The vGICv3 emulation isdone through the system registers. vcpu_base is only required for supporting GICv2 on GICv3. Yes, you are right, Thanks for the clarify. Hanjun
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Julien, On 04/11/2016 09:27 AM, Julien Grall wrote: > Hello Hanjun, > > On 11/04/16 06:27, Hanjun Guo wrote: >> On 2016/4/4 19:37, Julien Grall wrote: >>> +static void __init gic_acpi_setup_kvm_info(void) >>> +{ >>> +int irq; >>> + >>> +if (!gic_acpi_collect_virt_info()) { >>> +pr_warn("Unable to get hardware information used for >>> virtualization\n"); >>> +return; >>> +} >>> + >>> +gic_v3_kvm_info.type = GIC_V3; >>> + >>> +irq = acpi_register_gsi(NULL, acpi_data.maint_irq, >>> +acpi_data.maint_irq_mode, >>> +ACPI_ACTIVE_HIGH); >>> +if (irq <= 0) >>> +return; >>> + >>> +gic_v3_kvm_info.maint_irq = irq; >>> + >>> +if (acpi_data.vcpu_base) { >> >> Sorry, I'm not familiar with KVM, but I got a question here, will >> KVM works without valid vcpu_base in GICv3 mode? > Yes, KVM works without vcpu_base in GICv3 mode. The vcpu_base will be used for emulatingvGICv2 feature. The vGICv3 emulation isdone through the system registers. > vcpu_base is only required for supporting GICv2 on GICv3. > Yes, you are right, > Regards, > -- Shanker Donthineni Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Julien, On 04/11/2016 09:27 AM, Julien Grall wrote: > Hello Hanjun, > > On 11/04/16 06:27, Hanjun Guo wrote: >> On 2016/4/4 19:37, Julien Grall wrote: >>> +static void __init gic_acpi_setup_kvm_info(void) >>> +{ >>> +int irq; >>> + >>> +if (!gic_acpi_collect_virt_info()) { >>> +pr_warn("Unable to get hardware information used for >>> virtualization\n"); >>> +return; >>> +} >>> + >>> +gic_v3_kvm_info.type = GIC_V3; >>> + >>> +irq = acpi_register_gsi(NULL, acpi_data.maint_irq, >>> +acpi_data.maint_irq_mode, >>> +ACPI_ACTIVE_HIGH); >>> +if (irq <= 0) >>> +return; >>> + >>> +gic_v3_kvm_info.maint_irq = irq; >>> + >>> +if (acpi_data.vcpu_base) { >> >> Sorry, I'm not familiar with KVM, but I got a question here, will >> KVM works without valid vcpu_base in GICv3 mode? > Yes, KVM works without vcpu_base in GICv3 mode. The vcpu_base will be used for emulatingvGICv2 feature. The vGICv3 emulation isdone through the system registers. > vcpu_base is only required for supporting GICv2 on GICv3. > Yes, you are right, > Regards, > -- Shanker Donthineni Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hello Hanjun, On 11/04/16 06:27, Hanjun Guo wrote: On 2016/4/4 19:37, Julien Grall wrote: +static void __init gic_acpi_setup_kvm_info(void) +{ +int irq; + +if (!gic_acpi_collect_virt_info()) { +pr_warn("Unable to get hardware information used for virtualization\n"); +return; +} + +gic_v3_kvm_info.type = GIC_V3; + +irq = acpi_register_gsi(NULL, acpi_data.maint_irq, +acpi_data.maint_irq_mode, +ACPI_ACTIVE_HIGH); +if (irq <= 0) +return; + +gic_v3_kvm_info.maint_irq = irq; + +if (acpi_data.vcpu_base) { Sorry, I'm not familiar with KVM, but I got a question here, will KVM works without valid vcpu_base in GICv3 mode? vcpu_base is only required for supporting GICv2 on GICv3. Regards, -- Julien Grall
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hello Hanjun, On 11/04/16 06:27, Hanjun Guo wrote: On 2016/4/4 19:37, Julien Grall wrote: +static void __init gic_acpi_setup_kvm_info(void) +{ +int irq; + +if (!gic_acpi_collect_virt_info()) { +pr_warn("Unable to get hardware information used for virtualization\n"); +return; +} + +gic_v3_kvm_info.type = GIC_V3; + +irq = acpi_register_gsi(NULL, acpi_data.maint_irq, +acpi_data.maint_irq_mode, +ACPI_ACTIVE_HIGH); +if (irq <= 0) +return; + +gic_v3_kvm_info.maint_irq = irq; + +if (acpi_data.vcpu_base) { Sorry, I'm not familiar with KVM, but I got a question here, will KVM works without valid vcpu_base in GICv3 mode? vcpu_base is only required for supporting GICv2 on GICv3. Regards, -- Julien Grall
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
On 09/04/16 03:29, Shanker Donthineni wrote: Hi Julien, Hello Shanker, On 04/04/2016 06:37 AM, Julien Grall wrote: +static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *gicc = + (struct acpi_madt_generic_interrupt *)header; + int maint_irq_mode; + static int first_madt = true; + + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; + Do you think GICC parameters are valid for an unusable processor? Good point. We don't know if the value will be valid when the processor is unusable. If not we need a validation check here, some thing like this to skip GICC subtable entry. if (!(gicc->flags & ACPI_MADT_ENABLED)) return 0; I will add this check. Regards, -- Julien Grall
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
On 09/04/16 03:29, Shanker Donthineni wrote: Hi Julien, Hello Shanker, On 04/04/2016 06:37 AM, Julien Grall wrote: +static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *gicc = + (struct acpi_madt_generic_interrupt *)header; + int maint_irq_mode; + static int first_madt = true; + + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; + Do you think GICC parameters are valid for an unusable processor? Good point. We don't know if the value will be valid when the processor is unusable. If not we need a validation check here, some thing like this to skip GICC subtable entry. if (!(gicc->flags & ACPI_MADT_ENABLED)) return 0; I will add this check. Regards, -- Julien Grall
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
On 2016/4/4 19:37, Julien Grall wrote: Fill up the recently introduced gic_kvm_info with the hardware information used for virtualization. Signed-off-by: Julien GrallCc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier --- Changes in v5: - Remove the alignment check for GICV. It's already done in the KVM code. - Fix initialization of KVM with ACPI. Changes in v4: - Change the flow to call gic_kvm_set_info only when all the mandatory information are valid. - Remove unecessary code in ACPI parsing (the virtual control interface doesn't exist for GICv3). - Rework commit message - Rework the ACPI support as it didn't collect hardware info for virtualization when there is more than 1 redistributor region Changes in v3: - Add ACPI support Changes in v2: - Use 0 rather than a negative value to know when the maintenance IRQ is not present. - Use resource for vcpu and vctrl --- drivers/irqchip/irq-gic-v3.c | 110 - include/linux/irqchip/arm-gic-common.h | 1 + 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 50e87e6..08afbfe 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -56,6 +57,8 @@ struct gic_chip_data { static struct gic_chip_data gic_data __read_mostly; static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; +static struct gic_kvm_info gic_v3_kvm_info; + #define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist)) #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K) @@ -901,6 +904,30 @@ static int __init gic_validate_dist_version(void __iomem *dist_base) return 0; } +static void __init gic_of_setup_kvm_info(struct device_node *node) +{ + int ret; + struct resource r; + u32 gicv_idx; + + gic_v3_kvm_info.type = GIC_V3; + + gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0); + if (!gic_v3_kvm_info.maint_irq) + return; + + if (of_property_read_u32(node, "#redistributor-regions", +_idx)) + gicv_idx = 1; + + gicv_idx += 3; /* Also skip GICD, GICC, GICH */ + ret = of_address_to_resource(node, gicv_idx, ); + if (!ret) + gic_v3_kvm_info.vcpu = r; + + gic_set_kvm_info(_v3_kvm_info); +} + static int __init gic_of_init(struct device_node *node, struct device_node *parent) { void __iomem *dist_base; @@ -952,8 +979,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions, redist_stride, >fwnode); - if (!err) + if (!err) { + gic_of_setup_kvm_info(node); return 0; + } out_unmap_rdist: for (i = 0; i < nr_redist_regions; i++) @@ -974,6 +1003,9 @@ static struct struct redist_region *redist_regs; u32 nr_redist_regions; bool single_redist; + u32 maint_irq; + int maint_irq_mode; + phys_addr_t vcpu_base; } acpi_data __initdata; static void __init @@ -1110,7 +1142,81 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header, return true; } +static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *gicc = + (struct acpi_madt_generic_interrupt *)header; + int maint_irq_mode; + static int first_madt = true; + + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; + + if (first_madt) { + first_madt = false; + + acpi_data.maint_irq = gicc->vgic_interrupt; + acpi_data.maint_irq_mode = maint_irq_mode; + acpi_data.vcpu_base = gicc->gicv_base_address; + + return 0; + } + + /* +* The maintenance interrupt and GICV should be the same for every CPU +*/ + if ((acpi_data.maint_irq != gicc->vgic_interrupt) || + (acpi_data.maint_irq_mode != maint_irq_mode) || + (acpi_data.vcpu_base != gicc->gicv_base_address)) + return -EINVAL; + + return 0; +} + +static bool __init gic_acpi_collect_virt_info(void) +{ + int count; + + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, +
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
On 2016/4/4 19:37, Julien Grall wrote: Fill up the recently introduced gic_kvm_info with the hardware information used for virtualization. Signed-off-by: Julien Grall Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier --- Changes in v5: - Remove the alignment check for GICV. It's already done in the KVM code. - Fix initialization of KVM with ACPI. Changes in v4: - Change the flow to call gic_kvm_set_info only when all the mandatory information are valid. - Remove unecessary code in ACPI parsing (the virtual control interface doesn't exist for GICv3). - Rework commit message - Rework the ACPI support as it didn't collect hardware info for virtualization when there is more than 1 redistributor region Changes in v3: - Add ACPI support Changes in v2: - Use 0 rather than a negative value to know when the maintenance IRQ is not present. - Use resource for vcpu and vctrl --- drivers/irqchip/irq-gic-v3.c | 110 - include/linux/irqchip/arm-gic-common.h | 1 + 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 50e87e6..08afbfe 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -56,6 +57,8 @@ struct gic_chip_data { static struct gic_chip_data gic_data __read_mostly; static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; +static struct gic_kvm_info gic_v3_kvm_info; + #define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist)) #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K) @@ -901,6 +904,30 @@ static int __init gic_validate_dist_version(void __iomem *dist_base) return 0; } +static void __init gic_of_setup_kvm_info(struct device_node *node) +{ + int ret; + struct resource r; + u32 gicv_idx; + + gic_v3_kvm_info.type = GIC_V3; + + gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0); + if (!gic_v3_kvm_info.maint_irq) + return; + + if (of_property_read_u32(node, "#redistributor-regions", +_idx)) + gicv_idx = 1; + + gicv_idx += 3; /* Also skip GICD, GICC, GICH */ + ret = of_address_to_resource(node, gicv_idx, ); + if (!ret) + gic_v3_kvm_info.vcpu = r; + + gic_set_kvm_info(_v3_kvm_info); +} + static int __init gic_of_init(struct device_node *node, struct device_node *parent) { void __iomem *dist_base; @@ -952,8 +979,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions, redist_stride, >fwnode); - if (!err) + if (!err) { + gic_of_setup_kvm_info(node); return 0; + } out_unmap_rdist: for (i = 0; i < nr_redist_regions; i++) @@ -974,6 +1003,9 @@ static struct struct redist_region *redist_regs; u32 nr_redist_regions; bool single_redist; + u32 maint_irq; + int maint_irq_mode; + phys_addr_t vcpu_base; } acpi_data __initdata; static void __init @@ -1110,7 +1142,81 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header, return true; } +static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *gicc = + (struct acpi_madt_generic_interrupt *)header; + int maint_irq_mode; + static int first_madt = true; + + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; + + if (first_madt) { + first_madt = false; + + acpi_data.maint_irq = gicc->vgic_interrupt; + acpi_data.maint_irq_mode = maint_irq_mode; + acpi_data.vcpu_base = gicc->gicv_base_address; + + return 0; + } + + /* +* The maintenance interrupt and GICV should be the same for every CPU +*/ + if ((acpi_data.maint_irq != gicc->vgic_interrupt) || + (acpi_data.maint_irq_mode != maint_irq_mode) || + (acpi_data.vcpu_base != gicc->gicv_base_address)) + return -EINVAL; + + return 0; +} + +static bool __init gic_acpi_collect_virt_info(void) +{ + int count; + + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, + gic_acpi_parse_virt_madt_gicc, 0); + + return (count > 0); +} +
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Julien, On 04/04/2016 06:37 AM, Julien Grall wrote: > Fill up the recently introduced gic_kvm_info with the hardware > information used for virtualization. > > Signed-off-by: Julien Grall> Cc: Thomas Gleixner > Cc: Jason Cooper > Cc: Marc Zyngier > > --- > Changes in v5: > - Remove the alignment check for GICV. It's already done in the > KVM code. > - Fix initialization of KVM with ACPI. > > Changes in v4: > - Change the flow to call gic_kvm_set_info only when all the > mandatory information are valid. > - Remove unecessary code in ACPI parsing (the virtual control > interface doesn't exist for GICv3). > - Rework commit message > - Rework the ACPI support as it didn't collect hardware info for > virtualization when there is more than 1 redistributor region > > Changes in v3: > - Add ACPI support > > Changes in v2: > - Use 0 rather than a negative value to know when the maintenance > IRQ > is not present. > - Use resource for vcpu and vctrl > --- > drivers/irqchip/irq-gic-v3.c | 110 > - > include/linux/irqchip/arm-gic-common.h | 1 + > 2 files changed, 110 insertions(+), 1 deletion(-) > > diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c > index 50e87e6..08afbfe 100644 > --- a/drivers/irqchip/irq-gic-v3.c > +++ b/drivers/irqchip/irq-gic-v3.c > @@ -28,6 +28,7 @@ > #include > > #include > +#include > #include > > #include > @@ -56,6 +57,8 @@ struct gic_chip_data { > static struct gic_chip_data gic_data __read_mostly; > static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; > > +static struct gic_kvm_info gic_v3_kvm_info; > + > #define gic_data_rdist() > (this_cpu_ptr(gic_data.rdists.rdist)) > #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) > #define gic_data_rdist_sgi_base()(gic_data_rdist_rd_base() + > SZ_64K) > @@ -901,6 +904,30 @@ static int __init gic_validate_dist_version(void > __iomem *dist_base) > return 0; > } > > +static void __init gic_of_setup_kvm_info(struct device_node *node) > +{ > + int ret; > + struct resource r; > + u32 gicv_idx; > + > + gic_v3_kvm_info.type = GIC_V3; > + > + gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0); > + if (!gic_v3_kvm_info.maint_irq) > + return; > + > + if (of_property_read_u32(node, "#redistributor-regions", > + _idx)) > + gicv_idx = 1; > + > + gicv_idx += 3; /* Also skip GICD, GICC, GICH */ > + ret = of_address_to_resource(node, gicv_idx, ); > + if (!ret) > + gic_v3_kvm_info.vcpu = r; > + > + gic_set_kvm_info(_v3_kvm_info); > +} > + > static int __init gic_of_init(struct device_node *node, struct > device_node *parent) > { > void __iomem *dist_base; > @@ -952,8 +979,10 @@ static int __init gic_of_init(struct device_node > *node, struct device_node *pare > > err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions, >redist_stride, >fwnode); > - if (!err) > + if (!err) { > + gic_of_setup_kvm_info(node); > return 0; > + } > > out_unmap_rdist: > for (i = 0; i < nr_redist_regions; i++) > @@ -974,6 +1003,9 @@ static struct > struct redist_region *redist_regs; > u32 nr_redist_regions; > bool single_redist; > + u32 maint_irq; > + int maint_irq_mode; > + phys_addr_t vcpu_base; > } acpi_data __initdata; > > static void __init > @@ -1110,7 +1142,81 @@ static bool __init acpi_validate_gic_table(struct > acpi_subtable_header *header, > return true; > } > > +static int __init gic_acpi_parse_virt_madt_gicc(struct > acpi_subtable_header *header, > + const unsigned long end) > +{ > + struct acpi_madt_generic_interrupt *gicc = > + (struct acpi_madt_generic_interrupt *)header; > + int maint_irq_mode; > + static int first_madt = true; > + > + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? > + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; > + Do you think GICC parameters are valid for an unusable processor? If not we need a validation check here, some thing like this to skip GICC subtable entry. if (!(gicc->flags & ACPI_MADT_ENABLED)) return 0; > + if (first_madt) { > + first_madt = false; > + > + acpi_data.maint_irq = gicc->vgic_interrupt; > + acpi_data.maint_irq_mode = maint_irq_mode; > + acpi_data.vcpu_base = gicc->gicv_base_address; > + > + return 0; > + } > + > + /* > + * The maintenance interrupt and GICV should be the same for every > CPU > + */ > + if
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Julien, On 04/04/2016 06:37 AM, Julien Grall wrote: > Fill up the recently introduced gic_kvm_info with the hardware > information used for virtualization. > > Signed-off-by: Julien Grall > Cc: Thomas Gleixner > Cc: Jason Cooper > Cc: Marc Zyngier > > --- > Changes in v5: > - Remove the alignment check for GICV. It's already done in the > KVM code. > - Fix initialization of KVM with ACPI. > > Changes in v4: > - Change the flow to call gic_kvm_set_info only when all the > mandatory information are valid. > - Remove unecessary code in ACPI parsing (the virtual control > interface doesn't exist for GICv3). > - Rework commit message > - Rework the ACPI support as it didn't collect hardware info for > virtualization when there is more than 1 redistributor region > > Changes in v3: > - Add ACPI support > > Changes in v2: > - Use 0 rather than a negative value to know when the maintenance > IRQ > is not present. > - Use resource for vcpu and vctrl > --- > drivers/irqchip/irq-gic-v3.c | 110 > - > include/linux/irqchip/arm-gic-common.h | 1 + > 2 files changed, 110 insertions(+), 1 deletion(-) > > diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c > index 50e87e6..08afbfe 100644 > --- a/drivers/irqchip/irq-gic-v3.c > +++ b/drivers/irqchip/irq-gic-v3.c > @@ -28,6 +28,7 @@ > #include > > #include > +#include > #include > > #include > @@ -56,6 +57,8 @@ struct gic_chip_data { > static struct gic_chip_data gic_data __read_mostly; > static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; > > +static struct gic_kvm_info gic_v3_kvm_info; > + > #define gic_data_rdist() > (this_cpu_ptr(gic_data.rdists.rdist)) > #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) > #define gic_data_rdist_sgi_base()(gic_data_rdist_rd_base() + > SZ_64K) > @@ -901,6 +904,30 @@ static int __init gic_validate_dist_version(void > __iomem *dist_base) > return 0; > } > > +static void __init gic_of_setup_kvm_info(struct device_node *node) > +{ > + int ret; > + struct resource r; > + u32 gicv_idx; > + > + gic_v3_kvm_info.type = GIC_V3; > + > + gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0); > + if (!gic_v3_kvm_info.maint_irq) > + return; > + > + if (of_property_read_u32(node, "#redistributor-regions", > + _idx)) > + gicv_idx = 1; > + > + gicv_idx += 3; /* Also skip GICD, GICC, GICH */ > + ret = of_address_to_resource(node, gicv_idx, ); > + if (!ret) > + gic_v3_kvm_info.vcpu = r; > + > + gic_set_kvm_info(_v3_kvm_info); > +} > + > static int __init gic_of_init(struct device_node *node, struct > device_node *parent) > { > void __iomem *dist_base; > @@ -952,8 +979,10 @@ static int __init gic_of_init(struct device_node > *node, struct device_node *pare > > err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions, >redist_stride, >fwnode); > - if (!err) > + if (!err) { > + gic_of_setup_kvm_info(node); > return 0; > + } > > out_unmap_rdist: > for (i = 0; i < nr_redist_regions; i++) > @@ -974,6 +1003,9 @@ static struct > struct redist_region *redist_regs; > u32 nr_redist_regions; > bool single_redist; > + u32 maint_irq; > + int maint_irq_mode; > + phys_addr_t vcpu_base; > } acpi_data __initdata; > > static void __init > @@ -1110,7 +1142,81 @@ static bool __init acpi_validate_gic_table(struct > acpi_subtable_header *header, > return true; > } > > +static int __init gic_acpi_parse_virt_madt_gicc(struct > acpi_subtable_header *header, > + const unsigned long end) > +{ > + struct acpi_madt_generic_interrupt *gicc = > + (struct acpi_madt_generic_interrupt *)header; > + int maint_irq_mode; > + static int first_madt = true; > + > + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? > + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; > + Do you think GICC parameters are valid for an unusable processor? If not we need a validation check here, some thing like this to skip GICC subtable entry. if (!(gicc->flags & ACPI_MADT_ENABLED)) return 0; > + if (first_madt) { > + first_madt = false; > + > + acpi_data.maint_irq = gicc->vgic_interrupt; > + acpi_data.maint_irq_mode = maint_irq_mode; > + acpi_data.vcpu_base = gicc->gicv_base_address; > + > + return 0; > + } > + > + /* > + * The maintenance interrupt and GICV should be the same for every > CPU > + */ > + if ((acpi_data.maint_irq != gicc->vgic_interrupt) || > + (acpi_data.maint_irq_mode !=
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Christoffer, On 06/04/2016 18:22, Christoffer Dall wrote: On Mon, Apr 04, 2016 at 12:37:37PM +0100, Julien Grall wrote: +static void __init gic_acpi_setup_kvm_info(void) +{ + int irq; + + if (!gic_acpi_collect_virt_info()) { + pr_warn("Unable to get hardware information used for virtualization\n"); perhaps this should say something about gicv3 as well? Actually, none of the pr_* call contain GICv3 and there is no pr_fmt. I'm thinking to send a patch to add pr_fmt in the GICv3 driver. Otherwise (with my extremely limited acpi understanding): Reviewed-by: Christoffer DallThank you! Regards, -- Julien Grall
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
Hi Christoffer, On 06/04/2016 18:22, Christoffer Dall wrote: On Mon, Apr 04, 2016 at 12:37:37PM +0100, Julien Grall wrote: +static void __init gic_acpi_setup_kvm_info(void) +{ + int irq; + + if (!gic_acpi_collect_virt_info()) { + pr_warn("Unable to get hardware information used for virtualization\n"); perhaps this should say something about gicv3 as well? Actually, none of the pr_* call contain GICv3 and there is no pr_fmt. I'm thinking to send a patch to add pr_fmt in the GICv3 driver. Otherwise (with my extremely limited acpi understanding): Reviewed-by: Christoffer Dall Thank you! Regards, -- Julien Grall
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
On Mon, Apr 04, 2016 at 12:37:37PM +0100, Julien Grall wrote: > Fill up the recently introduced gic_kvm_info with the hardware > information used for virtualization. > > Signed-off-by: Julien Grall> Cc: Thomas Gleixner > Cc: Jason Cooper > Cc: Marc Zyngier > > --- > Changes in v5: > - Remove the alignment check for GICV. It's already done in the > KVM code. > - Fix initialization of KVM with ACPI. > > Changes in v4: > - Change the flow to call gic_kvm_set_info only when all the > mandatory information are valid. > - Remove unecessary code in ACPI parsing (the virtual control > interface doesn't exist for GICv3). > - Rework commit message > - Rework the ACPI support as it didn't collect hardware info for > virtualization when there is more than 1 redistributor region > > Changes in v3: > - Add ACPI support > > Changes in v2: > - Use 0 rather than a negative value to know when the maintenance IRQ > is not present. > - Use resource for vcpu and vctrl > --- > drivers/irqchip/irq-gic-v3.c | 110 > - > include/linux/irqchip/arm-gic-common.h | 1 + > 2 files changed, 110 insertions(+), 1 deletion(-) > > diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c > index 50e87e6..08afbfe 100644 > --- a/drivers/irqchip/irq-gic-v3.c > +++ b/drivers/irqchip/irq-gic-v3.c > @@ -28,6 +28,7 @@ > #include > > #include > +#include > #include > > #include > @@ -56,6 +57,8 @@ struct gic_chip_data { > static struct gic_chip_data gic_data __read_mostly; > static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; > > +static struct gic_kvm_info gic_v3_kvm_info; > + > #define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist)) > #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) > #define gic_data_rdist_sgi_base()(gic_data_rdist_rd_base() + SZ_64K) > @@ -901,6 +904,30 @@ static int __init gic_validate_dist_version(void __iomem > *dist_base) > return 0; > } > > +static void __init gic_of_setup_kvm_info(struct device_node *node) > +{ > + int ret; > + struct resource r; > + u32 gicv_idx; > + > + gic_v3_kvm_info.type = GIC_V3; > + > + gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0); > + if (!gic_v3_kvm_info.maint_irq) > + return; > + > + if (of_property_read_u32(node, "#redistributor-regions", > + _idx)) > + gicv_idx = 1; > + > + gicv_idx += 3; /* Also skip GICD, GICC, GICH */ > + ret = of_address_to_resource(node, gicv_idx, ); > + if (!ret) > + gic_v3_kvm_info.vcpu = r; > + > + gic_set_kvm_info(_v3_kvm_info); > +} > + > static int __init gic_of_init(struct device_node *node, struct device_node > *parent) > { > void __iomem *dist_base; > @@ -952,8 +979,10 @@ static int __init gic_of_init(struct device_node *node, > struct device_node *pare > > err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions, >redist_stride, >fwnode); > - if (!err) > + if (!err) { > + gic_of_setup_kvm_info(node); > return 0; > + } > > out_unmap_rdist: > for (i = 0; i < nr_redist_regions; i++) > @@ -974,6 +1003,9 @@ static struct > struct redist_region *redist_regs; > u32 nr_redist_regions; > bool single_redist; > + u32 maint_irq; > + int maint_irq_mode; > + phys_addr_t vcpu_base; > } acpi_data __initdata; > > static void __init > @@ -1110,7 +1142,81 @@ static bool __init acpi_validate_gic_table(struct > acpi_subtable_header *header, > return true; > } > > +static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header > *header, > + const unsigned long end) > +{ > + struct acpi_madt_generic_interrupt *gicc = > + (struct acpi_madt_generic_interrupt *)header; > + int maint_irq_mode; > + static int first_madt = true; > + > + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? > + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; > + > + if (first_madt) { > + first_madt = false; > + > + acpi_data.maint_irq = gicc->vgic_interrupt; > + acpi_data.maint_irq_mode = maint_irq_mode; > + acpi_data.vcpu_base = gicc->gicv_base_address; > + > + return 0; > + } > + > + /* > + * The maintenance interrupt and GICV should be the same for every CPU > + */ > + if ((acpi_data.maint_irq != gicc->vgic_interrupt) || > + (acpi_data.maint_irq_mode != maint_irq_mode) || > + (acpi_data.vcpu_base != gicc->gicv_base_address)) > + return -EINVAL; > + > + return 0; >
Re: [PATCH v5 6/9] irqchip/gic-v3: Parse and export virtual GIC information
On Mon, Apr 04, 2016 at 12:37:37PM +0100, Julien Grall wrote: > Fill up the recently introduced gic_kvm_info with the hardware > information used for virtualization. > > Signed-off-by: Julien Grall > Cc: Thomas Gleixner > Cc: Jason Cooper > Cc: Marc Zyngier > > --- > Changes in v5: > - Remove the alignment check for GICV. It's already done in the > KVM code. > - Fix initialization of KVM with ACPI. > > Changes in v4: > - Change the flow to call gic_kvm_set_info only when all the > mandatory information are valid. > - Remove unecessary code in ACPI parsing (the virtual control > interface doesn't exist for GICv3). > - Rework commit message > - Rework the ACPI support as it didn't collect hardware info for > virtualization when there is more than 1 redistributor region > > Changes in v3: > - Add ACPI support > > Changes in v2: > - Use 0 rather than a negative value to know when the maintenance IRQ > is not present. > - Use resource for vcpu and vctrl > --- > drivers/irqchip/irq-gic-v3.c | 110 > - > include/linux/irqchip/arm-gic-common.h | 1 + > 2 files changed, 110 insertions(+), 1 deletion(-) > > diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c > index 50e87e6..08afbfe 100644 > --- a/drivers/irqchip/irq-gic-v3.c > +++ b/drivers/irqchip/irq-gic-v3.c > @@ -28,6 +28,7 @@ > #include > > #include > +#include > #include > > #include > @@ -56,6 +57,8 @@ struct gic_chip_data { > static struct gic_chip_data gic_data __read_mostly; > static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; > > +static struct gic_kvm_info gic_v3_kvm_info; > + > #define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist)) > #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) > #define gic_data_rdist_sgi_base()(gic_data_rdist_rd_base() + SZ_64K) > @@ -901,6 +904,30 @@ static int __init gic_validate_dist_version(void __iomem > *dist_base) > return 0; > } > > +static void __init gic_of_setup_kvm_info(struct device_node *node) > +{ > + int ret; > + struct resource r; > + u32 gicv_idx; > + > + gic_v3_kvm_info.type = GIC_V3; > + > + gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0); > + if (!gic_v3_kvm_info.maint_irq) > + return; > + > + if (of_property_read_u32(node, "#redistributor-regions", > + _idx)) > + gicv_idx = 1; > + > + gicv_idx += 3; /* Also skip GICD, GICC, GICH */ > + ret = of_address_to_resource(node, gicv_idx, ); > + if (!ret) > + gic_v3_kvm_info.vcpu = r; > + > + gic_set_kvm_info(_v3_kvm_info); > +} > + > static int __init gic_of_init(struct device_node *node, struct device_node > *parent) > { > void __iomem *dist_base; > @@ -952,8 +979,10 @@ static int __init gic_of_init(struct device_node *node, > struct device_node *pare > > err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions, >redist_stride, >fwnode); > - if (!err) > + if (!err) { > + gic_of_setup_kvm_info(node); > return 0; > + } > > out_unmap_rdist: > for (i = 0; i < nr_redist_regions; i++) > @@ -974,6 +1003,9 @@ static struct > struct redist_region *redist_regs; > u32 nr_redist_regions; > bool single_redist; > + u32 maint_irq; > + int maint_irq_mode; > + phys_addr_t vcpu_base; > } acpi_data __initdata; > > static void __init > @@ -1110,7 +1142,81 @@ static bool __init acpi_validate_gic_table(struct > acpi_subtable_header *header, > return true; > } > > +static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header > *header, > + const unsigned long end) > +{ > + struct acpi_madt_generic_interrupt *gicc = > + (struct acpi_madt_generic_interrupt *)header; > + int maint_irq_mode; > + static int first_madt = true; > + > + maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ? > + ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; > + > + if (first_madt) { > + first_madt = false; > + > + acpi_data.maint_irq = gicc->vgic_interrupt; > + acpi_data.maint_irq_mode = maint_irq_mode; > + acpi_data.vcpu_base = gicc->gicv_base_address; > + > + return 0; > + } > + > + /* > + * The maintenance interrupt and GICV should be the same for every CPU > + */ > + if ((acpi_data.maint_irq != gicc->vgic_interrupt) || > + (acpi_data.maint_irq_mode != maint_irq_mode) || > + (acpi_data.vcpu_base != gicc->gicv_base_address)) > + return -EINVAL; > + > + return 0; > +} > + > +static bool __init gic_acpi_collect_virt_info(void) > +{ > + int count; >