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,
