diff options
Diffstat (limited to 'arch/arm/kvm/mmio.c')
-rw-r--r-- | arch/arm/kvm/mmio.c | 46 |
1 files changed, 18 insertions, 28 deletions
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c index 98a870ff1a5c..72a12f2171b2 100644 --- a/arch/arm/kvm/mmio.c +++ b/arch/arm/kvm/mmio.c | |||
@@ -33,16 +33,16 @@ | |||
33 | */ | 33 | */ |
34 | int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) | 34 | int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) |
35 | { | 35 | { |
36 | __u32 *dest; | 36 | unsigned long *dest; |
37 | unsigned int len; | 37 | unsigned int len; |
38 | int mask; | 38 | int mask; |
39 | 39 | ||
40 | if (!run->mmio.is_write) { | 40 | if (!run->mmio.is_write) { |
41 | dest = vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt); | 41 | dest = vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt); |
42 | memset(dest, 0, sizeof(int)); | 42 | *dest = 0; |
43 | 43 | ||
44 | len = run->mmio.len; | 44 | len = run->mmio.len; |
45 | if (len > 4) | 45 | if (len > sizeof(unsigned long)) |
46 | return -EINVAL; | 46 | return -EINVAL; |
47 | 47 | ||
48 | memcpy(dest, run->mmio.data, len); | 48 | memcpy(dest, run->mmio.data, len); |
@@ -50,7 +50,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
50 | trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, | 50 | trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, |
51 | *((u64 *)run->mmio.data)); | 51 | *((u64 *)run->mmio.data)); |
52 | 52 | ||
53 | if (vcpu->arch.mmio_decode.sign_extend && len < 4) { | 53 | if (vcpu->arch.mmio_decode.sign_extend && |
54 | len < sizeof(unsigned long)) { | ||
54 | mask = 1U << ((len * 8) - 1); | 55 | mask = 1U << ((len * 8) - 1); |
55 | *dest = (*dest ^ mask) - mask; | 56 | *dest = (*dest ^ mask) - mask; |
56 | } | 57 | } |
@@ -65,40 +66,29 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, | |||
65 | unsigned long rt, len; | 66 | unsigned long rt, len; |
66 | bool is_write, sign_extend; | 67 | bool is_write, sign_extend; |
67 | 68 | ||
68 | if ((vcpu->arch.hsr >> 8) & 1) { | 69 | if (kvm_vcpu_dabt_isextabt(vcpu)) { |
69 | /* cache operation on I/O addr, tell guest unsupported */ | 70 | /* cache operation on I/O addr, tell guest unsupported */ |
70 | kvm_inject_dabt(vcpu, vcpu->arch.hxfar); | 71 | kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu)); |
71 | return 1; | 72 | return 1; |
72 | } | 73 | } |
73 | 74 | ||
74 | if ((vcpu->arch.hsr >> 7) & 1) { | 75 | if (kvm_vcpu_dabt_iss1tw(vcpu)) { |
75 | /* page table accesses IO mem: tell guest to fix its TTBR */ | 76 | /* page table accesses IO mem: tell guest to fix its TTBR */ |
76 | kvm_inject_dabt(vcpu, vcpu->arch.hxfar); | 77 | kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu)); |
77 | return 1; | 78 | return 1; |
78 | } | 79 | } |
79 | 80 | ||
80 | switch ((vcpu->arch.hsr >> 22) & 0x3) { | 81 | len = kvm_vcpu_dabt_get_as(vcpu); |
81 | case 0: | 82 | if (unlikely(len < 0)) |
82 | len = 1; | 83 | return len; |
83 | break; | ||
84 | case 1: | ||
85 | len = 2; | ||
86 | break; | ||
87 | case 2: | ||
88 | len = 4; | ||
89 | break; | ||
90 | default: | ||
91 | kvm_err("Hardware is weird: SAS 0b11 is reserved\n"); | ||
92 | return -EFAULT; | ||
93 | } | ||
94 | 84 | ||
95 | is_write = vcpu->arch.hsr & HSR_WNR; | 85 | is_write = kvm_vcpu_dabt_iswrite(vcpu); |
96 | sign_extend = vcpu->arch.hsr & HSR_SSE; | 86 | sign_extend = kvm_vcpu_dabt_issext(vcpu); |
97 | rt = (vcpu->arch.hsr & HSR_SRT_MASK) >> HSR_SRT_SHIFT; | 87 | rt = kvm_vcpu_dabt_get_rd(vcpu); |
98 | 88 | ||
99 | if (kvm_vcpu_reg_is_pc(vcpu, rt)) { | 89 | if (kvm_vcpu_reg_is_pc(vcpu, rt)) { |
100 | /* IO memory trying to read/write pc */ | 90 | /* IO memory trying to read/write pc */ |
101 | kvm_inject_pabt(vcpu, vcpu->arch.hxfar); | 91 | kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu)); |
102 | return 1; | 92 | return 1; |
103 | } | 93 | } |
104 | 94 | ||
@@ -112,7 +102,7 @@ static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, | |||
112 | * The MMIO instruction is emulated and should not be re-executed | 102 | * The MMIO instruction is emulated and should not be re-executed |
113 | * in the guest. | 103 | * in the guest. |
114 | */ | 104 | */ |
115 | kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1); | 105 | kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); |
116 | return 0; | 106 | return 0; |
117 | } | 107 | } |
118 | 108 | ||
@@ -130,7 +120,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, | |||
130 | * space do its magic. | 120 | * space do its magic. |
131 | */ | 121 | */ |
132 | 122 | ||
133 | if (vcpu->arch.hsr & HSR_ISV) { | 123 | if (kvm_vcpu_dabt_isvalid(vcpu)) { |
134 | ret = decode_hsr(vcpu, fault_ipa, &mmio); | 124 | ret = decode_hsr(vcpu, fault_ipa, &mmio); |
135 | if (ret) | 125 | if (ret) |
136 | return ret; | 126 | return ret; |