This series is an attempt to provide CPU hotplug support on ARM virt platform. This is based on ACPI GED device. We should enable ACPI support, and use vGICv3 and 64bit CPU to support CPU hotplug. Under KVM accel, the KVM vCPUs is pre-created. Besides, vGIC IRIs is pre-created too. However, QEMU vCPU objects are defer-created. Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
198 lines
8.1 KiB
Diff
198 lines
8.1 KiB
Diff
From de97ff4a01008ad98f7d69adc4b84843fff3ce19 Mon Sep 17 00:00:00 2001
|
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
Date: Fri, 10 Apr 2020 10:59:55 +0800
|
|
Subject: [PATCH] intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif
|
|
|
|
The CPU object of hotplugged CPU will be defer-created (during
|
|
hotplug session), so we must factor out some code to let it can
|
|
be applied to individual CPU.
|
|
|
|
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
---
|
|
hw/intc/arm_gicv3.c | 5 +-
|
|
hw/intc/arm_gicv3_cpuif.c | 122 ++++++++++++++++++--------------------
|
|
hw/intc/gicv3_internal.h | 2 +-
|
|
3 files changed, 64 insertions(+), 65 deletions(-)
|
|
|
|
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
|
|
index 66eaa97198..2fe79f794d 100644
|
|
--- a/hw/intc/arm_gicv3.c
|
|
+++ b/hw/intc/arm_gicv3.c
|
|
@@ -367,6 +367,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
|
|
GICv3State *s = ARM_GICV3(dev);
|
|
ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s);
|
|
Error *local_err = NULL;
|
|
+ int i;
|
|
|
|
agc->parent_realize(dev, &local_err);
|
|
if (local_err) {
|
|
@@ -386,7 +387,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
|
|
return;
|
|
}
|
|
|
|
- gicv3_init_cpuif(s);
|
|
+ for (i = 0; i < s->num_cpu; i++) {
|
|
+ gicv3_init_one_cpuif(s, i);
|
|
+ }
|
|
}
|
|
|
|
static void arm_gicv3_class_init(ObjectClass *klass, void *data)
|
|
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
|
|
index 3b212d91c8..56aa5efede 100644
|
|
--- a/hw/intc/arm_gicv3_cpuif.c
|
|
+++ b/hw/intc/arm_gicv3_cpuif.c
|
|
@@ -2597,78 +2597,74 @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
|
|
gicv3_cpuif_update(cs);
|
|
}
|
|
|
|
-void gicv3_init_cpuif(GICv3State *s)
|
|
+void gicv3_init_one_cpuif(GICv3State *s, int ncpu)
|
|
{
|
|
/* Called from the GICv3 realize function; register our system
|
|
* registers with the CPU
|
|
*/
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < s->num_cpu; i++) {
|
|
- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
|
|
- GICv3CPUState *cs = &s->cpu[i];
|
|
-
|
|
- /* Note that we can't just use the GICv3CPUState as an opaque pointer
|
|
- * in define_arm_cp_regs_with_opaque(), because when we're called back
|
|
- * it might be with code translated by CPU 0 but run by CPU 1, in
|
|
- * which case we'd get the wrong value.
|
|
- * So instead we define the regs with no ri->opaque info, and
|
|
- * get back to the GICv3CPUState from the CPUARMState.
|
|
- */
|
|
- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
|
|
- if (arm_feature(&cpu->env, ARM_FEATURE_EL2)
|
|
- && cpu->gic_num_lrs) {
|
|
- int j;
|
|
+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu));
|
|
+ GICv3CPUState *cs = &s->cpu[ncpu];
|
|
+
|
|
+ /* Note that we can't just use the GICv3CPUState as an opaque pointer
|
|
+ * in define_arm_cp_regs_with_opaque(), because when we're called back
|
|
+ * it might be with code translated by CPU 0 but run by CPU 1, in
|
|
+ * which case we'd get the wrong value.
|
|
+ * So instead we define the regs with no ri->opaque info, and
|
|
+ * get back to the GICv3CPUState from the CPUARMState.
|
|
+ */
|
|
+ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
|
|
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL2)
|
|
+ && cpu->gic_num_lrs) {
|
|
+ int j;
|
|
|
|
- cs->maintenance_irq = cpu->gicv3_maintenance_interrupt;
|
|
+ cs->maintenance_irq = cpu->gicv3_maintenance_interrupt;
|
|
|
|
- cs->num_list_regs = cpu->gic_num_lrs;
|
|
- cs->vpribits = cpu->gic_vpribits;
|
|
- cs->vprebits = cpu->gic_vprebits;
|
|
+ cs->num_list_regs = cpu->gic_num_lrs;
|
|
+ cs->vpribits = cpu->gic_vpribits;
|
|
+ cs->vprebits = cpu->gic_vprebits;
|
|
|
|
- /* Check against architectural constraints: getting these
|
|
- * wrong would be a bug in the CPU code defining these,
|
|
- * and the implementation relies on them holding.
|
|
- */
|
|
- g_assert(cs->vprebits <= cs->vpribits);
|
|
- g_assert(cs->vprebits >= 5 && cs->vprebits <= 7);
|
|
- g_assert(cs->vpribits >= 5 && cs->vpribits <= 8);
|
|
+ /* Check against architectural constraints: getting these
|
|
+ * wrong would be a bug in the CPU code defining these,
|
|
+ * and the implementation relies on them holding.
|
|
+ */
|
|
+ g_assert(cs->vprebits <= cs->vpribits);
|
|
+ g_assert(cs->vprebits >= 5 && cs->vprebits <= 7);
|
|
+ g_assert(cs->vpribits >= 5 && cs->vpribits <= 8);
|
|
|
|
- define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo);
|
|
+ define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo);
|
|
|
|
- for (j = 0; j < cs->num_list_regs; j++) {
|
|
- /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs
|
|
- * are split into two cp15 regs, LR (the low part, with the
|
|
- * same encoding as the AArch64 LR) and LRC (the high part).
|
|
- */
|
|
- ARMCPRegInfo lr_regset[] = {
|
|
- { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH,
|
|
- .opc0 = 3, .opc1 = 4, .crn = 12,
|
|
- .crm = 12 + (j >> 3), .opc2 = j & 7,
|
|
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
|
|
- .access = PL2_RW,
|
|
- .readfn = ich_lr_read,
|
|
- .writefn = ich_lr_write,
|
|
- },
|
|
- { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32,
|
|
- .cp = 15, .opc1 = 4, .crn = 12,
|
|
- .crm = 14 + (j >> 3), .opc2 = j & 7,
|
|
- .type = ARM_CP_IO | ARM_CP_NO_RAW,
|
|
- .access = PL2_RW,
|
|
- .readfn = ich_lr_read,
|
|
- .writefn = ich_lr_write,
|
|
- },
|
|
- REGINFO_SENTINEL
|
|
- };
|
|
- define_arm_cp_regs(cpu, lr_regset);
|
|
- }
|
|
- if (cs->vprebits >= 6) {
|
|
- define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo);
|
|
- }
|
|
- if (cs->vprebits == 7) {
|
|
- define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
|
|
- }
|
|
+ for (j = 0; j < cs->num_list_regs; j++) {
|
|
+ /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs
|
|
+ * are split into two cp15 regs, LR (the low part, with the
|
|
+ * same encoding as the AArch64 LR) and LRC (the high part).
|
|
+ */
|
|
+ ARMCPRegInfo lr_regset[] = {
|
|
+ { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH,
|
|
+ .opc0 = 3, .opc1 = 4, .crn = 12,
|
|
+ .crm = 12 + (j >> 3), .opc2 = j & 7,
|
|
+ .type = ARM_CP_IO | ARM_CP_NO_RAW,
|
|
+ .access = PL2_RW,
|
|
+ .readfn = ich_lr_read,
|
|
+ .writefn = ich_lr_write,
|
|
+ },
|
|
+ { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32,
|
|
+ .cp = 15, .opc1 = 4, .crn = 12,
|
|
+ .crm = 14 + (j >> 3), .opc2 = j & 7,
|
|
+ .type = ARM_CP_IO | ARM_CP_NO_RAW,
|
|
+ .access = PL2_RW,
|
|
+ .readfn = ich_lr_read,
|
|
+ .writefn = ich_lr_write,
|
|
+ },
|
|
+ REGINFO_SENTINEL
|
|
+ };
|
|
+ define_arm_cp_regs(cpu, lr_regset);
|
|
+ }
|
|
+ if (cs->vprebits >= 6) {
|
|
+ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo);
|
|
+ }
|
|
+ if (cs->vprebits == 7) {
|
|
+ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
|
|
}
|
|
- arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
|
|
}
|
|
+ arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
|
|
}
|
|
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
|
|
index 05303a55c8..cfbfe8a549 100644
|
|
--- a/hw/intc/gicv3_internal.h
|
|
+++ b/hw/intc/gicv3_internal.h
|
|
@@ -297,7 +297,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
|
|
void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
|
|
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
|
|
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
|
|
-void gicv3_init_cpuif(GICv3State *s);
|
|
+void gicv3_init_one_cpuif(GICv3State *s, int ncpu);
|
|
|
|
/**
|
|
* gicv3_cpuif_update:
|
|
--
|
|
2.19.1
|