Re: [PATCH V2 3/5] kvm: arm64: Detect GIC version for proper ACPI vGIC probing
On 10/06/15 05:16, Wei Huang wrote: There are two GICs (GICv2 and GICv3) supported by KVM. So it is necessary to find out GIC version before calling ACPI probing functions defined in vgic-v2.c and vgic-v3.c. This patch detects GIC version by checking gic_version field of GIC distributor, which was defined since ACPI 6.0. In case of ACPI 5.1, we use manual hardware discovery to find out GIC version. NOTE: This patch is based on a recent patch by Hanjun Guo. Well, this is really a duplicate of Hanjun's patch, and I'd rather have some common infrastructure. Surely it should be possible for the ACPI GIC code to export the necessary entry points, or even to provide the required information? Thanks, M. Signed-off-by: Hanjun Guo hanjun@linaro.org Signed-off-by: Wei Huang w...@redhat.com --- include/kvm/arm_vgic.h | 18 + virt/kvm/arm/vgic-v2.c | 10 + virt/kvm/arm/vgic-v3.c | 10 + virt/kvm/arm/vgic.c| 100 - 4 files changed, 137 insertions(+), 1 deletion(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 3ee732a..7a44b08 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -24,6 +24,7 @@ #include linux/irqreturn.h #include linux/spinlock.h #include linux/types.h +#include linux/acpi.h #include kvm/iodev.h #define VGIC_NR_IRQS_LEGACY 256 @@ -335,10 +336,18 @@ int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu); int vgic_v2_dt_probe(struct device_node *vgic_node, const struct vgic_ops **ops, const struct vgic_params **params); +#ifdef CONFIG_ACPI +int vgic_v2_acpi_probe(struct acpi_madt_generic_interrupt *, +const struct vgic_ops **ops, +const struct vgic_params **params); +#endif /* CONFIG_ACPI */ #ifdef CONFIG_ARM_GIC_V3 int vgic_v3_dt_probe(struct device_node *vgic_node, const struct vgic_ops **ops, const struct vgic_params **params); +int vgic_v3_acpi_probe(struct acpi_madt_generic_interrupt *, +const struct vgic_ops **ops, +const struct vgic_params **params); #else static inline int vgic_v3_dt_probe(struct device_node *vgic_node, const struct vgic_ops **ops, @@ -346,6 +355,15 @@ static inline int vgic_v3_dt_probe(struct device_node *vgic_node, { return -ENODEV; } + +#ifdef CONFIG_ACPI +int vgic_v3_acpi_probe(struct acpi_madt_generic_interrupt *, +const struct vgic_ops **ops, +const struct vgic_params **params) +{ + return -ENODEV; +} +#endif /* CONFIG_ACPI */ #endif #endif diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index 295996f..711de82 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -23,6 +23,7 @@ #include linux/of.h #include linux/of_address.h #include linux/of_irq.h +#include linux/acpi.h #include linux/irqchip/arm-gic.h @@ -257,3 +258,12 @@ out: of_node_put(vgic_node); return ret; } + +#ifdef CONFIG_ACPI +int vgic_v2_acpi_probe(struct acpi_madt_generic_interrupt *vgic_acpi, +const struct vgic_ops **ops, +const struct vgic_params **params) +{ + return -EINVAL; +} +#endif /* CONFIG_ACPI */ diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index 91814e2..99d0f9f 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c @@ -23,6 +23,7 @@ #include linux/of.h #include linux/of_address.h #include linux/of_irq.h +#include linux/acpi.h #include linux/irqchip/arm-gic-v3.h @@ -285,3 +286,12 @@ out: of_node_put(vgic_node); return ret; } + +#ifdef CONFIG_ACPI +int vgic_v3_acpi_probe(struct acpi_madt_generic_interrupt *vgic_acpi, +const struct vgic_ops **ops, +const struct vgic_params **params) +{ + return -EINVAL; +} +#endif /* CONFIG_ACPI */ diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index b4010f0..cd09877 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -28,6 +28,7 @@ #include linux/acpi.h #include linux/irqchip/arm-gic.h +#include linux/irqchip/arm-gic-v3.h #include asm/kvm_emulate.h #include asm/kvm_arm.h @@ -2114,9 +2115,106 @@ static int kvm_vgic_dt_probe(void) } #ifdef CONFIG_ACPI +u8 gic_version = ACPI_MADT_GIC_VER_UNKNOWN; +phys_addr_t dist_phy_base; +static struct acpi_madt_generic_interrupt *vgic_acpi; + +static void gic_get_acpi_header(struct acpi_subtable_header *header) +{ + vgic_acpi = (struct acpi_madt_generic_interrupt *)header; +} + +static int gic_parse_distributor(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_distributor *dist; + + dist = (struct
[PATCH V2 3/5] kvm: arm64: Detect GIC version for proper ACPI vGIC probing
There are two GICs (GICv2 and GICv3) supported by KVM. So it is necessary to find out GIC version before calling ACPI probing functions defined in vgic-v2.c and vgic-v3.c. This patch detects GIC version by checking gic_version field of GIC distributor, which was defined since ACPI 6.0. In case of ACPI 5.1, we use manual hardware discovery to find out GIC version. NOTE: This patch is based on a recent patch by Hanjun Guo. Signed-off-by: Hanjun Guo hanjun@linaro.org Signed-off-by: Wei Huang w...@redhat.com --- include/kvm/arm_vgic.h | 18 + virt/kvm/arm/vgic-v2.c | 10 + virt/kvm/arm/vgic-v3.c | 10 + virt/kvm/arm/vgic.c| 100 - 4 files changed, 137 insertions(+), 1 deletion(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 3ee732a..7a44b08 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -24,6 +24,7 @@ #include linux/irqreturn.h #include linux/spinlock.h #include linux/types.h +#include linux/acpi.h #include kvm/iodev.h #define VGIC_NR_IRQS_LEGACY256 @@ -335,10 +336,18 @@ int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu); int vgic_v2_dt_probe(struct device_node *vgic_node, const struct vgic_ops **ops, const struct vgic_params **params); +#ifdef CONFIG_ACPI +int vgic_v2_acpi_probe(struct acpi_madt_generic_interrupt *, + const struct vgic_ops **ops, + const struct vgic_params **params); +#endif /* CONFIG_ACPI */ #ifdef CONFIG_ARM_GIC_V3 int vgic_v3_dt_probe(struct device_node *vgic_node, const struct vgic_ops **ops, const struct vgic_params **params); +int vgic_v3_acpi_probe(struct acpi_madt_generic_interrupt *, + const struct vgic_ops **ops, + const struct vgic_params **params); #else static inline int vgic_v3_dt_probe(struct device_node *vgic_node, const struct vgic_ops **ops, @@ -346,6 +355,15 @@ static inline int vgic_v3_dt_probe(struct device_node *vgic_node, { return -ENODEV; } + +#ifdef CONFIG_ACPI +int vgic_v3_acpi_probe(struct acpi_madt_generic_interrupt *, + const struct vgic_ops **ops, + const struct vgic_params **params) +{ + return -ENODEV; +} +#endif /* CONFIG_ACPI */ #endif #endif diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index 295996f..711de82 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -23,6 +23,7 @@ #include linux/of.h #include linux/of_address.h #include linux/of_irq.h +#include linux/acpi.h #include linux/irqchip/arm-gic.h @@ -257,3 +258,12 @@ out: of_node_put(vgic_node); return ret; } + +#ifdef CONFIG_ACPI +int vgic_v2_acpi_probe(struct acpi_madt_generic_interrupt *vgic_acpi, + const struct vgic_ops **ops, + const struct vgic_params **params) +{ + return -EINVAL; +} +#endif /* CONFIG_ACPI */ diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index 91814e2..99d0f9f 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c @@ -23,6 +23,7 @@ #include linux/of.h #include linux/of_address.h #include linux/of_irq.h +#include linux/acpi.h #include linux/irqchip/arm-gic-v3.h @@ -285,3 +286,12 @@ out: of_node_put(vgic_node); return ret; } + +#ifdef CONFIG_ACPI +int vgic_v3_acpi_probe(struct acpi_madt_generic_interrupt *vgic_acpi, + const struct vgic_ops **ops, + const struct vgic_params **params) +{ + return -EINVAL; +} +#endif /* CONFIG_ACPI */ diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index b4010f0..cd09877 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -28,6 +28,7 @@ #include linux/acpi.h #include linux/irqchip/arm-gic.h +#include linux/irqchip/arm-gic-v3.h #include asm/kvm_emulate.h #include asm/kvm_arm.h @@ -2114,9 +2115,106 @@ static int kvm_vgic_dt_probe(void) } #ifdef CONFIG_ACPI +u8 gic_version = ACPI_MADT_GIC_VER_UNKNOWN; +phys_addr_t dist_phy_base; +static struct acpi_madt_generic_interrupt *vgic_acpi; + +static void gic_get_acpi_header(struct acpi_subtable_header *header) +{ + vgic_acpi = (struct acpi_madt_generic_interrupt *)header; +} + +static int gic_parse_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; + + gic_version = dist-gic_version; + dist_phy_base = dist-base_address; + + return 0; +} + +static int gic_match_redist(struct acpi_subtable_header *header, + const unsigned long end) +{ + return 0; +} + +static bool