|
|
@@ -102,6 +102,8 @@ static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
|
|
|
|
|
|
static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly;
|
|
|
|
|
|
+static struct gic_kvm_info gic_v2_kvm_info;
|
|
|
+
|
|
|
#ifdef CONFIG_GIC_NON_BANKED
|
|
|
static void __iomem *gic_get_percpu_base(union gic_base *base)
|
|
|
{
|
|
|
@@ -1189,6 +1191,29 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static void __init gic_of_setup_kvm_info(struct device_node *node)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ struct resource *vctrl_res = &gic_v2_kvm_info.vctrl;
|
|
|
+ struct resource *vcpu_res = &gic_v2_kvm_info.vcpu;
|
|
|
+
|
|
|
+ gic_v2_kvm_info.type = GIC_V2;
|
|
|
+
|
|
|
+ gic_v2_kvm_info.maint_irq = irq_of_parse_and_map(node, 0);
|
|
|
+ if (!gic_v2_kvm_info.maint_irq)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ret = of_address_to_resource(node, 2, vctrl_res);
|
|
|
+ if (ret)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ret = of_address_to_resource(node, 3, vcpu_res);
|
|
|
+ if (ret)
|
|
|
+ return;
|
|
|
+
|
|
|
+ gic_set_kvm_info(&gic_v2_kvm_info);
|
|
|
+}
|
|
|
+
|
|
|
int __init
|
|
|
gic_of_init(struct device_node *node, struct device_node *parent)
|
|
|
{
|
|
|
@@ -1218,8 +1243,10 @@ gic_of_init(struct device_node *node, struct device_node *parent)
|
|
|
|
|
|
__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
|
|
|
&node->fwnode);
|
|
|
- if (!gic_cnt)
|
|
|
+ if (!gic_cnt) {
|
|
|
gic_init_physaddr(node);
|
|
|
+ gic_of_setup_kvm_info(node);
|
|
|
+ }
|
|
|
|
|
|
if (parent) {
|
|
|
irq = irq_of_parse_and_map(node, 0);
|
|
|
@@ -1248,6 +1275,10 @@ IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
|
|
|
static struct
|
|
|
{
|
|
|
phys_addr_t cpu_phys_base;
|
|
|
+ u32 maint_irq;
|
|
|
+ int maint_irq_mode;
|
|
|
+ phys_addr_t vctrl_base;
|
|
|
+ phys_addr_t vcpu_base;
|
|
|
} acpi_data __initdata;
|
|
|
|
|
|
static int __init
|
|
|
@@ -1272,6 +1303,12 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
|
|
|
return -EINVAL;
|
|
|
|
|
|
acpi_data.cpu_phys_base = gic_cpu_base;
|
|
|
+ acpi_data.maint_irq = processor->vgic_interrupt;
|
|
|
+ acpi_data.maint_irq_mode = (processor->flags & ACPI_MADT_VGIC_IRQ_MODE) ?
|
|
|
+ ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
|
|
|
+ acpi_data.vctrl_base = processor->gich_base_address;
|
|
|
+ acpi_data.vcpu_base = processor->gicv_base_address;
|
|
|
+
|
|
|
cpu_base_assigned = 1;
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -1302,6 +1339,41 @@ static bool __init gic_validate_dist(struct acpi_subtable_header *header,
|
|
|
|
|
|
#define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K)
|
|
|
#define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K)
|
|
|
+#define ACPI_GICV2_VCTRL_MEM_SIZE (SZ_4K)
|
|
|
+#define ACPI_GICV2_VCPU_MEM_SIZE (SZ_8K)
|
|
|
+
|
|
|
+static void __init gic_acpi_setup_kvm_info(void)
|
|
|
+{
|
|
|
+ int irq;
|
|
|
+ struct resource *vctrl_res = &gic_v2_kvm_info.vctrl;
|
|
|
+ struct resource *vcpu_res = &gic_v2_kvm_info.vcpu;
|
|
|
+
|
|
|
+ gic_v2_kvm_info.type = GIC_V2;
|
|
|
+
|
|
|
+ if (!acpi_data.vctrl_base)
|
|
|
+ return;
|
|
|
+
|
|
|
+ vctrl_res->flags = IORESOURCE_MEM;
|
|
|
+ vctrl_res->start = acpi_data.vctrl_base;
|
|
|
+ vctrl_res->end = vctrl_res->start + ACPI_GICV2_VCTRL_MEM_SIZE - 1;
|
|
|
+
|
|
|
+ if (!acpi_data.vcpu_base)
|
|
|
+ return;
|
|
|
+
|
|
|
+ vcpu_res->flags = IORESOURCE_MEM;
|
|
|
+ vcpu_res->start = acpi_data.vcpu_base;
|
|
|
+ vcpu_res->end = vcpu_res->start + ACPI_GICV2_VCPU_MEM_SIZE - 1;
|
|
|
+
|
|
|
+ irq = acpi_register_gsi(NULL, acpi_data.maint_irq,
|
|
|
+ acpi_data.maint_irq_mode,
|
|
|
+ ACPI_ACTIVE_HIGH);
|
|
|
+ if (irq <= 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ gic_v2_kvm_info.maint_irq = irq;
|
|
|
+
|
|
|
+ gic_set_kvm_info(&gic_v2_kvm_info);
|
|
|
+}
|
|
|
|
|
|
static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
|
|
|
const unsigned long end)
|
|
|
@@ -1359,6 +1431,8 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
|
|
|
if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
|
|
|
gicv2m_init(NULL, gic_data[0].domain);
|
|
|
|
|
|
+ gic_acpi_setup_kvm_info();
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
|