[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH RFC 19/22] arm/cpuhp: Changes required to (re)init the vcpu regis
From: |
Salil Mehta |
Subject: |
[PATCH RFC 19/22] arm/cpuhp: Changes required to (re)init the vcpu register info |
Date: |
Sat, 13 Jun 2020 22:36:26 +0100 |
VCPU register info needs to be re-initialized each time vcpu is hot-plugged.
This has to be done both for emulation/TCG and KVM case. This is done in
context to the GIC update notification for any vcpu hot-(un)plug events. This
change adds that support and re-factors existing to maximize the code re-use.
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
hw/intc/arm_gicv3.c | 1 +
hw/intc/arm_gicv3_common.c | 6 +-
hw/intc/arm_gicv3_cpuif.c | 134 ++++++++++++++++-------------
hw/intc/arm_gicv3_kvm.c | 7 +-
hw/intc/gicv3_internal.h | 1 +
include/hw/intc/arm_gicv3_common.h | 1 +
6 files changed, 86 insertions(+), 64 deletions(-)
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 66eaa97198..86f2f4cca7 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -396,6 +396,7 @@ static void arm_gicv3_class_init(ObjectClass *klass, void
*data)
ARMGICv3Class *agc = ARM_GICV3_CLASS(klass);
agcc->post_load = arm_gicv3_post_load;
+ agcc->init_cpu_reginfo = gicv3_init_cpu_reginfo;
device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize);
}
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index f6b7b359cb..01e4aba4f1 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -330,6 +330,7 @@ static void arm_gicv3_cpu_update_notifier(Notifier *
notifier, void * data)
{
VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
GICv3State *s = ARM_GICV3_COMMON(vms->gic);
+ ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
CPUState *cpu = (CPUState *)data;
int gic_cpuif_num;
@@ -351,7 +352,10 @@ static void arm_gicv3_cpu_update_notifier(Notifier *
notifier, void * data)
gicv3_set_gicv3state(cpu, &s->cpu[gic_cpuif_num]);
gicv3_set_cpustate(&s->cpu[gic_cpuif_num], cpu);
- /* TODO: initialize the registers info for this newly added cpu */
+ /* initialize the registers info for this newly added cpu */
+ if (c->init_cpu_reginfo) {
+ c->init_cpu_reginfo(cpu);
+ }
}
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index b3aa5979ca..1126fffa55 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -2605,6 +2605,74 @@ static const ARMCPRegInfo
gicv3_cpuif_ich_apxr23_reginfo[] = {
REGINFO_SENTINEL
};
+void gicv3_init_cpu_reginfo(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ GICv3CPUState *gcs = icc_cs_from_env(&cpu->env);
+
+ /* 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;
+
+ gcs->maintenance_irq = cpu->gicv3_maintenance_interrupt;
+
+ gcs->num_list_regs = cpu->gic_num_lrs;
+ gcs->vpribits = cpu->gic_vpribits;
+ gcs->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(gcs->vprebits <= gcs->vpribits);
+ g_assert(gcs->vprebits >= 5 && gcs->vprebits <= 7);
+ g_assert(gcs->vpribits >= 5 && gcs->vpribits <= 8);
+
+ define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo);
+
+ for (j = 0; j < gcs->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 (gcs->vprebits >= 6) {
+ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo);
+ }
+ if (gcs->vprebits == 7) {
+ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
+ }
+ }
+}
+
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
{
GICv3CPUState *cs = opaque;
@@ -2621,69 +2689,11 @@ void gicv3_init_cpuif(GICv3State *s)
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;
- 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;
-
- /* 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);
-
- 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);
- }
+ if (qemu_present_cpu(CPU(cpu))) {
+ GICv3CPUState *cs = icc_cs_from_env(&cpu->env);
+ gicv3_init_cpu_reginfo(CPU(cpu));
+ 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/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 7fe000e53c..8d19af3974 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -781,6 +781,10 @@ static void vm_change_state_handler(void *opaque, int
running,
}
}
+static void kvm_gicv3_init_cpu_reginfo(CPUState *cs)
+{
+ define_arm_cp_regs(ARM_CPU(cs), gicv3_cpuif_reginfo);
+}
static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
{
@@ -813,7 +817,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error
**errp)
for (i = 0; i < s->num_cpu; i++) {
CPUState *cs = qemu_get_cpu(i);
if (qemu_present_cpu(cs))
- define_arm_cp_regs(ARM_CPU(cs), gicv3_cpuif_reginfo);
+ kvm_gicv3_init_cpu_reginfo(cs);
}
/* Try to create the device via the device control API */
@@ -902,6 +906,7 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass,
void *data)
agcc->pre_save = kvm_arm_gicv3_get;
agcc->post_load = kvm_arm_gicv3_put;
+ agcc->init_cpu_reginfo = kvm_gicv3_init_cpu_reginfo;
device_class_set_parent_realize(dc, kvm_arm_gicv3_realize,
&kgc->parent_realize);
device_class_set_parent_reset(dc, kvm_arm_gicv3_reset, &kgc->parent_reset);
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 6e14a7a6cd..66eec3c3fc 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -298,6 +298,7 @@ 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_cpu_reginfo(CPUState *cs);
/**
* gicv3_cpuif_update:
diff --git a/include/hw/intc/arm_gicv3_common.h
b/include/hw/intc/arm_gicv3_common.h
index b51f74c728..4d1cbc66db 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -294,6 +294,7 @@ typedef struct ARMGICv3CommonClass {
void (*pre_save)(GICv3State *s);
void (*post_load)(GICv3State *s);
+ void (*init_cpu_reginfo)(CPUState *cs);
} ARMGICv3CommonClass;
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
--
2.17.1
- [PATCH RFC 09/22] arm/cpuhp: Init GED framework with cpu hotplug events, (continued)
- [PATCH RFC 09/22] arm/cpuhp: Init GED framework with cpu hotplug events, Salil Mehta, 2020/06/13
- [PATCH RFC 10/22] arm/cpuhp: Update CPUs AML with cpu-(ctrl)dev change, Salil Mehta, 2020/06/13
- [PATCH RFC 11/22] arm/cpuhp: Update GED _EVT method AML with cpu scan, Salil Mehta, 2020/06/13
- [PATCH RFC 12/22] arm/cpuhp: MADT Tbl change to size the guest with possible vcpus, Salil Mehta, 2020/06/13
- [PATCH RFC 13/22] arm/cpuhp: Add ACPI _MAT entry for Processor object, Salil Mehta, 2020/06/13
- [PATCH RFC 14/22] arm/cpuhp: Release objects for *disabled* possible vcpus after init, Salil Mehta, 2020/06/13
- [PATCH RFC 15/22] arm/cpuhp: Update ACPI GED framework to support vcpu hotplug, Salil Mehta, 2020/06/13
- [PATCH RFC 16/22] arm/cpuhp: Add/update basic hot-(un)plug framework, Salil Mehta, 2020/06/13
- [PATCH RFC 17/22] arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during hot-(un)plug, Salil Mehta, 2020/06/13
- [PATCH RFC 18/22] arm/cpuhp: Changes to update GIC with vcpu hot-plug notification, Salil Mehta, 2020/06/13
- [PATCH RFC 19/22] arm/cpuhp: Changes required to (re)init the vcpu register info,
Salil Mehta <=
- [PATCH RFC 20/22] arm/cpuhp: Update the guest(via GED) about cpu hot-(un)plug events, Salil Mehta, 2020/06/13
- [PATCH RFC 21/22] arm/cpuhp: Changes required for reset and to support next boot, Salil Mehta, 2020/06/13
- [PATCH RFC 22/22] arm/cpuhp: Add support of *unrealize* ARMCPU during vcpu hot-unplug, Salil Mehta, 2020/06/13
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, no-reply, 2020/06/13
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, no-reply, 2020/06/13
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, Marc Zyngier, 2020/06/14
- Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch, Andrew Jones, 2020/06/23