mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
@ 2026-01-25  5:43 Zixing Liu
  2026-01-26  2:09 ` Bibo Mao
  0 siblings, 1 reply; 9+ messages in thread
From: Zixing Liu @ 2026-01-25  5:43 UTC (permalink / raw)
  To: WANG Xuerui, Huacai Chen, Bibo Mao
  Cc: Kexy Biscuit, Mingcong Bai, Zixing Liu, Paolo Bonzini,
	Jonathan Corbet, Tianrui Zhao, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux

This ioctl can be used by userspace applications to determine which
(special) registers are get/set-able.

This can be very useful for cross-platform VMMs so that they do not have
to hardcode register indices for each supported architectures.

Signed-off-by: Zixing Liu <liushuyu@aosc.io>
---

For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
VirtualBox-kvm in the future.

 Documentation/virt/kvm/api.rst |  2 +-
 arch/loongarch/kvm/vcpu.c      | 69 ++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 01a3abef8abb..f46dd8be282f 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -3603,7 +3603,7 @@ VCPU matching underlying host.
 ---------------------
 
 :Capability: basic
-:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
+:Architectures: arm64, loongarch, mips, riscv, x86 (if KVM_CAP_ONE_REG)
 :Type: vcpu ioctl
 :Parameters: struct kvm_reg_list (in/out)
 :Returns: 0 on success; -1 on error
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 656b954c1134..b884eb9c76aa 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct kvm_vcpu *vcpu,
 	return ret;
 }
 
+static unsigned long kvm_loongarch_num_lbt_regs(void)
+{
+	/* +1 for the LBT_FTOP flag (inside arch.fpu) */
+	return sizeof(struct loongarch_lbt) / sizeof(unsigned long) + 1;
+}
+
+static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
+{
+	/* +1 for the KVM_REG_LOONGARCH_COUNTER register */
+	unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
+
+	if (kvm_guest_has_lbt(&vcpu->arch))
+		res += kvm_loongarch_num_lbt_regs();
+
+	return res;
+}
+
+static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
+					  u64 __user *uindices)
+{
+	u64 reg;
+	unsigned int i;
+
+	for (i = 0; i < CSR_MAX_NUMS; i++) {
+		reg = KVM_IOC_CSRID(i);
+		if (put_user(reg, uindices++))
+			return -EFAULT;
+	}
+
+	for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
+		reg = KVM_IOC_CPUCFG(i);
+		if (put_user(reg, uindices++))
+			return -EFAULT;
+	}
+
+	reg = KVM_REG_LOONGARCH_COUNTER;
+	if (put_user(reg, uindices++))
+		return -EFAULT;
+
+	if (!kvm_guest_has_lbt(&vcpu->arch))
+		return 0;
+
+	for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
+		reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
+		if (put_user(reg, uindices++))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
 			 unsigned int ioctl, unsigned long arg)
 {
@@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
 		break;
 	}
+	case KVM_GET_REG_LIST: {
+		struct kvm_reg_list __user *user_list = argp;
+		struct kvm_reg_list reg_list;
+		unsigned n;
+
+		r = -EFAULT;
+		if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
+			break;
+		n = reg_list.n;
+		reg_list.n = kvm_loongarch_num_regs(vcpu);
+		if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
+			break;
+		r = -E2BIG;
+		if (n < reg_list.n)
+			break;
+		r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
+		break;
+	}
 	default:
 		r = -ENOIOCTLCMD;
 		break;
-- 
2.52.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-25  5:43 [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch Zixing Liu
@ 2026-01-26  2:09 ` Bibo Mao
  2026-01-26  3:38   ` liushuyu
  0 siblings, 1 reply; 9+ messages in thread
From: Bibo Mao @ 2026-01-26  2:09 UTC (permalink / raw)
  To: Zixing Liu, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux



On 2026/1/25 下午1:43, Zixing Liu wrote:
> This ioctl can be used by userspace applications to determine which
> (special) registers are get/set-able.
> 
> This can be very useful for cross-platform VMMs so that they do not have
> to hardcode register indices for each supported architectures.
> 
> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
> ---
> 
> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
> VirtualBox-kvm in the future.
> 
>   Documentation/virt/kvm/api.rst |  2 +-
>   arch/loongarch/kvm/vcpu.c      | 69 ++++++++++++++++++++++++++++++++++
>   2 files changed, 70 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 01a3abef8abb..f46dd8be282f 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>   ---------------------
>   
>   :Capability: basic
> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
> +:Architectures: arm64, loongarch, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>   :Type: vcpu ioctl
>   :Parameters: struct kvm_reg_list (in/out)
>   :Returns: 0 on success; -1 on error
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index 656b954c1134..b884eb9c76aa 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct kvm_vcpu *vcpu,
>   	return ret;
>   }
>   
> +static unsigned long kvm_loongarch_num_lbt_regs(void)
> +{
> +	/* +1 for the LBT_FTOP flag (inside arch.fpu) */
> +	return sizeof(struct loongarch_lbt) / sizeof(unsigned long) + 1;
> +}
> +
> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
> +{
> +	/* +1 for the KVM_REG_LOONGARCH_COUNTER register */
> +	unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
> +
> +	if (kvm_guest_has_lbt(&vcpu->arch))
> +		res += kvm_loongarch_num_lbt_regs();
> +
> +	return res;
> +}
> +
> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
> +					  u64 __user *uindices)
> +{
> +	u64 reg;
> +	unsigned int i;
> +
> +	for (i = 0; i < CSR_MAX_NUMS; i++) {
> +		reg = KVM_IOC_CSRID(i);
> +		if (put_user(reg, uindices++))
> +			return -EFAULT;
> +	}
CSR_MAX_NUMS is max number of accessible CSR registers, instead only 
part of them is used by vCPU model. By my understanding, there will be 
no much meaning if CSR_MAX_NUMS is returned. And I think it will be 
better if real CSR register id and number is returned.

Regards
Bibo Mao
> +
> +	for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
> +		reg = KVM_IOC_CPUCFG(i);
> +		if (put_user(reg, uindices++))
> +			return -EFAULT;
> +	}
> +
> +	reg = KVM_REG_LOONGARCH_COUNTER;
> +	if (put_user(reg, uindices++))
> +		return -EFAULT;
> +
> +	if (!kvm_guest_has_lbt(&vcpu->arch))
> +		return 0;
> +
> +	for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
> +		reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
> +		if (put_user(reg, uindices++))
> +			return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
>   long kvm_arch_vcpu_ioctl(struct file *filp,
>   			 unsigned int ioctl, unsigned long arg)
>   {
> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>   		r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>   		break;
>   	}
> +	case KVM_GET_REG_LIST: {
> +		struct kvm_reg_list __user *user_list = argp;
> +		struct kvm_reg_list reg_list;
> +		unsigned n;
> +
> +		r = -EFAULT;
> +		if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
> +			break;
> +		n = reg_list.n;
> +		reg_list.n = kvm_loongarch_num_regs(vcpu);
> +		if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
> +			break;
> +		r = -E2BIG;
> +		if (n < reg_list.n)
> +			break;
> +		r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
> +		break;
> +	}
>   	default:
>   		r = -ENOIOCTLCMD;
>   		break;
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  2:09 ` Bibo Mao
@ 2026-01-26  3:38   ` liushuyu
  2026-01-26  3:57     ` Bibo Mao
  0 siblings, 1 reply; 9+ messages in thread
From: liushuyu @ 2026-01-26  3:38 UTC (permalink / raw)
  To: Bibo Mao, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux

Hi Bibo,
>
>
> On 2026/1/25 下午1:43, Zixing Liu wrote:
>> This ioctl can be used by userspace applications to determine which
>> (special) registers are get/set-able.
>>
>> This can be very useful for cross-platform VMMs so that they do not have
>> to hardcode register indices for each supported architectures.
>>
>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>> ---
>>
>> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
>> VirtualBox-kvm in the future.
>>
>>   Documentation/virt/kvm/api.rst |  2 +-
>>   arch/loongarch/kvm/vcpu.c      | 69 ++++++++++++++++++++++++++++++++++
>>   2 files changed, 70 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/virt/kvm/api.rst
>> b/Documentation/virt/kvm/api.rst
>> index 01a3abef8abb..f46dd8be282f 100644
>> --- a/Documentation/virt/kvm/api.rst
>> +++ b/Documentation/virt/kvm/api.rst
>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>   ---------------------
>>     :Capability: basic
>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>   :Type: vcpu ioctl
>>   :Parameters: struct kvm_reg_list (in/out)
>>   :Returns: 0 on success; -1 on error
>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>> index 656b954c1134..b884eb9c76aa 100644
>> --- a/arch/loongarch/kvm/vcpu.c
>> +++ b/arch/loongarch/kvm/vcpu.c
>> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct
>> kvm_vcpu *vcpu,
>>       return ret;
>>   }
>>   +static unsigned long kvm_loongarch_num_lbt_regs(void)
>> +{
>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long) + 1;
>> +}
>> +
>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>> +{
>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>> +
>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>> +        res += kvm_loongarch_num_lbt_regs();
>> +
>> +    return res;
>> +}
>> +
>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>> +                      u64 __user *uindices)
>> +{
>> +    u64 reg;
>> +    unsigned int i;
>> +
>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>> +        reg = KVM_IOC_CSRID(i);
>> +        if (put_user(reg, uindices++))
>> +            return -EFAULT;
>> +    }
> CSR_MAX_NUMS is max number of accessible CSR registers, instead only
> part of them is used by vCPU model. By my understanding, there will be
> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
> better if real CSR register id and number is returned. 
>
Did you mean we should only return the CSR registers initialized in this
function
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
?

That looks like a very large list and the values of the register IDs are
not fully continuous. If that is the case, how do we maintain the
get/set-able CSR register list?

> Regards
> Bibo Mao
>> +
>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>> +        reg = KVM_IOC_CPUCFG(i);
>> +        if (put_user(reg, uindices++))
>> +            return -EFAULT;
>> +    }
>> +
>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>> +    if (put_user(reg, uindices++))
>> +        return -EFAULT;
>> +
>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>> +        return 0;
>> +
>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>> +        if (put_user(reg, uindices++))
>> +            return -EFAULT;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   long kvm_arch_vcpu_ioctl(struct file *filp,
>>                unsigned int ioctl, unsigned long arg)
>>   {
>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>           r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>           break;
>>       }
>> +    case KVM_GET_REG_LIST: {
>> +        struct kvm_reg_list __user *user_list = argp;
>> +        struct kvm_reg_list reg_list;
>> +        unsigned n;
>> +
>> +        r = -EFAULT;
>> +        if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
>> +            break;
>> +        n = reg_list.n;
>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>> +            break;
>> +        r = -E2BIG;
>> +        if (n < reg_list.n)
>> +            break;
>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>> +        break;
>> +    }
>>       default:
>>           r = -ENOIOCTLCMD;
>>           break;
>>
>
Thanks,
Zixing

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  3:38   ` liushuyu
@ 2026-01-26  3:57     ` Bibo Mao
  2026-01-26  4:22       ` liushuyu
  0 siblings, 1 reply; 9+ messages in thread
From: Bibo Mao @ 2026-01-26  3:57 UTC (permalink / raw)
  To: liushuyu, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux



On 2026/1/26 上午11:38, liushuyu wrote:
> Hi Bibo,
>>
>>
>> On 2026/1/25 下午1:43, Zixing Liu wrote:
>>> This ioctl can be used by userspace applications to determine which
>>> (special) registers are get/set-able.
>>>
>>> This can be very useful for cross-platform VMMs so that they do not have
>>> to hardcode register indices for each supported architectures.
>>>
>>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>>> ---
>>>
>>> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
>>> VirtualBox-kvm in the future.
>>>
>>>    Documentation/virt/kvm/api.rst |  2 +-
>>>    arch/loongarch/kvm/vcpu.c      | 69 ++++++++++++++++++++++++++++++++++
>>>    2 files changed, 70 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/Documentation/virt/kvm/api.rst
>>> b/Documentation/virt/kvm/api.rst
>>> index 01a3abef8abb..f46dd8be282f 100644
>>> --- a/Documentation/virt/kvm/api.rst
>>> +++ b/Documentation/virt/kvm/api.rst
>>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>>    ---------------------
>>>      :Capability: basic
>>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>>    :Type: vcpu ioctl
>>>    :Parameters: struct kvm_reg_list (in/out)
>>>    :Returns: 0 on success; -1 on error
>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>> index 656b954c1134..b884eb9c76aa 100644
>>> --- a/arch/loongarch/kvm/vcpu.c
>>> +++ b/arch/loongarch/kvm/vcpu.c
>>> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct
>>> kvm_vcpu *vcpu,
>>>        return ret;
>>>    }
>>>    +static unsigned long kvm_loongarch_num_lbt_regs(void)
>>> +{
>>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long) + 1;
>>> +}
>>> +
>>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>>> +{
>>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>>> +
>>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>>> +        res += kvm_loongarch_num_lbt_regs();
>>> +
>>> +    return res;
>>> +}
>>> +
>>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>> +                      u64 __user *uindices)
>>> +{
>>> +    u64 reg;
>>> +    unsigned int i;
>>> +
>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>> +        reg = KVM_IOC_CSRID(i);
>>> +        if (put_user(reg, uindices++))
>>> +            return -EFAULT;
>>> +    }
>> CSR_MAX_NUMS is max number of accessible CSR registers, instead only
>> part of them is used by vCPU model. By my understanding, there will be
>> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
>> better if real CSR register id and number is returned.
>>
> Did you mean we should only return the CSR registers initialized in this
> function
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
> ?
> 
> That looks like a very large list and the values of the register IDs are
> not fully continuous. If that is the case, how do we maintain the
> get/set-able CSR register list?
It will be better if CSR register list can be categorized, for example 
with LoongArch CPU manual CSR register is split into 8 types from 
chapter 7.4 -- 7.11

At the beginning, there is big array with size CSR_MAX_NUMS without any 
category, it can be fine-gained in late.

Regards
Bibo Mao
> 
>> Regards
>> Bibo Mao
>>> +
>>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>>> +        reg = KVM_IOC_CPUCFG(i);
>>> +        if (put_user(reg, uindices++))
>>> +            return -EFAULT;
>>> +    }
>>> +
>>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>>> +    if (put_user(reg, uindices++))
>>> +        return -EFAULT;
>>> +
>>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>>> +        return 0;
>>> +
>>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>>> +        if (put_user(reg, uindices++))
>>> +            return -EFAULT;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>    long kvm_arch_vcpu_ioctl(struct file *filp,
>>>                 unsigned int ioctl, unsigned long arg)
>>>    {
>>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>>            r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>>            break;
>>>        }
>>> +    case KVM_GET_REG_LIST: {
>>> +        struct kvm_reg_list __user *user_list = argp;
>>> +        struct kvm_reg_list reg_list;
>>> +        unsigned n;
>>> +
>>> +        r = -EFAULT;
>>> +        if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
>>> +            break;
>>> +        n = reg_list.n;
>>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>>> +            break;
>>> +        r = -E2BIG;
>>> +        if (n < reg_list.n)
>>> +            break;
>>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>>> +        break;
>>> +    }
>>>        default:
>>>            r = -ENOIOCTLCMD;
>>>            break;
>>>
>>
> Thanks,
> Zixing
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  3:57     ` Bibo Mao
@ 2026-01-26  4:22       ` liushuyu
  2026-01-26  8:36         ` Bibo Mao
  0 siblings, 1 reply; 9+ messages in thread
From: liushuyu @ 2026-01-26  4:22 UTC (permalink / raw)
  To: Bibo Mao, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux

Hi Bibo,

>
>
> On 2026/1/26 上午11:38, liushuyu wrote:
>> Hi Bibo,
>>>
>>>
>>> On 2026/1/25 下午1:43, Zixing Liu wrote:
>>>> This ioctl can be used by userspace applications to determine which
>>>> (special) registers are get/set-able.
>>>>
>>>> This can be very useful for cross-platform VMMs so that they do not
>>>> have
>>>> to hardcode register indices for each supported architectures.
>>>>
>>>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>>>> ---
>>>>
>>>> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
>>>> VirtualBox-kvm in the future.
>>>>
>>>>    Documentation/virt/kvm/api.rst |  2 +-
>>>>    arch/loongarch/kvm/vcpu.c      | 69
>>>> ++++++++++++++++++++++++++++++++++
>>>>    2 files changed, 70 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/Documentation/virt/kvm/api.rst
>>>> b/Documentation/virt/kvm/api.rst
>>>> index 01a3abef8abb..f46dd8be282f 100644
>>>> --- a/Documentation/virt/kvm/api.rst
>>>> +++ b/Documentation/virt/kvm/api.rst
>>>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>>>    ---------------------
>>>>      :Capability: basic
>>>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if
>>>> KVM_CAP_ONE_REG)
>>>>    :Type: vcpu ioctl
>>>>    :Parameters: struct kvm_reg_list (in/out)
>>>>    :Returns: 0 on success; -1 on error
>>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>>> index 656b954c1134..b884eb9c76aa 100644
>>>> --- a/arch/loongarch/kvm/vcpu.c
>>>> +++ b/arch/loongarch/kvm/vcpu.c
>>>> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct
>>>> kvm_vcpu *vcpu,
>>>>        return ret;
>>>>    }
>>>>    +static unsigned long kvm_loongarch_num_lbt_regs(void)
>>>> +{
>>>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>>>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long) + 1;
>>>> +}
>>>> +
>>>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>>>> +
>>>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>>>> +        res += kvm_loongarch_num_lbt_regs();
>>>> +
>>>> +    return res;
>>>> +}
>>>> +
>>>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>>> +                      u64 __user *uindices)
>>>> +{
>>>> +    u64 reg;
>>>> +    unsigned int i;
>>>> +
>>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>>> +        reg = KVM_IOC_CSRID(i);
>>>> +        if (put_user(reg, uindices++))
>>>> +            return -EFAULT;
>>>> +    }
>>> CSR_MAX_NUMS is max number of accessible CSR registers, instead only
>>> part of them is used by vCPU model. By my understanding, there will be
>>> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
>>> better if real CSR register id and number is returned.
>>>
>> Did you mean we should only return the CSR registers initialized in this
>> function
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
>>
>> ?
>>
>> That looks like a very large list and the values of the register IDs are
>> not fully continuous. If that is the case, how do we maintain the
>> get/set-able CSR register list?
> It will be better if CSR register list can be categorized, for example
> with LoongArch CPU manual CSR register is split into 8 types from
> chapter 7.4 -- 7.11
>
> At the beginning, there is big array with size CSR_MAX_NUMS without
> any category, it can be fine-gained in late. 

Does that mean in the new `kvm_loongarch_copy_reg_indices` function, it
is also okay to embed this big list in there?

Or do you want to extract the list from the `kvm_init_gcsr_flag`
function and refactor both functions to share one single big list
(probably in the kvm_host.h header)?

Because from what I could understand, your previous messages point to
that we need to use this list to make out what CSR registers to return
to the user space VMMs.

>
> Regards
> Bibo Mao
>>
>>> Regards
>>> Bibo Mao
>>>> +
>>>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>>>> +        reg = KVM_IOC_CPUCFG(i);
>>>> +        if (put_user(reg, uindices++))
>>>> +            return -EFAULT;
>>>> +    }
>>>> +
>>>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>>>> +    if (put_user(reg, uindices++))
>>>> +        return -EFAULT;
>>>> +
>>>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>>>> +        return 0;
>>>> +
>>>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>>>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>>>> +        if (put_user(reg, uindices++))
>>>> +            return -EFAULT;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>    long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>                 unsigned int ioctl, unsigned long arg)
>>>>    {
>>>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>            r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>>>            break;
>>>>        }
>>>> +    case KVM_GET_REG_LIST: {
>>>> +        struct kvm_reg_list __user *user_list = argp;
>>>> +        struct kvm_reg_list reg_list;
>>>> +        unsigned n;
>>>> +
>>>> +        r = -EFAULT;
>>>> +        if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
>>>> +            break;
>>>> +        n = reg_list.n;
>>>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>>>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>>>> +            break;
>>>> +        r = -E2BIG;
>>>> +        if (n < reg_list.n)
>>>> +            break;
>>>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>>>> +        break;
>>>> +    }
>>>>        default:
>>>>            r = -ENOIOCTLCMD;
>>>>            break;
>>>>
>>>
>> Thanks,
>> Zixing
>>
>
Thanks,
Zixing

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  4:22       ` liushuyu
@ 2026-01-26  8:36         ` Bibo Mao
  2026-01-26  8:54           ` liushuyu
  0 siblings, 1 reply; 9+ messages in thread
From: Bibo Mao @ 2026-01-26  8:36 UTC (permalink / raw)
  To: liushuyu, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux



On 2026/1/26 下午12:22, liushuyu wrote:
> Hi Bibo,
> 
>>
>>
>> On 2026/1/26 上午11:38, liushuyu wrote:
>>> Hi Bibo,
>>>>
>>>>
>>>> On 2026/1/25 下午1:43, Zixing Liu wrote:
>>>>> This ioctl can be used by userspace applications to determine which
>>>>> (special) registers are get/set-able.
>>>>>
>>>>> This can be very useful for cross-platform VMMs so that they do not
>>>>> have
>>>>> to hardcode register indices for each supported architectures.
>>>>>
>>>>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>>>>> ---
>>>>>
>>>>> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
>>>>> VirtualBox-kvm in the future.
>>>>>
>>>>>     Documentation/virt/kvm/api.rst |  2 +-
>>>>>     arch/loongarch/kvm/vcpu.c      | 69
>>>>> ++++++++++++++++++++++++++++++++++
>>>>>     2 files changed, 70 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/Documentation/virt/kvm/api.rst
>>>>> b/Documentation/virt/kvm/api.rst
>>>>> index 01a3abef8abb..f46dd8be282f 100644
>>>>> --- a/Documentation/virt/kvm/api.rst
>>>>> +++ b/Documentation/virt/kvm/api.rst
>>>>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>>>>     ---------------------
>>>>>       :Capability: basic
>>>>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>>>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if
>>>>> KVM_CAP_ONE_REG)
>>>>>     :Type: vcpu ioctl
>>>>>     :Parameters: struct kvm_reg_list (in/out)
>>>>>     :Returns: 0 on success; -1 on error
>>>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>>>> index 656b954c1134..b884eb9c76aa 100644
>>>>> --- a/arch/loongarch/kvm/vcpu.c
>>>>> +++ b/arch/loongarch/kvm/vcpu.c
>>>>> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct
>>>>> kvm_vcpu *vcpu,
>>>>>         return ret;
>>>>>     }
>>>>>     +static unsigned long kvm_loongarch_num_lbt_regs(void)
>>>>> +{
>>>>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>>>>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long) + 1;
>>>>> +}
>>>>> +
>>>>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>>>>> +{
>>>>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>>>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>>>>> +
>>>>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>>>>> +        res += kvm_loongarch_num_lbt_regs();
>>>>> +
>>>>> +    return res;
>>>>> +}
>>>>> +
>>>>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>>>> +                      u64 __user *uindices)
>>>>> +{
>>>>> +    u64 reg;
>>>>> +    unsigned int i;
>>>>> +
>>>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>>>> +        reg = KVM_IOC_CSRID(i);
>>>>> +        if (put_user(reg, uindices++))
>>>>> +            return -EFAULT;
>>>>> +    }
>>>> CSR_MAX_NUMS is max number of accessible CSR registers, instead only
>>>> part of them is used by vCPU model. By my understanding, there will be
>>>> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
>>>> better if real CSR register id and number is returned.
>>>>
>>> Did you mean we should only return the CSR registers initialized in this
>>> function
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
>>>
>>> ?
>>>
>>> That looks like a very large list and the values of the register IDs are
>>> not fully continuous. If that is the case, how do we maintain the
>>> get/set-able CSR register list?
>> It will be better if CSR register list can be categorized, for example
>> with LoongArch CPU manual CSR register is split into 8 types from
>> chapter 7.4 -- 7.11
>>
>> At the beginning, there is big array with size CSR_MAX_NUMS without
>> any category, it can be fine-gained in late.
> 
> Does that mean in the new `kvm_loongarch_copy_reg_indices` function, it
> is also okay to embed this big list in there?
Firstly I do not know how to use ioctl command KVM_GET_REG_LIST in VMM 
actually.

At the second from the word "determine which (special) registers are 
get/set-able", I think that it is better to set accessible CSR register 
number and ID rather than the total number CSR_MAX_NUMS.

+static int kvm_loongarch_num_csr_regs(struct kvm_vcpu *vcpu)
+{
+	unsigned int i, count;
+
+	count = 0
+	for (i = 0; i < CSR_MAX_NUMS; i++) {
+		if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
+			continue;
+		count++;
+	}
+	return count;
+}

static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
{
	/* +1 for the KVM_REG_LOONGARCH_COUNTER register */
+	unsigned long res = kvm_loongarch_num_csr_regs + KVM_MAX_CPUCFG_REGS + 1;

	if (kvm_guest_has_lbt(&vcpu->arch))
		res += kvm_loongarch_num_lbt_regs();

	return res;
}

static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
					  u64 __user *uindices)
{
	u64 reg;
	unsigned int i;

	for (i = 0; i < CSR_MAX_NUMS; i++) {
+                if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
+                    continue;
		reg = KVM_IOC_CSRID(i);
		if (put_user(reg, uindices++))
			return -EFAULT;
	}

Regards
Bibo Mao
> 
> Or do you want to extract the list from the `kvm_init_gcsr_flag`
> function and refactor both functions to share one single big list
> (probably in the kvm_host.h header)?
> 
> Because from what I could understand, your previous messages point to
> that we need to use this list to make out what CSR registers to return
> to the user space VMMs.

> 
>>
>> Regards
>> Bibo Mao
>>>
>>>> Regards
>>>> Bibo Mao
>>>>> +
>>>>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>>>>> +        reg = KVM_IOC_CPUCFG(i);
>>>>> +        if (put_user(reg, uindices++))
>>>>> +            return -EFAULT;
>>>>> +    }
>>>>> +
>>>>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>>>>> +    if (put_user(reg, uindices++))
>>>>> +        return -EFAULT;
>>>>> +
>>>>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>>>>> +        return 0;
>>>>> +
>>>>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>>>>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>>>>> +        if (put_user(reg, uindices++))
>>>>> +            return -EFAULT;
>>>>> +    }
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>>     long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>                  unsigned int ioctl, unsigned long arg)
>>>>>     {
>>>>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>             r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>>>>             break;
>>>>>         }
>>>>> +    case KVM_GET_REG_LIST: {
>>>>> +        struct kvm_reg_list __user *user_list = argp;
>>>>> +        struct kvm_reg_list reg_list;
>>>>> +        unsigned n;
>>>>> +
>>>>> +        r = -EFAULT;
>>>>> +        if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
>>>>> +            break;
>>>>> +        n = reg_list.n;
>>>>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>>>>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>>>>> +            break;
>>>>> +        r = -E2BIG;
>>>>> +        if (n < reg_list.n)
>>>>> +            break;
>>>>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>>>>> +        break;
>>>>> +    }
>>>>>         default:
>>>>>             r = -ENOIOCTLCMD;
>>>>>             break;
>>>>>
>>>>
>>> Thanks,
>>> Zixing
>>>
>>
> Thanks,
> Zixing
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  8:36         ` Bibo Mao
@ 2026-01-26  8:54           ` liushuyu
  2026-01-26  9:35             ` Bibo Mao
  0 siblings, 1 reply; 9+ messages in thread
From: liushuyu @ 2026-01-26  8:54 UTC (permalink / raw)
  To: Bibo Mao, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux

Hi Bibo,

>
>
> On 2026/1/26 下午12:22, liushuyu wrote:
>> Hi Bibo,
>>
>>>
>>>
>>> On 2026/1/26 上午11:38, liushuyu wrote:
>>>> Hi Bibo,
>>>>>
>>>>>
>>>>> On 2026/1/25 下午1:43, Zixing Liu wrote:
>>>>>> This ioctl can be used by userspace applications to determine which
>>>>>> (special) registers are get/set-able.
>>>>>>
>>>>>> This can be very useful for cross-platform VMMs so that they do not
>>>>>> have
>>>>>> to hardcode register indices for each supported architectures.
>>>>>>
>>>>>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>>>>>> ---
>>>>>>
>>>>>> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
>>>>>> VirtualBox-kvm in the future.
>>>>>>
>>>>>>     Documentation/virt/kvm/api.rst |  2 +-
>>>>>>     arch/loongarch/kvm/vcpu.c      | 69
>>>>>> ++++++++++++++++++++++++++++++++++
>>>>>>     2 files changed, 70 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/Documentation/virt/kvm/api.rst
>>>>>> b/Documentation/virt/kvm/api.rst
>>>>>> index 01a3abef8abb..f46dd8be282f 100644
>>>>>> --- a/Documentation/virt/kvm/api.rst
>>>>>> +++ b/Documentation/virt/kvm/api.rst
>>>>>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>>>>>     ---------------------
>>>>>>       :Capability: basic
>>>>>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>>>>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if
>>>>>> KVM_CAP_ONE_REG)
>>>>>>     :Type: vcpu ioctl
>>>>>>     :Parameters: struct kvm_reg_list (in/out)
>>>>>>     :Returns: 0 on success; -1 on error
>>>>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>>>>> index 656b954c1134..b884eb9c76aa 100644
>>>>>> --- a/arch/loongarch/kvm/vcpu.c
>>>>>> +++ b/arch/loongarch/kvm/vcpu.c
>>>>>> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct
>>>>>> kvm_vcpu *vcpu,
>>>>>>         return ret;
>>>>>>     }
>>>>>>     +static unsigned long kvm_loongarch_num_lbt_regs(void)
>>>>>> +{
>>>>>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>>>>>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long)
>>>>>> + 1;
>>>>>> +}
>>>>>> +
>>>>>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>>>>>> +{
>>>>>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>>>>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>>>>>> +
>>>>>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>>>>>> +        res += kvm_loongarch_num_lbt_regs();
>>>>>> +
>>>>>> +    return res;
>>>>>> +}
>>>>>> +
>>>>>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>>>>> +                      u64 __user *uindices)
>>>>>> +{
>>>>>> +    u64 reg;
>>>>>> +    unsigned int i;
>>>>>> +
>>>>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>>>>> +        reg = KVM_IOC_CSRID(i);
>>>>>> +        if (put_user(reg, uindices++))
>>>>>> +            return -EFAULT;
>>>>>> +    }
>>>>> CSR_MAX_NUMS is max number of accessible CSR registers, instead only
>>>>> part of them is used by vCPU model. By my understanding, there
>>>>> will be
>>>>> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
>>>>> better if real CSR register id and number is returned.
>>>>>
>>>> Did you mean we should only return the CSR registers initialized in
>>>> this
>>>> function
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
>>>>
>>>>
>>>> ?
>>>>
>>>> That looks like a very large list and the values of the register
>>>> IDs are
>>>> not fully continuous. If that is the case, how do we maintain the
>>>> get/set-able CSR register list?
>>> It will be better if CSR register list can be categorized, for example
>>> with LoongArch CPU manual CSR register is split into 8 types from
>>> chapter 7.4 -- 7.11
>>>
>>> At the beginning, there is big array with size CSR_MAX_NUMS without
>>> any category, it can be fine-gained in late.
>>
>> Does that mean in the new `kvm_loongarch_copy_reg_indices` function, it
>> is also okay to embed this big list in there?
> Firstly I do not know how to use ioctl command KVM_GET_REG_LIST in VMM
> actually.
>
> At the second from the word "determine which (special) registers are
> get/set-able", I think that it is better to set accessible CSR
> register number and ID rather than the total number CSR_MAX_NUMS. 
>
Understood. I will post a v2 patch, and we can continue the discussion
from there to see if I understood your points correctly.

> +static int kvm_loongarch_num_csr_regs(struct kvm_vcpu *vcpu)
> +{
> +    unsigned int i, count;
> +
> +    count = 0
> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
> +        if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
> +            continue;
> +        count++;
> +    }
> +    return count;
> +}
>
> static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
> {
>     /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
> +    unsigned long res = kvm_loongarch_num_csr_regs +
> KVM_MAX_CPUCFG_REGS + 1;
>
>     if (kvm_guest_has_lbt(&vcpu->arch))
>         res += kvm_loongarch_num_lbt_regs();
>
>     return res;
> }
>
> static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>                       u64 __user *uindices)
> {
>     u64 reg;
>     unsigned int i;
>
>     for (i = 0; i < CSR_MAX_NUMS; i++) {
> +                if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
> +                    continue;
>         reg = KVM_IOC_CSRID(i);
>         if (put_user(reg, uindices++))
>             return -EFAULT;
>     }
>
> Regards
> Bibo Mao
>>
>> Or do you want to extract the list from the `kvm_init_gcsr_flag`
>> function and refactor both functions to share one single big list
>> (probably in the kvm_host.h header)?
>>
>> Because from what I could understand, your previous messages point to
>> that we need to use this list to make out what CSR registers to return
>> to the user space VMMs.
>
>>
>>>
>>> Regards
>>> Bibo Mao
>>>>
>>>>> Regards
>>>>> Bibo Mao
>>>>>> +
>>>>>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>>>>>> +        reg = KVM_IOC_CPUCFG(i);
>>>>>> +        if (put_user(reg, uindices++))
>>>>>> +            return -EFAULT;
>>>>>> +    }
>>>>>> +
>>>>>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>>>>>> +    if (put_user(reg, uindices++))
>>>>>> +        return -EFAULT;
>>>>>> +
>>>>>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>>>>>> +        return 0;
>>>>>> +
>>>>>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>>>>>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>>>>>> +        if (put_user(reg, uindices++))
>>>>>> +            return -EFAULT;
>>>>>> +    }
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>>     long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>>                  unsigned int ioctl, unsigned long arg)
>>>>>>     {
>>>>>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>>             r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>>>>>             break;
>>>>>>         }
>>>>>> +    case KVM_GET_REG_LIST: {
>>>>>> +        struct kvm_reg_list __user *user_list = argp;
>>>>>> +        struct kvm_reg_list reg_list;
>>>>>> +        unsigned n;
>>>>>> +
>>>>>> +        r = -EFAULT;
>>>>>> +        if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
>>>>>> +            break;
>>>>>> +        n = reg_list.n;
>>>>>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>>>>>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>>>>>> +            break;
>>>>>> +        r = -E2BIG;
>>>>>> +        if (n < reg_list.n)
>>>>>> +            break;
>>>>>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>>>>>> +        break;
>>>>>> +    }
>>>>>>         default:
>>>>>>             r = -ENOIOCTLCMD;
>>>>>>             break;
>>>>>>
>>>>>
>>>> Thanks,
>>>> Zixing
>>>>
>>>
>> Thanks,
>> Zixing
>>
>
Thanks,

Zixing


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  8:54           ` liushuyu
@ 2026-01-26  9:35             ` Bibo Mao
  2026-01-26 10:03               ` liushuyu
  0 siblings, 1 reply; 9+ messages in thread
From: Bibo Mao @ 2026-01-26  9:35 UTC (permalink / raw)
  To: liushuyu, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux



On 2026/1/26 下午4:54, liushuyu wrote:
> Hi Bibo,
> 
>>
>>
>> On 2026/1/26 下午12:22, liushuyu wrote:
>>> Hi Bibo,
>>>
>>>>
>>>>
>>>> On 2026/1/26 上午11:38, liushuyu wrote:
>>>>> Hi Bibo,
>>>>>>
>>>>>>
>>>>>> On 2026/1/25 下午1:43, Zixing Liu wrote:
>>>>>>> This ioctl can be used by userspace applications to determine which
>>>>>>> (special) registers are get/set-able.
>>>>>>>
>>>>>>> This can be very useful for cross-platform VMMs so that they do not
>>>>>>> have
>>>>>>> to hardcode register indices for each supported architectures.
>>>>>>>
>>>>>>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>>>>>>> ---
>>>>>>>
>>>>>>> For example, this ioctl could be used by rust-vmm/rust-kvm or maybe
>>>>>>> VirtualBox-kvm in the future.
>>>>>>>
>>>>>>>      Documentation/virt/kvm/api.rst |  2 +-
>>>>>>>      arch/loongarch/kvm/vcpu.c      | 69
>>>>>>> ++++++++++++++++++++++++++++++++++
>>>>>>>      2 files changed, 70 insertions(+), 1 deletion(-)
>>>>>>>
>>>>>>> diff --git a/Documentation/virt/kvm/api.rst
>>>>>>> b/Documentation/virt/kvm/api.rst
>>>>>>> index 01a3abef8abb..f46dd8be282f 100644
>>>>>>> --- a/Documentation/virt/kvm/api.rst
>>>>>>> +++ b/Documentation/virt/kvm/api.rst
>>>>>>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>>>>>>      ---------------------
>>>>>>>        :Capability: basic
>>>>>>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>>>>>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if
>>>>>>> KVM_CAP_ONE_REG)
>>>>>>>      :Type: vcpu ioctl
>>>>>>>      :Parameters: struct kvm_reg_list (in/out)
>>>>>>>      :Returns: 0 on success; -1 on error
>>>>>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>>>>>> index 656b954c1134..b884eb9c76aa 100644
>>>>>>> --- a/arch/loongarch/kvm/vcpu.c
>>>>>>> +++ b/arch/loongarch/kvm/vcpu.c
>>>>>>> @@ -1186,6 +1186,57 @@ static int kvm_loongarch_vcpu_set_attr(struct
>>>>>>> kvm_vcpu *vcpu,
>>>>>>>          return ret;
>>>>>>>      }
>>>>>>>      +static unsigned long kvm_loongarch_num_lbt_regs(void)
>>>>>>> +{
>>>>>>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>>>>>>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long)
>>>>>>> + 1;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>>>>>>> +{
>>>>>>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>>>>>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>>>>>>> +
>>>>>>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>>>>>>> +        res += kvm_loongarch_num_lbt_regs();
>>>>>>> +
>>>>>>> +    return res;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>>>>>> +                      u64 __user *uindices)
>>>>>>> +{
>>>>>>> +    u64 reg;
>>>>>>> +    unsigned int i;
>>>>>>> +
>>>>>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>>>>>> +        reg = KVM_IOC_CSRID(i);
>>>>>>> +        if (put_user(reg, uindices++))
>>>>>>> +            return -EFAULT;
>>>>>>> +    }
>>>>>> CSR_MAX_NUMS is max number of accessible CSR registers, instead only
>>>>>> part of them is used by vCPU model. By my understanding, there
>>>>>> will be
>>>>>> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
>>>>>> better if real CSR register id and number is returned.
>>>>>>
>>>>> Did you mean we should only return the CSR registers initialized in
>>>>> this
>>>>> function
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
>>>>>
>>>>>
>>>>> ?
>>>>>
>>>>> That looks like a very large list and the values of the register
>>>>> IDs are
>>>>> not fully continuous. If that is the case, how do we maintain the
>>>>> get/set-able CSR register list?
>>>> It will be better if CSR register list can be categorized, for example
>>>> with LoongArch CPU manual CSR register is split into 8 types from
>>>> chapter 7.4 -- 7.11
>>>>
>>>> At the beginning, there is big array with size CSR_MAX_NUMS without
>>>> any category, it can be fine-gained in late.
>>>
>>> Does that mean in the new `kvm_loongarch_copy_reg_indices` function, it
>>> is also okay to embed this big list in there?
>> Firstly I do not know how to use ioctl command KVM_GET_REG_LIST in VMM
>> actually.
>>
>> At the second from the word "determine which (special) registers are
>> get/set-able", I think that it is better to set accessible CSR
>> register number and ID rather than the total number CSR_MAX_NUMS.
>>
> Understood. I will post a v2 patch, and we can continue the discussion
> from there to see if I understood your points correctly.
Remember to add such lines in function kvm_init_gcsr_flag() in the next 
round, since MSGINT CSR registers are missing here.

void kvm_init_gcsr_flag(void) {
+        if (cpu_has_msgint) {
+                set_gcsr_hw_flag(LOONGARCH_CSR_ISR0);
+                set_gcsr_hw_flag(LOONGARCH_CSR_ISR1);
+                set_gcsr_hw_flag(LOONGARCH_CSR_ISR2);
+                set_gcsr_hw_flag(LOONGARCH_CSR_ISR3);
+        }
}

Regards
Bibo Mao
> 
>> +static int kvm_loongarch_num_csr_regs(struct kvm_vcpu *vcpu)
>> +{
>> +    unsigned int i, count;
>> +
>> +    count = 0
>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>> +        if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
>> +            continue;
>> +        count++;
>> +    }
>> +    return count;
>> +}
>>
>> static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>> {
>>      /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>> +    unsigned long res = kvm_loongarch_num_csr_regs +
>> KVM_MAX_CPUCFG_REGS + 1;
>>
>>      if (kvm_guest_has_lbt(&vcpu->arch))
>>          res += kvm_loongarch_num_lbt_regs();
>>
>>      return res;
>> }
>>
>> static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>                        u64 __user *uindices)
>> {
>>      u64 reg;
>>      unsigned int i;
>>
>>      for (i = 0; i < CSR_MAX_NUMS; i++) {
>> +                if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
>> +                    continue;
>>          reg = KVM_IOC_CSRID(i);
>>          if (put_user(reg, uindices++))
>>              return -EFAULT;
>>      }
>>
>> Regards
>> Bibo Mao
>>>
>>> Or do you want to extract the list from the `kvm_init_gcsr_flag`
>>> function and refactor both functions to share one single big list
>>> (probably in the kvm_host.h header)?
>>>
>>> Because from what I could understand, your previous messages point to
>>> that we need to use this list to make out what CSR registers to return
>>> to the user space VMMs.
>>
>>>
>>>>
>>>> Regards
>>>> Bibo Mao
>>>>>
>>>>>> Regards
>>>>>> Bibo Mao
>>>>>>> +
>>>>>>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>>>>>>> +        reg = KVM_IOC_CPUCFG(i);
>>>>>>> +        if (put_user(reg, uindices++))
>>>>>>> +            return -EFAULT;
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>>>>>>> +    if (put_user(reg, uindices++))
>>>>>>> +        return -EFAULT;
>>>>>>> +
>>>>>>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>>>>>>> +        return 0;
>>>>>>> +
>>>>>>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>>>>>>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>>>>>>> +        if (put_user(reg, uindices++))
>>>>>>> +            return -EFAULT;
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>>      long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>>>                   unsigned int ioctl, unsigned long arg)
>>>>>>>      {
>>>>>>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>>>              r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>>>>>>              break;
>>>>>>>          }
>>>>>>> +    case KVM_GET_REG_LIST: {
>>>>>>> +        struct kvm_reg_list __user *user_list = argp;
>>>>>>> +        struct kvm_reg_list reg_list;
>>>>>>> +        unsigned n;
>>>>>>> +
>>>>>>> +        r = -EFAULT;
>>>>>>> +        if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
>>>>>>> +            break;
>>>>>>> +        n = reg_list.n;
>>>>>>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>>>>>>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>>>>>>> +            break;
>>>>>>> +        r = -E2BIG;
>>>>>>> +        if (n < reg_list.n)
>>>>>>> +            break;
>>>>>>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>>>>>>> +        break;
>>>>>>> +    }
>>>>>>>          default:
>>>>>>>              r = -ENOIOCTLCMD;
>>>>>>>              break;
>>>>>>>
>>>>>>
>>>>> Thanks,
>>>>> Zixing
>>>>>
>>>>
>>> Thanks,
>>> Zixing
>>>
>>
> Thanks,
> 
> Zixing
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch
  2026-01-26  9:35             ` Bibo Mao
@ 2026-01-26 10:03               ` liushuyu
  0 siblings, 0 replies; 9+ messages in thread
From: liushuyu @ 2026-01-26 10:03 UTC (permalink / raw)
  To: Bibo Mao, WANG Xuerui, Huacai Chen
  Cc: Kexy Biscuit, Mingcong Bai, Paolo Bonzini, Jonathan Corbet,
	Tianrui Zhao, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, kvm, linux-doc, linux-kernel,
	loongarch, linux-riscv, rust-for-linux

Hi Bibo,

>
>
> On 2026/1/26 下午4:54, liushuyu wrote:
>> Hi Bibo,
>>
>>>
>>>
>>> On 2026/1/26 下午12:22, liushuyu wrote:
>>>> Hi Bibo,
>>>>
>>>>>
>>>>>
>>>>> On 2026/1/26 上午11:38, liushuyu wrote:
>>>>>> Hi Bibo,
>>>>>>>
>>>>>>>
>>>>>>> On 2026/1/25 下午1:43, Zixing Liu wrote:
>>>>>>>> This ioctl can be used by userspace applications to determine
>>>>>>>> which
>>>>>>>> (special) registers are get/set-able.
>>>>>>>>
>>>>>>>> This can be very useful for cross-platform VMMs so that they do
>>>>>>>> not
>>>>>>>> have
>>>>>>>> to hardcode register indices for each supported architectures.
>>>>>>>>
>>>>>>>> Signed-off-by: Zixing Liu <liushuyu@aosc.io>
>>>>>>>> ---
>>>>>>>>
>>>>>>>> For example, this ioctl could be used by rust-vmm/rust-kvm or
>>>>>>>> maybe
>>>>>>>> VirtualBox-kvm in the future.
>>>>>>>>
>>>>>>>>      Documentation/virt/kvm/api.rst |  2 +-
>>>>>>>>      arch/loongarch/kvm/vcpu.c      | 69
>>>>>>>> ++++++++++++++++++++++++++++++++++
>>>>>>>>      2 files changed, 70 insertions(+), 1 deletion(-)
>>>>>>>>
>>>>>>>> diff --git a/Documentation/virt/kvm/api.rst
>>>>>>>> b/Documentation/virt/kvm/api.rst
>>>>>>>> index 01a3abef8abb..f46dd8be282f 100644
>>>>>>>> --- a/Documentation/virt/kvm/api.rst
>>>>>>>> +++ b/Documentation/virt/kvm/api.rst
>>>>>>>> @@ -3603,7 +3603,7 @@ VCPU matching underlying host.
>>>>>>>>      ---------------------
>>>>>>>>        :Capability: basic
>>>>>>>> -:Architectures: arm64, mips, riscv, x86 (if KVM_CAP_ONE_REG)
>>>>>>>> +:Architectures: arm64, loongarch, mips, riscv, x86 (if
>>>>>>>> KVM_CAP_ONE_REG)
>>>>>>>>      :Type: vcpu ioctl
>>>>>>>>      :Parameters: struct kvm_reg_list (in/out)
>>>>>>>>      :Returns: 0 on success; -1 on error
>>>>>>>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>>>>>>> index 656b954c1134..b884eb9c76aa 100644
>>>>>>>> --- a/arch/loongarch/kvm/vcpu.c
>>>>>>>> +++ b/arch/loongarch/kvm/vcpu.c
>>>>>>>> @@ -1186,6 +1186,57 @@ static int
>>>>>>>> kvm_loongarch_vcpu_set_attr(struct
>>>>>>>> kvm_vcpu *vcpu,
>>>>>>>>          return ret;
>>>>>>>>      }
>>>>>>>>      +static unsigned long kvm_loongarch_num_lbt_regs(void)
>>>>>>>> +{
>>>>>>>> +    /* +1 for the LBT_FTOP flag (inside arch.fpu) */
>>>>>>>> +    return sizeof(struct loongarch_lbt) / sizeof(unsigned long)
>>>>>>>> + 1;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu
>>>>>>>> *vcpu)
>>>>>>>> +{
>>>>>>>> +    /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>>>>>>> +    unsigned long res = CSR_MAX_NUMS + KVM_MAX_CPUCFG_REGS + 1;
>>>>>>>> +
>>>>>>>> +    if (kvm_guest_has_lbt(&vcpu->arch))
>>>>>>>> +        res += kvm_loongarch_num_lbt_regs();
>>>>>>>> +
>>>>>>>> +    return res;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>>>>>>> +                      u64 __user *uindices)
>>>>>>>> +{
>>>>>>>> +    u64 reg;
>>>>>>>> +    unsigned int i;
>>>>>>>> +
>>>>>>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>>>>>>> +        reg = KVM_IOC_CSRID(i);
>>>>>>>> +        if (put_user(reg, uindices++))
>>>>>>>> +            return -EFAULT;
>>>>>>>> +    }
>>>>>>> CSR_MAX_NUMS is max number of accessible CSR registers, instead
>>>>>>> only
>>>>>>> part of them is used by vCPU model. By my understanding, there
>>>>>>> will be
>>>>>>> no much meaning if CSR_MAX_NUMS is returned. And I think it will be
>>>>>>> better if real CSR register id and number is returned.
>>>>>>>
>>>>>> Did you mean we should only return the CSR registers initialized in
>>>>>> this
>>>>>> function
>>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/kvm/main.c?id=63804fed149a6750ffd28610c5c1c98cce6bd377#n48
>>>>>>
>>>>>>
>>>>>>
>>>>>> ?
>>>>>>
>>>>>> That looks like a very large list and the values of the register
>>>>>> IDs are
>>>>>> not fully continuous. If that is the case, how do we maintain the
>>>>>> get/set-able CSR register list?
>>>>> It will be better if CSR register list can be categorized, for
>>>>> example
>>>>> with LoongArch CPU manual CSR register is split into 8 types from
>>>>> chapter 7.4 -- 7.11
>>>>>
>>>>> At the beginning, there is big array with size CSR_MAX_NUMS without
>>>>> any category, it can be fine-gained in late.
>>>>
>>>> Does that mean in the new `kvm_loongarch_copy_reg_indices`
>>>> function, it
>>>> is also okay to embed this big list in there?
>>> Firstly I do not know how to use ioctl command KVM_GET_REG_LIST in VMM
>>> actually.
>>>
>>> At the second from the word "determine which (special) registers are
>>> get/set-able", I think that it is better to set accessible CSR
>>> register number and ID rather than the total number CSR_MAX_NUMS.
>>>
>> Understood. I will post a v2 patch, and we can continue the discussion
>> from there to see if I understood your points correctly.
> Remember to add such lines in function kvm_init_gcsr_flag() in the
> next round, since MSGINT CSR registers are missing here.
>
> void kvm_init_gcsr_flag(void) {
> +        if (cpu_has_msgint) {
> +                set_gcsr_hw_flag(LOONGARCH_CSR_ISR0);
> +                set_gcsr_hw_flag(LOONGARCH_CSR_ISR1);
> +                set_gcsr_hw_flag(LOONGARCH_CSR_ISR2);
> +                set_gcsr_hw_flag(LOONGARCH_CSR_ISR3);
> +        }
> } 
>
I think this might need to be a separate patch or commit.

Do you want me to include this in the KVM_GET_REG_LIST patch, or do you
want to submit this change separately?

> Regards
> Bibo Mao
>>
>>> +static int kvm_loongarch_num_csr_regs(struct kvm_vcpu *vcpu)
>>> +{
>>> +    unsigned int i, count;
>>> +
>>> +    count = 0
>>> +    for (i = 0; i < CSR_MAX_NUMS; i++) {
>>> +        if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
>>> +            continue;
>>> +        count++;
>>> +    }
>>> +    return count;
>>> +}
>>>
>>> static unsigned long kvm_loongarch_num_regs(struct kvm_vcpu *vcpu)
>>> {
>>>      /* +1 for the KVM_REG_LOONGARCH_COUNTER register */
>>> +    unsigned long res = kvm_loongarch_num_csr_regs +
>>> KVM_MAX_CPUCFG_REGS + 1;
>>>
>>>      if (kvm_guest_has_lbt(&vcpu->arch))
>>>          res += kvm_loongarch_num_lbt_regs();
>>>
>>>      return res;
>>> }
>>>
>>> static int kvm_loongarch_copy_reg_indices(struct kvm_vcpu *vcpu,
>>>                        u64 __user *uindices)
>>> {
>>>      u64 reg;
>>>      unsigned int i;
>>>
>>>      for (i = 0; i < CSR_MAX_NUMS; i++) {
>>> +                if (!(get_gcsr_flag(i) & (SW_GCSR | HW_GCSR)))
>>> +                    continue;
>>>          reg = KVM_IOC_CSRID(i);
>>>          if (put_user(reg, uindices++))
>>>              return -EFAULT;
>>>      }
>>>
>>> Regards
>>> Bibo Mao
>>>>
>>>> Or do you want to extract the list from the `kvm_init_gcsr_flag`
>>>> function and refactor both functions to share one single big list
>>>> (probably in the kvm_host.h header)?
>>>>
>>>> Because from what I could understand, your previous messages point to
>>>> that we need to use this list to make out what CSR registers to return
>>>> to the user space VMMs.
>>>
>>>>
>>>>>
>>>>> Regards
>>>>> Bibo Mao
>>>>>>
>>>>>>> Regards
>>>>>>> Bibo Mao
>>>>>>>> +
>>>>>>>> +    for (i = 0; i < KVM_MAX_CPUCFG_REGS; i++) {
>>>>>>>> +        reg = KVM_IOC_CPUCFG(i);
>>>>>>>> +        if (put_user(reg, uindices++))
>>>>>>>> +            return -EFAULT;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    reg = KVM_REG_LOONGARCH_COUNTER;
>>>>>>>> +    if (put_user(reg, uindices++))
>>>>>>>> +        return -EFAULT;
>>>>>>>> +
>>>>>>>> +    if (!kvm_guest_has_lbt(&vcpu->arch))
>>>>>>>> +        return 0;
>>>>>>>> +
>>>>>>>> +    for (i = 1; i <= kvm_loongarch_num_lbt_regs(); i++) {
>>>>>>>> +        reg = (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | i);
>>>>>>>> +        if (put_user(reg, uindices++))
>>>>>>>> +            return -EFAULT;
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>>>>                   unsigned int ioctl, unsigned long arg)
>>>>>>>>      {
>>>>>>>> @@ -1251,6 +1302,24 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>>>>>>>              r = kvm_loongarch_vcpu_set_attr(vcpu, &attr);
>>>>>>>>              break;
>>>>>>>>          }
>>>>>>>> +    case KVM_GET_REG_LIST: {
>>>>>>>> +        struct kvm_reg_list __user *user_list = argp;
>>>>>>>> +        struct kvm_reg_list reg_list;
>>>>>>>> +        unsigned n;
>>>>>>>> +
>>>>>>>> +        r = -EFAULT;
>>>>>>>> +        if (copy_from_user(&reg_list, user_list,
>>>>>>>> sizeof(reg_list)))
>>>>>>>> +            break;
>>>>>>>> +        n = reg_list.n;
>>>>>>>> +        reg_list.n = kvm_loongarch_num_regs(vcpu);
>>>>>>>> +        if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
>>>>>>>> +            break;
>>>>>>>> +        r = -E2BIG;
>>>>>>>> +        if (n < reg_list.n)
>>>>>>>> +            break;
>>>>>>>> +        r = kvm_loongarch_copy_reg_indices(vcpu, user_list->reg);
>>>>>>>> +        break;
>>>>>>>> +    }
>>>>>>>>          default:
>>>>>>>>              r = -ENOIOCTLCMD;
>>>>>>>>              break;
>>>>>>>>
>>>>>>>
>>>>>> Thanks,
>>>>>> Zixing
>>>>>>
>>>>>
>>>> Thanks,
>>>> Zixing
>>>>
>>>
>> Thanks,
>>
>> Zixing
>>
>
Thanks,

Zixing


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-01-26 10:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-25  5:43 [PATCH 1/1] KVM: Add KVM_GET_REG_LIST ioctl for LoongArch Zixing Liu
2026-01-26  2:09 ` Bibo Mao
2026-01-26  3:38   ` liushuyu
2026-01-26  3:57     ` Bibo Mao
2026-01-26  4:22       ` liushuyu
2026-01-26  8:36         ` Bibo Mao
2026-01-26  8:54           ` liushuyu
2026-01-26  9:35             ` Bibo Mao
2026-01-26 10:03               ` liushuyu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®