return 0;
 }
 
-static void reset_bvr(struct kvm_vcpu *vcpu,
+static u64 reset_bvr(struct kvm_vcpu *vcpu,
                      const struct sys_reg_desc *rd)
 {
        vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val;
+       return rd->val;
 }
 
 static bool trap_bcr(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static void reset_bcr(struct kvm_vcpu *vcpu,
+static u64 reset_bcr(struct kvm_vcpu *vcpu,
                      const struct sys_reg_desc *rd)
 {
        vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val;
+       return rd->val;
 }
 
 static bool trap_wvr(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static void reset_wvr(struct kvm_vcpu *vcpu,
+static u64 reset_wvr(struct kvm_vcpu *vcpu,
                      const struct sys_reg_desc *rd)
 {
        vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val;
+       return rd->val;
 }
 
 static bool trap_wcr(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static void reset_wcr(struct kvm_vcpu *vcpu,
+static u64 reset_wcr(struct kvm_vcpu *vcpu,
                      const struct sys_reg_desc *rd)
 {
        vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val;
+       return rd->val;
 }
 
-static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        u64 amair = read_sysreg(amair_el1);
        vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1);
+       return amair;
 }
 
-static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        u64 actlr = read_sysreg(actlr_el1);
        vcpu_write_sys_reg(vcpu, actlr, ACTLR_EL1);
+       return actlr;
 }
 
-static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        u64 mpidr;
 
        mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0);
        mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1);
        mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2);
-       vcpu_write_sys_reg(vcpu, (1ULL << 31) | mpidr, MPIDR_EL1);
+       mpidr |= (1ULL << 31);
+       vcpu_write_sys_reg(vcpu, mpidr, MPIDR_EL1);
+
+       return mpidr;
 }
 
 static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu,
        return REG_HIDDEN;
 }
 
-static void reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        u64 n, mask = BIT(ARMV8_PMU_CYCLE_IDX);
 
        /* No PMU available, any PMU reg may UNDEF... */
        if (!kvm_arm_support_pmu_v3())
-               return;
+               return 0;
 
        n = read_sysreg(pmcr_el0) >> ARMV8_PMU_PMCR_N_SHIFT;
        n &= ARMV8_PMU_PMCR_N_MASK;
 
        reset_unknown(vcpu, r);
        __vcpu_sys_reg(vcpu, r->reg) &= mask;
+
+       return __vcpu_sys_reg(vcpu, r->reg);
 }
 
-static void reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        reset_unknown(vcpu, r);
        __vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0);
+
+       return __vcpu_sys_reg(vcpu, r->reg);
 }
 
-static void reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        reset_unknown(vcpu, r);
        __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_EVTYPE_MASK;
+
+       return __vcpu_sys_reg(vcpu, r->reg);
 }
 
-static void reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        reset_unknown(vcpu, r);
        __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_COUNTER_MASK;
+
+       return __vcpu_sys_reg(vcpu, r->reg);
 }
 
-static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        u64 pmcr;
 
        /* No PMU available, PMCR_EL0 may UNDEF... */
        if (!kvm_arm_support_pmu_v3())
-               return;
+               return 0;
 
        /* Only preserve PMCR_EL0.N, and reset the rest to 0 */
        pmcr = read_sysreg(pmcr_el0) & (ARMV8_PMU_PMCR_N_MASK << ARMV8_PMU_PMCR_N_SHIFT);
                pmcr |= ARMV8_PMU_PMCR_LC;
 
        __vcpu_sys_reg(vcpu, r->reg) = pmcr;
+
+       return __vcpu_sys_reg(vcpu, r->reg);
 }
 
 static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
 }
 
 /* Read a sanitised cpufeature ID register by sys_reg_desc */
-static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r)
+static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
+                                      const struct sys_reg_desc *r)
 {
        u32 id = reg_to_encoding(r);
        u64 val;
        return val;
 }
 
+static u64 kvm_read_sanitised_id_reg(struct kvm_vcpu *vcpu,
+                                    const struct sys_reg_desc *r)
+{
+       return __kvm_read_sanitised_id_reg(vcpu, r);
+}
+
+static u64 read_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+       return __kvm_read_sanitised_id_reg(vcpu, r);
+}
+
 static unsigned int id_visibility(const struct kvm_vcpu *vcpu,
                                  const struct sys_reg_desc *r)
 {
  * Fabricate a CLIDR_EL1 value instead of using the real value, which can vary
  * by the physical CPU which the vcpu currently resides in.
  */
-static void reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
        u64 ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0);
        u64 clidr;
                clidr |= 2 << CLIDR_TTYPE_SHIFT(loc);
 
        __vcpu_sys_reg(vcpu, r->reg) = clidr;
+
+       return __vcpu_sys_reg(vcpu, r->reg);
 }
 
 static int set_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
        .visibility = elx2_visibility,          \
 }
 
+/*
+ * Since reset() callback and field val are not used for idregs, they will be
+ * used for specific purposes for idregs.
+ * The reset() would return KVM sanitised register value. The value would be the
+ * same as the host kernel sanitised value if there is no KVM sanitisation.
+ * The val would be used as a mask indicating writable fields for the idreg.
+ * Only bits with 1 are writable from userspace. This mask might not be
+ * necessary in the future whenever all ID registers are enabled as writable
+ * from userspace.
+ */
+
 /* sys_reg_desc initialiser for known cpufeature ID registers */
 #define ID_SANITISED(name) {                   \
        SYS_DESC(SYS_##name),                   \
        .get_user = get_id_reg,                 \
        .set_user = set_id_reg,                 \
        .visibility = id_visibility,            \
+       .reset = kvm_read_sanitised_id_reg,     \
+       .val = 0,                               \
 }
 
 /* sys_reg_desc initialiser for known cpufeature ID registers */
        .get_user = get_id_reg,                 \
        .set_user = set_id_reg,                 \
        .visibility = aa32_id_visibility,       \
+       .reset = kvm_read_sanitised_id_reg,     \
+       .val = 0,                               \
 }
 
 /*
        .access = access_id_reg,                        \
        .get_user = get_id_reg,                         \
        .set_user = set_id_reg,                         \
-       .visibility = raz_visibility                    \
+       .visibility = raz_visibility,                   \
+       .reset = kvm_read_sanitised_id_reg,             \
+       .val = 0,                                       \
 }
 
 /*
        .get_user = get_id_reg,                 \
        .set_user = set_id_reg,                 \
        .visibility = raz_visibility,           \
+       .reset = kvm_read_sanitised_id_reg,     \
+       .val = 0,                               \
 }
 
 static bool access_sp_el1(struct kvm_vcpu *vcpu,
  */
 
 #define FUNCTION_INVARIANT(reg)                                                \
-       static void get_##reg(struct kvm_vcpu *v,                       \
+       static u64 get_##reg(struct kvm_vcpu *v,                        \
                              const struct sys_reg_desc *r)             \
        {                                                               \
                ((struct sys_reg_desc *)r)->val = read_sysreg(reg);     \
+               return ((struct sys_reg_desc *)r)->val;                 \
        }
 
 FUNCTION_INVARIANT(midr_el1)
 FUNCTION_INVARIANT(revidr_el1)
 FUNCTION_INVARIANT(aidr_el1)
 
-static void get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
+static u64 get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
 {
        ((struct sys_reg_desc *)r)->val = read_sanitised_ftr_reg(SYS_CTR_EL0);
+       return ((struct sys_reg_desc *)r)->val;
 }
 
 /* ->val is filled in by kvm_sys_reg_table_init() */