aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/kvm.h7
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h2
-rw-r--r--arch/powerpc/kvm/powerpc.c24
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 {
77struct kvm_guest_debug_arch { 77struct 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);
51extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, 51extern 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
54extern int kvmppc_emulate_instruction(struct kvm_run *run, 54extern 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,
278static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, 278static 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
306int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, 325int 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
326int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, 345int 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;