Skip to content

Commit c783253

Browse files
6eanutavpatel
authored andcommitted
RISC-V: KVM: Fix sign extension for MMIO loads
The kvm_riscv_vcpu_mmio_return() function handles MMIO read results by writing the data back to the guest register. For signed load instructions (LB, LH, LW on RV64), the value needs sign-extension from a smaller integer to unsigned long. The current code uses: (ulong)data << shift >> shift but (ulong) makes the right shift a logical shift (zero-extend) rather than an arithmetic shift (sign-extend), causing incorrect results when the MMIO device returns a negative value. For example, LB reading 0x80 would return 128 instead of -128. Fix this by casting to (long) after the left shift so that the subsequent right shift is arithmetic and correctly propagates the sign bit: (long)((ulong)data << shift) >> shift Additionally, remove the unnecessary shift assignment for LBU (unsigned byte load) since it does not need sign extension. This makes LBU consistent with LHU and LWU which already keep shift = 0. Fixes: b91f0e4 ("RISC-V: KVM: Factor-out instruction emulation into separate sources") Signed-off-by: Jiakai Xu <jiakaiPeanut@gmail.com> Signed-off-by: Jiakai Xu <xujiakai2025@iscas.ac.cn> Assisted-by: OpenClaw:DeepSeek-V3.2 Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260514081752.472987-1-xujiakai2025@iscas.ac.cn Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent fdb69d4 commit c783253

1 file changed

Lines changed: 4 additions & 5 deletions

File tree

arch/riscv/kvm/vcpu_insn.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,6 @@ int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
415415
shift = 8 * (sizeof(ulong) - len);
416416
} else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) {
417417
len = 1;
418-
shift = 8 * (sizeof(ulong) - len);
419418
#ifdef CONFIG_64BIT
420419
} else if ((insn & INSN_MASK_LD) == INSN_MATCH_LD) {
421420
len = 8;
@@ -649,22 +648,22 @@ int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
649648
case 1:
650649
data8 = *((u8 *)run->mmio.data);
651650
SET_RD(insn, &vcpu->arch.guest_context,
652-
(ulong)data8 << shift >> shift);
651+
(long)((ulong)data8 << shift) >> shift);
653652
break;
654653
case 2:
655654
data16 = *((u16 *)run->mmio.data);
656655
SET_RD(insn, &vcpu->arch.guest_context,
657-
(ulong)data16 << shift >> shift);
656+
(long)((ulong)data16 << shift) >> shift);
658657
break;
659658
case 4:
660659
data32 = *((u32 *)run->mmio.data);
661660
SET_RD(insn, &vcpu->arch.guest_context,
662-
(ulong)data32 << shift >> shift);
661+
(long)((ulong)data32 << shift) >> shift);
663662
break;
664663
case 8:
665664
data64 = *((u64 *)run->mmio.data);
666665
SET_RD(insn, &vcpu->arch.guest_context,
667-
(ulong)data64 << shift >> shift);
666+
(long)((ulong)data64 << shift) >> shift);
668667
break;
669668
default:
670669
return -EOPNOTSUPP;

0 commit comments

Comments
 (0)