@@ -567,18 +567,17 @@ struct thumb_decode {
static bool decode_thumb_wb(struct kvm_vcpu *vcpu, struct arm_insn *ti)
{
u8 imm8 = ti->instr & 0xff;
- u32 offset_addr = vcpu->arch.hxfar;
ti->P = (ti->instr >> 10) & 1;
ti->U = (ti->instr >> 9) & 1;
ti->Rn = (ti->instr >> 16) & 0xf;
ti->Rd = (ti->instr >> 12) & 0xf;
- /* Handle Writeback */
+ /* Handle Writeback: offset_addr relative to fault address. */
if (!ti->P && ti->U)
- ti->offset_addr = offset_addr + imm8;
+ ti->offset_addr = imm8;
else if (!ti->P && !ti->U)
- ti->offset_addr = offset_addr - imm8;
+ ti->offset_addr = -imm8;
return true;
}
@@ -740,8 +739,10 @@ static bool execute(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
if (kvm_vcpu_reg_is_pc(vcpu, ai->Rn))
return false;
- if (!ai->P)
- *vcpu_reg(vcpu, ai->Rn) = ai->offset_addr;
+ if (!ai->P) {
+ *vcpu_reg(vcpu, ai->Rn)
+ = vcpu->arch.hxfar + ai->offset_addr;
+ }
vcpu->arch.mmio.sign_extend = ai->sign_extend;
return true;
}