[RFC PATCH 02/46] KVM: arm64: Split demux_c15_{get,set}_val from userspace accessors
From: Pasha Tatashin
Date: Sun Sep 20 2026 - 15:37:20 EST
Factor demux_c15_get_val() and demux_c15_set_val() out of demux_c15_get()
and demux_c15_set() so kernel callers can read and write demultiplexed
coprocessor registers without going through userspace pointers.
Signed-off-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
---
arch/arm64/kvm/sys_regs.c | 48 +++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 44aae52c473d..b873ccf1ab14 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -5496,10 +5496,9 @@ id_to_sys_reg_desc(struct kvm_vcpu *vcpu, u64 id,
return r;
}
-static int demux_c15_get(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
+static int demux_c15_get_val(struct kvm_vcpu *vcpu, u64 id, u32 *val)
{
- u32 val;
- u32 __user *uval = uaddr;
+ u32 idx;
/* Fail if we have unknown bits set. */
if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
@@ -5510,21 +5509,34 @@ static int demux_c15_get(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
case KVM_REG_ARM_DEMUX_ID_CCSIDR:
if (KVM_REG_SIZE(id) != 4)
return -ENOENT;
- val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
+ idx = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
- if (val >= CSSELR_MAX)
+ if (idx >= CSSELR_MAX)
return -ENOENT;
- return put_user(get_ccsidr(vcpu, val), uval);
+ *val = get_ccsidr(vcpu, idx);
+ return 0;
default:
return -ENOENT;
}
}
-static int demux_c15_set(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
+static int demux_c15_get(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
{
- u32 val, newval;
u32 __user *uval = uaddr;
+ u32 val;
+ int ret;
+
+ ret = demux_c15_get_val(vcpu, id, &val);
+ if (!ret)
+ ret = put_user(val, uval);
+
+ return ret;
+}
+
+static int demux_c15_set_val(struct kvm_vcpu *vcpu, u64 id, u32 newval)
+{
+ u32 idx;
/* Fail if we have unknown bits set. */
if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
@@ -5535,20 +5547,28 @@ static int demux_c15_set(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
case KVM_REG_ARM_DEMUX_ID_CCSIDR:
if (KVM_REG_SIZE(id) != 4)
return -ENOENT;
- val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
+ idx = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
>> KVM_REG_ARM_DEMUX_VAL_SHIFT;
- if (val >= CSSELR_MAX)
+ if (idx >= CSSELR_MAX)
return -ENOENT;
- if (get_user(newval, uval))
- return -EFAULT;
-
- return set_ccsidr(vcpu, val, newval);
+ return set_ccsidr(vcpu, idx, newval);
default:
return -ENOENT;
}
}
+static int demux_c15_set(struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
+{
+ u32 __user *uval = uaddr;
+ u32 newval;
+
+ if (get_user(newval, uval))
+ return -EFAULT;
+
+ return demux_c15_set_val(vcpu, id, newval);
+}
+
static u64 kvm_one_reg_to_id(const struct kvm_one_reg *reg)
{
switch(reg->id) {
--
2.55.0.1082.g2b9226bbc0-goog