[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH v6 4/4] hw/intc/arm_gicv3_kvm: Reset GICv3 cpu interfa
From: |
vijay . kilari |
Subject: |
[Qemu-arm] [PATCH v6 4/4] hw/intc/arm_gicv3_kvm: Reset GICv3 cpu interface registers |
Date: |
Wed, 23 Nov 2016 18:09:24 +0530 |
From: Vijaya Kumar K <address@hidden>
Reset CPU interface registers of GICv3 when CPU is reset.
For this, object interface is used, which is called from
arm_cpu_reset function.
Signed-off-by: Vijaya Kumar K <address@hidden>
---
hw/intc/arm_gicv3_kvm.c | 37 +++++++++++++++++++++++++++++++++++++
include/hw/arm/linux-boot-if.h | 28 ++++++++++++++++++++++++++++
target-arm/cpu.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 96 insertions(+)
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 77af32d..267c2d6 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -29,6 +29,7 @@
#include "gicv3_internal.h"
#include "vgic_common.h"
#include "migration/migration.h"
+#include "hw/arm/linux-boot-if.h"
#ifdef DEBUG_GICV3_KVM
#define DPRINTF(fmt, ...) \
@@ -604,6 +605,36 @@ static void kvm_arm_gicv3_get(GICv3State *s)
}
}
+static void arm_gicv3_reset_cpuif(ARMDeviceResetIf *obj,
+ unsigned int cpu_num)
+{
+ GICv3CPUState *c;
+ GICv3State *s = ARM_GICV3_COMMON(obj);
+
+ if (!s && !s->cpu) {
+ return;
+ }
+
+ c = &s->cpu[cpu_num];
+ if (!c) {
+ return;
+ }
+
+ /* Initialize to actual HW supported configuration */
+ kvm_gicc_access(s, ICC_CTLR_EL1, cpu_num,
+ &c->icc_ctlr_el1[GICV3_NS], false);
+
+ c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
+ c->icc_pmr_el1 = 0;
+ c->icc_bpr[GICV3_G0] = GIC_MIN_BPR;
+ c->icc_bpr[GICV3_G1] = GIC_MIN_BPR;
+ c->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR;
+
+ c->icc_sre_el1 = 0x7;
+ memset(c->icc_apr, 0, sizeof(c->icc_apr));
+ memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen));
+}
+
static void kvm_arm_gicv3_reset(DeviceState *dev)
{
GICv3State *s = ARM_GICV3_COMMON(dev);
@@ -688,6 +719,7 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass,
void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);
KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass);
+ ARMDeviceResetIfClass *adrifc = ARM_DEVICE_RESET_IF_CLASS(klass);
agcc->pre_save = kvm_arm_gicv3_get;
agcc->post_load = kvm_arm_gicv3_put;
@@ -695,6 +727,7 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass,
void *data)
kgc->parent_reset = dc->reset;
dc->realize = kvm_arm_gicv3_realize;
dc->reset = kvm_arm_gicv3_reset;
+ adrifc->arm_device_reset = arm_gicv3_reset_cpuif;
}
static const TypeInfo kvm_arm_gicv3_info = {
@@ -703,6 +736,10 @@ static const TypeInfo kvm_arm_gicv3_info = {
.instance_size = sizeof(GICv3State),
.class_init = kvm_arm_gicv3_class_init,
.class_size = sizeof(KVMARMGICv3Class),
+ .interfaces = (InterfaceInfo []) {
+ { TYPE_ARM_DEVICE_RESET_IF },
+ { },
+ },
};
static void kvm_arm_gicv3_register_types(void)
diff --git a/include/hw/arm/linux-boot-if.h b/include/hw/arm/linux-boot-if.h
index aba4479..4a8affd 100644
--- a/include/hw/arm/linux-boot-if.h
+++ b/include/hw/arm/linux-boot-if.h
@@ -40,4 +40,32 @@ typedef struct ARMLinuxBootIfClass {
void (*arm_linux_init)(ARMLinuxBootIf *obj, bool secure_boot);
} ARMLinuxBootIfClass;
+#define TYPE_ARM_DEVICE_RESET_IF "arm-device-reset-if"
+#define ARM_DEVICE_RESET_IF_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ARMDeviceResetIfClass, (klass),
TYPE_ARM_DEVICE_RESET_IF)
+#define ARM_DEVICE_RESET_IF_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ARMDeviceResetIfClass, (obj), TYPE_ARM_DEVICE_RESET_IF)
+#define ARM_DEVICE_RESET_IF(obj) \
+ INTERFACE_CHECK(ARMDeviceResetIf, (obj), TYPE_ARM_DEVICE_RESET_IF)
+
+typedef struct ARMDeviceResetIf {
+ /*< private >*/
+ Object parent_obj;
+} ARMDeviceResetIf;
+
+typedef struct ARMDeviceResetIfClass {
+ /*< private >*/
+ InterfaceClass parent_class;
+
+ /*< public >*/
+ /** arm_device_reset: Reset the device when cpu is reset is
+ * called. Some device registers like GICv3 cpu interface registers
+ * required to be reset when CPU is reset instead of GICv3 device
+ * reset. This callback is called when arm_cpu_reset is called.
+ *
+ * @obj: the object implementing this interface
+ * @cpu_num: CPU number being reset
+ */
+ void (*arm_device_reset)(ARMDeviceResetIf *obj, unsigned int cpu_num);
+} ARMDeviceResetIfClass;
#endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 99f0dbe..44806be 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -30,6 +30,7 @@
#include "hw/loader.h"
#endif
#include "hw/arm/arm.h"
+#include "hw/arm/linux-boot-if.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
@@ -113,6 +114,21 @@ static void cp_reg_check_reset(gpointer key, gpointer
value, gpointer opaque)
assert(oldvalue == newvalue);
}
+static int do_arm_device_reset(Object *obj, void *opaque)
+{
+ if (object_dynamic_cast(obj, TYPE_ARM_DEVICE_RESET_IF)) {
+ ARMDeviceResetIf *adrif = ARM_DEVICE_RESET_IF(obj);
+ ARMDeviceResetIfClass *adrifc = ARM_DEVICE_RESET_IF_GET_CLASS(obj);
+ CPUState *cpu = opaque;
+
+ if (adrifc->arm_device_reset) {
+ adrifc->arm_device_reset(adrif, cpu->cpu_index);
+ }
+ }
+ return 0;
+}
+
+
/* CPUClass::reset() */
static void arm_cpu_reset(CPUState *s)
{
@@ -228,6 +244,8 @@ static void arm_cpu_reset(CPUState *s)
&env->vfp.standard_fp_status);
tlb_flush(s, 1);
+ object_child_foreach_recursive(object_get_root(),
+ do_arm_device_reset, s);
#ifndef CONFIG_USER_ONLY
if (kvm_enabled()) {
kvm_arm_reset_vcpu(cpu);
@@ -1595,6 +1613,19 @@ static void cpu_register(const ARMCPUInfo *info)
g_free((void *)type_info.name);
}
+static const TypeInfo arm_device_reset_if_info = {
+ .name = TYPE_ARM_DEVICE_RESET_IF,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(ARMDeviceResetIfClass),
+};
+
+static void arm_device_reset_register_types(void)
+{
+ type_register_static(&arm_device_reset_if_info);
+}
+
+type_init(arm_device_reset_register_types)
+
static const TypeInfo arm_cpu_type_info = {
.name = TYPE_ARM_CPU,
.parent = TYPE_CPU,
--
1.9.1
- [Qemu-arm] [PATCH v6 4/4] hw/intc/arm_gicv3_kvm: Reset GICv3 cpu interface registers,
vijay . kilari <=