Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()
@ 2026-06-04 12:34 Qiang Ma
  2026-06-04 12:59 ` sashiko-bot
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Qiang Ma @ 2026-06-04 12:34 UTC (permalink / raw)
  To: zhaotianrui, maobibo, chenhuacai, kernel
  Cc: kvm, loongarch, linux-kernel, Qiang Ma, stable

The LoongArch CSRXCHG instruction returns the full old CSR value in rd
after applying the masked update. kvm_emu_xchg_csr() currently masks
the saved value before returning it to the guest, so rd receives only
the bits selected by the write mask.

That breaks the architectural behavior and makes a zero mask return 0
instead of the previous CSR value. Keep the masked CSR update, but
return the unmodified old CSR value.

Fixes: da50f5a693ff ("LoongArch: KVM: Implement handle csr exception")
Cc: stable@vger.kernel.org
Signed-off-by: Qiang Ma <maqianga@uniontech.com>
---
 arch/loongarch/kvm/exit.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index 3b95cd0f989b..264813d45cbe 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid,
 		old = kvm_read_sw_gcsr(csr, csrid);
 		val = (old & ~csr_mask) | (val & csr_mask);
 		kvm_write_sw_gcsr(csr, csrid, val);
-		old = old & csr_mask;
 	} else
 		pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
 
-- 
2.20.1


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

* Re: [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()
  2026-06-04 12:34 [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr() Qiang Ma
@ 2026-06-04 12:59 ` sashiko-bot
  2026-06-05  1:41 ` Bibo Mao
  2026-06-05  7:19 ` Bibo Mao
  2 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-06-04 12:59 UTC (permalink / raw)
  To: Qiang Ma; +Cc: kvm

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Emulated instructions writing to $r0 corrupt `vcpu->arch.gprs[0]` for subsequent emulated instructions.
--

commit 8b252fdbff14650492d9c9a2864373942e2fb35e
Author: Qiang Ma <maqianga@uniontech.com>

LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()

The LoongArch CSRXCHG instruction returns the full old CSR value in rd
after applying the masked update. kvm_emu_xchg_csr() currently masks
the saved value before returning it to the guest, so rd receives only
the bits selected by the write mask.

That breaks the architectural behavior and makes a zero mask return 0
instead of the previous CSR value. Keep the masked CSR update, but
return the unmodified old CSR value.

Fixes: da50f5a693ff ("LoongArch: KVM: Implement handle csr exception")
Cc: stable@vger.kernel.org
Signed-off-by: Qiang Ma <maqianga@uniontech.com>

> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index 3b95cd0f989b0..264813d45cbe0 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid,
>  		old = kvm_read_sw_gcsr(csr, csrid);
>  		val = (old & ~csr_mask) | (val & csr_mask);
>  		kvm_write_sw_gcsr(csr, csrid, val);
> -		old = old & csr_mask;
>  	} else
>  		pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
>  

[Severity: High]
This isn't a bug introduced by this patch, but does the return value from
kvm_emu_xchg_csr() overwrite vcpu->arch.gprs[0] if the destination
register rd is 0?

Looking at the caller kvm_handle_csr() in arch/loongarch/kvm/exit.c:

	switch (rj) {
	case 0: /* process csrrd */
		val = kvm_emu_read_csr(vcpu, csrid);
		vcpu->arch.gprs[rd] = val;
		break;
	...
	default: /* process csrxchg */
		val = vcpu->arch.gprs[rd];
		csr_mask = vcpu->arch.gprs[rj];
		val = kvm_emu_xchg_csr(vcpu, csrid, csr_mask, val);
		vcpu->arch.gprs[rd] = val;
	}

Since $r0 is hardwired to 0 on LoongArch, if a guest executes an emulated
instruction with $r0 as the destination, kvm_handle_csr() will write a non-zero
value to vcpu->arch.gprs[0]. 

KVM does not clear vcpu->arch.gprs[0] between VM exits. If the guest
subsequently executes another KVM-emulated instruction that uses $r0 as an
input, KVM will read the stale non-zero value instead of 0.

Can this corrupt the guest context state for subsequent emulated instructions?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260604123433.3182173-1-maqianga@uniontech.com?part=1

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

* Re: [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()
  2026-06-04 12:34 [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr() Qiang Ma
  2026-06-04 12:59 ` sashiko-bot
@ 2026-06-05  1:41 ` Bibo Mao
       [not found]   ` <4CD61A5AB07B2388+7fa119a1-af5f-4def-b2c4-6073fc397b10@uniontech.com>
  2026-06-05  7:19 ` Bibo Mao
  2 siblings, 1 reply; 6+ messages in thread
From: Bibo Mao @ 2026-06-05  1:41 UTC (permalink / raw)
  To: Qiang Ma, zhaotianrui, chenhuacai, kernel
  Cc: kvm, loongarch, linux-kernel, stable



On 2026/6/4 下午8:34, Qiang Ma wrote:
> The LoongArch CSRXCHG instruction returns the full old CSR value in rd
> after applying the masked update. kvm_emu_xchg_csr() currently masks
> the saved value before returning it to the guest, so rd receives only
> the bits selected by the write mask.
> 
> That breaks the architectural behavior and makes a zero mask return 0
> instead of the previous CSR value. Keep the masked CSR update, but
> return the unmodified old CSR value.
> 
> Fixes: da50f5a693ff ("LoongArch: KVM: Implement handle csr exception")
> Cc: stable@vger.kernel.org
> Signed-off-by: Qiang Ma <maqianga@uniontech.com>
> ---
>   arch/loongarch/kvm/exit.c | 1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index 3b95cd0f989b..264813d45cbe 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid,
>   		old = kvm_read_sw_gcsr(csr, csrid);
>   		val = (old & ~csr_mask) | (val & csr_mask);
>   		kvm_write_sw_gcsr(csr, csrid, val);
> -		old = old & csr_mask;

Hi Qiang Ma

This is correct from the manual. Is there any test case or problem in 
practice?  I want to evaluate severity about this problem.

Regards
Bibo Mao
>   	} else
>   		pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
>   
> 


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

* Re: [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()
       [not found]   ` <4CD61A5AB07B2388+7fa119a1-af5f-4def-b2c4-6073fc397b10@uniontech.com>
@ 2026-06-05  6:27     ` Bibo Mao
  2026-06-05  6:50       ` Qiang Ma
  0 siblings, 1 reply; 6+ messages in thread
From: Bibo Mao @ 2026-06-05  6:27 UTC (permalink / raw)
  To: Qiang Ma, zhaotianrui, chenhuacai, kernel
  Cc: kvm, loongarch, linux-kernel, stable



On 2026/6/5 下午2:08, Qiang Ma wrote:
> 
> 在 2026/6/5 09:41, Bibo Mao 写道:
>>
>>
>> On 2026/6/4 下午8:34, Qiang Ma wrote:
>>> The LoongArch CSRXCHG instruction returns the full old CSR value in rd
>>> after applying the masked update. kvm_emu_xchg_csr() currently masks
>>> the saved value before returning it to the guest, so rd receives only
>>> the bits selected by the write mask.
>>>
>>> That breaks the architectural behavior and makes a zero mask return 0
>>> instead of the previous CSR value. Keep the masked CSR update, but
>>> return the unmodified old CSR value.
>>>
>>> Fixes: da50f5a693ff ("LoongArch: KVM: Implement handle csr exception")
>>> Cc: stable@vger.kernel.org
>>> Signed-off-by: Qiang Ma <maqianga@uniontech.com>
>>> ---
>>>   arch/loongarch/kvm/exit.c | 1 -
>>>   1 file changed, 1 deletion(-)
>>>
>>> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
>>> index 3b95cd0f989b..264813d45cbe 100644
>>> --- a/arch/loongarch/kvm/exit.c
>>> +++ b/arch/loongarch/kvm/exit.c
>>> @@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct 
>>> kvm_vcpu *vcpu, int csrid,
>>>           old = kvm_read_sw_gcsr(csr, csrid);
>>>           val = (old & ~csr_mask) | (val & csr_mask);
>>>           kvm_write_sw_gcsr(csr, csrid, val);
>>> -        old = old & csr_mask;
>>
>> Hi Qiang Ma
>>
>> This is correct from the manual. Is there any test case or problem in 
>> practice?  I want to evaluate severity about this problem.
> 
> Yes, I have written a selftest for this. Below are the test results 
> comparing without and with the patch.
> 
> I have not encountered this problem in an actual operating environment.
> 
> without this patch:
> 
> [root@node1 loongarch]# ./csrxchg_testRandom seed: 0x6b8b4567Testing 
> guest mode: PA-bits:47, VA-bits:47, 16K pagesTesting CSR: IMPCTL1 
> (implementation-specific control 1)Initial guest CSR value: 
> 0x10000100Checking that CSRXCHG updates the CSR per mask and returnsthe 
> full old CSR value in rd.
> 
> Case: zero-maskwrite value : 0xffffffffffffffffwrite mask : 0returned 
> old CSR value : 0expected old CSR value : 0x10000100CSR value after 
> update : 0x10000100expected CSR after update: 0x10000100result : FAIL
> 
> Case: partial-maskwrite value : 0write mask : 0x100returned old CSR 
> value : 0x100expected old CSR value : 0x10000100CSR value after update : 
> 0x10000000expected CSR after update: 0x10000000result : FAIL
> 
> CSRXCHG test FAILED
> 
> with this patch:
> 
> [root@node1 loongarch]# ./csrxchg_testRandom seed: 0x6b8b4567Testing 
> guest mode: PA-bits:47, VA-bits:47, 16K pagesTesting CSR: IMPCTL1 
> (implementation-specific control 1)Initial guest CSR value: 
> 0x10000100Checking that CSRXCHG updates the CSR per mask and returnsthe 
> full old CSR value in rd.
> 
> Case: zero-maskwrite value : 0xffffffffffffffffwrite mask : 0returned 
> old CSR value : 0x10000100expected old CSR value : 0x10000100CSR value 
> after update : 0x10000100expected CSR after update: 0x10000100result : PASS
> 
> Case: partial-maskwrite value : 0write mask : 0x100returned old CSR 
> value : 0x10000100expected old CSR value : 0x10000100CSR value after 
> update : 0x10000000expected CSR after update: 0x10000000result : PASS
> 
> CSRXCHG test PASSED
> 
> Should this selftest case be included as a patch and sent along with 
> version 2?
No, it is not necessary. I test csrxchg instruction by myself, the 
manual is right, return value should be the whole old value.

My meaning is that what is the scenery where CSR register is SW emulated 
in KVM mode, or this problem is found by code browsing.

Regards
Bibo Mao

> 
>>
>> Regards
>> Bibo Mao
>>>       } else
>>>           pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", 
>>> csrid, vcpu->arch.pc);
>>>
>>
>>


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

* Re: [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()
  2026-06-05  6:27     ` Bibo Mao
@ 2026-06-05  6:50       ` Qiang Ma
  0 siblings, 0 replies; 6+ messages in thread
From: Qiang Ma @ 2026-06-05  6:50 UTC (permalink / raw)
  To: Bibo Mao, zhaotianrui, chenhuacai, kernel
  Cc: kvm, loongarch, linux-kernel, stable


在 2026/6/5 14:27, Bibo Mao 写道:
>
>
> On 2026/6/5 下午2:08, Qiang Ma wrote:
>>
>> 在 2026/6/5 09:41, Bibo Mao 写道:
>>>
>>>
>>> On 2026/6/4 下午8:34, Qiang Ma wrote:
>>>> The LoongArch CSRXCHG instruction returns the full old CSR value in rd
>>>> after applying the masked update. kvm_emu_xchg_csr() currently masks
>>>> the saved value before returning it to the guest, so rd receives only
>>>> the bits selected by the write mask.
>>>>
>>>> That breaks the architectural behavior and makes a zero mask return 0
>>>> instead of the previous CSR value. Keep the masked CSR update, but
>>>> return the unmodified old CSR value.
>>>>
>>>> Fixes: da50f5a693ff ("LoongArch: KVM: Implement handle csr exception")
>>>> Cc: stable@vger.kernel.org
>>>> Signed-off-by: Qiang Ma <maqianga@uniontech.com>
>>>> ---
>>>>   arch/loongarch/kvm/exit.c | 1 -
>>>>   1 file changed, 1 deletion(-)
>>>>
>>>> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
>>>> index 3b95cd0f989b..264813d45cbe 100644
>>>> --- a/arch/loongarch/kvm/exit.c
>>>> +++ b/arch/loongarch/kvm/exit.c
>>>> @@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct 
>>>> kvm_vcpu *vcpu, int csrid,
>>>>           old = kvm_read_sw_gcsr(csr, csrid);
>>>>           val = (old & ~csr_mask) | (val & csr_mask);
>>>>           kvm_write_sw_gcsr(csr, csrid, val);
>>>> -        old = old & csr_mask;
>>>
>>> Hi Qiang Ma
>>>
>>> This is correct from the manual. Is there any test case or problem 
>>> in practice?  I want to evaluate severity about this problem.
>>
>> Yes, I have written a selftest for this. Below are the test results 
>> comparing without and with the patch.
>>
>> I have not encountered this problem in an actual operating environment.
>>
>> without this patch:
>>
>> [root@node1 loongarch]# ./csrxchg_testRandom seed: 0x6b8b4567Testing 
>> guest mode: PA-bits:47, VA-bits:47, 16K pagesTesting CSR: IMPCTL1 
>> (implementation-specific control 1)Initial guest CSR value: 
>> 0x10000100Checking that CSRXCHG updates the CSR per mask and 
>> returnsthe full old CSR value in rd.
>>
>> Case: zero-maskwrite value : 0xffffffffffffffffwrite mask : 0returned 
>> old CSR value : 0expected old CSR value : 0x10000100CSR value after 
>> update : 0x10000100expected CSR after update: 0x10000100result : FAIL
>>
>> Case: partial-maskwrite value : 0write mask : 0x100returned old CSR 
>> value : 0x100expected old CSR value : 0x10000100CSR value after 
>> update : 0x10000000expected CSR after update: 0x10000000result : FAIL
>>
>> CSRXCHG test FAILED
>>
>> with this patch:
>>
>> [root@node1 loongarch]# ./csrxchg_testRandom seed: 0x6b8b4567Testing 
>> guest mode: PA-bits:47, VA-bits:47, 16K pagesTesting CSR: IMPCTL1 
>> (implementation-specific control 1)Initial guest CSR value: 
>> 0x10000100Checking that CSRXCHG updates the CSR per mask and 
>> returnsthe full old CSR value in rd.
>>
>> Case: zero-maskwrite value : 0xffffffffffffffffwrite mask : 0returned 
>> old CSR value : 0x10000100expected old CSR value : 0x10000100CSR 
>> value after update : 0x10000100expected CSR after update: 
>> 0x10000100result : PASS
>>
>> Case: partial-maskwrite value : 0write mask : 0x100returned old CSR 
>> value : 0x10000100expected old CSR value : 0x10000100CSR value after 
>> update : 0x10000000expected CSR after update: 0x10000000result : PASS
>>
>> CSRXCHG test PASSED
>>
>> Should this selftest case be included as a patch and sent along with 
>> version 2?
> No, it is not necessary. I test csrxchg instruction by myself, the 
> manual is right, return value should be the whole old value.
>
> My meaning is that what is the scenery where CSR register is SW 
> emulated in KVM mode, or this problem is found by code browsing.
Understood. This was discovered while browsing the code.
>
> Regards
> Bibo Mao
>
>>
>>>
>>> Regards
>>> Bibo Mao
>>>>       } else
>>>>           pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", 
>>>> csrid, vcpu->arch.pc);
>>>>
>>>
>>>
>
>


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

* Re: [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr()
  2026-06-04 12:34 [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr() Qiang Ma
  2026-06-04 12:59 ` sashiko-bot
  2026-06-05  1:41 ` Bibo Mao
@ 2026-06-05  7:19 ` Bibo Mao
  2 siblings, 0 replies; 6+ messages in thread
From: Bibo Mao @ 2026-06-05  7:19 UTC (permalink / raw)
  To: Qiang Ma, zhaotianrui, chenhuacai, kernel
  Cc: kvm, loongarch, linux-kernel, stable



On 2026/6/4 下午8:34, Qiang Ma wrote:
> The LoongArch CSRXCHG instruction returns the full old CSR value in rd
> after applying the masked update. kvm_emu_xchg_csr() currently masks
> the saved value before returning it to the guest, so rd receives only
> the bits selected by the write mask.
> 
> That breaks the architectural behavior and makes a zero mask return 0
> instead of the previous CSR value. Keep the masked CSR update, but
> return the unmodified old CSR value.
> 
> Fixes: da50f5a693ff ("LoongArch: KVM: Implement handle csr exception")
> Cc: stable@vger.kernel.org
> Signed-off-by: Qiang Ma <maqianga@uniontech.com>
> ---
>   arch/loongarch/kvm/exit.c | 1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index 3b95cd0f989b..264813d45cbe 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -103,7 +103,6 @@ static unsigned long kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid,
>   		old = kvm_read_sw_gcsr(csr, csrid);
>   		val = (old & ~csr_mask) | (val & csr_mask);
>   		kvm_write_sw_gcsr(csr, csrid, val);
> -		old = old & csr_mask;
>   	} else
>   		pr_warn_once("Unsupported csrxchg 0x%x with pc %lx\n", csrid, vcpu->arch.pc);
>   
> 
Reviewed-by: Bibo Mao <maobibo@loongson.cn>


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

end of thread, other threads:[~2026-06-05  7:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-04 12:34 [PATCH] LoongArch: KVM: return full old CSR value from kvm_emu_xchg_csr() Qiang Ma
2026-06-04 12:59 ` sashiko-bot
2026-06-05  1:41 ` Bibo Mao
     [not found]   ` <4CD61A5AB07B2388+7fa119a1-af5f-4def-b2c4-6073fc397b10@uniontech.com>
2026-06-05  6:27     ` Bibo Mao
2026-06-05  6:50       ` Qiang Ma
2026-06-05  7:19 ` Bibo Mao

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