diff options
-rw-r--r-- | arch/powerpc/include/asm/kvm.h | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 24 |
3 files changed, 30 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index 81f3b0b5601e..19bae31202ce 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h | |||
@@ -77,4 +77,11 @@ struct kvm_debug_exit_arch { | |||
77 | struct kvm_guest_debug_arch { | 77 | struct kvm_guest_debug_arch { |
78 | }; | 78 | }; |
79 | 79 | ||
80 | #define KVM_REG_MASK 0x001f | ||
81 | #define KVM_REG_EXT_MASK 0xffe0 | ||
82 | #define KVM_REG_GPR 0x0000 | ||
83 | #define KVM_REG_FPR 0x0020 | ||
84 | #define KVM_REG_QPR 0x0040 | ||
85 | #define KVM_REG_FQPR 0x0060 | ||
86 | |||
80 | #endif /* __LINUX_KVM_POWERPC_H */ | 87 | #endif /* __LINUX_KVM_POWERPC_H */ |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index e2642829e435..c011170f572b 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -49,7 +49,7 @@ extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
49 | unsigned int rt, unsigned int bytes, | 49 | unsigned int rt, unsigned int bytes, |
50 | int is_bigendian); | 50 | int is_bigendian); |
51 | extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | 51 | extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, |
52 | u32 val, unsigned int bytes, int is_bigendian); | 52 | u64 val, unsigned int bytes, int is_bigendian); |
53 | 53 | ||
54 | extern int kvmppc_emulate_instruction(struct kvm_run *run, | 54 | extern int kvmppc_emulate_instruction(struct kvm_run *run, |
55 | struct kvm_vcpu *vcpu); | 55 | struct kvm_vcpu *vcpu); |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 297fcd2ff7d0..b7858b1e15ec 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -278,7 +278,7 @@ static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu, | |||
278 | static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, | 278 | static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, |
279 | struct kvm_run *run) | 279 | struct kvm_run *run) |
280 | { | 280 | { |
281 | ulong gpr; | 281 | u64 gpr; |
282 | 282 | ||
283 | if (run->mmio.len > sizeof(gpr)) { | 283 | if (run->mmio.len > sizeof(gpr)) { |
284 | printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len); | 284 | printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len); |
@@ -287,6 +287,7 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, | |||
287 | 287 | ||
288 | if (vcpu->arch.mmio_is_bigendian) { | 288 | if (vcpu->arch.mmio_is_bigendian) { |
289 | switch (run->mmio.len) { | 289 | switch (run->mmio.len) { |
290 | case 8: gpr = *(u64 *)run->mmio.data; break; | ||
290 | case 4: gpr = *(u32 *)run->mmio.data; break; | 291 | case 4: gpr = *(u32 *)run->mmio.data; break; |
291 | case 2: gpr = *(u16 *)run->mmio.data; break; | 292 | case 2: gpr = *(u16 *)run->mmio.data; break; |
292 | case 1: gpr = *(u8 *)run->mmio.data; break; | 293 | case 1: gpr = *(u8 *)run->mmio.data; break; |
@@ -301,6 +302,24 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, | |||
301 | } | 302 | } |
302 | 303 | ||
303 | kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr); | 304 | kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr); |
305 | |||
306 | switch (vcpu->arch.io_gpr & KVM_REG_EXT_MASK) { | ||
307 | case KVM_REG_GPR: | ||
308 | kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr); | ||
309 | break; | ||
310 | case KVM_REG_FPR: | ||
311 | vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr; | ||
312 | break; | ||
313 | case KVM_REG_QPR: | ||
314 | vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr; | ||
315 | break; | ||
316 | case KVM_REG_FQPR: | ||
317 | vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr; | ||
318 | vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr; | ||
319 | break; | ||
320 | default: | ||
321 | BUG(); | ||
322 | } | ||
304 | } | 323 | } |
305 | 324 | ||
306 | int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | 325 | int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, |
@@ -324,7 +343,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
324 | } | 343 | } |
325 | 344 | ||
326 | int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | 345 | int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, |
327 | u32 val, unsigned int bytes, int is_bigendian) | 346 | u64 val, unsigned int bytes, int is_bigendian) |
328 | { | 347 | { |
329 | void *data = run->mmio.data; | 348 | void *data = run->mmio.data; |
330 | 349 | ||
@@ -342,6 +361,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
342 | /* Store the value at the lowest bytes in 'data'. */ | 361 | /* Store the value at the lowest bytes in 'data'. */ |
343 | if (is_bigendian) { | 362 | if (is_bigendian) { |
344 | switch (bytes) { | 363 | switch (bytes) { |
364 | case 8: *(u64 *)data = val; break; | ||
345 | case 4: *(u32 *)data = val; break; | 365 | case 4: *(u32 *)data = val; break; |
346 | case 2: *(u16 *)data = val; break; | 366 | case 2: *(u16 *)data = val; break; |
347 | case 1: *(u8 *)data = val; break; | 367 | case 1: *(u8 *)data = val; break; |