aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-09-25 16:31:56 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:54 -0400
commita136a8bdc02fc14625ac45ee846cc646fc46597e (patch)
tree7016d41b16ea11769f918526eca63a80b3014d71 /arch
parent5bd1cf118533aba41b3fbd4834e6362a9237db71 (diff)
KVM: PPC: Book3S: Get/set guest SPRs using the GET/SET_ONE_REG interface
This enables userspace to get and set various SPRs (special-purpose registers) using the KVM_[GS]ET_ONE_REG ioctls. With this, userspace can get and set all the SPRs that are part of the guest state, either through the KVM_[GS]ET_REGS ioctls, the KVM_[GS]ET_SREGS ioctls, or the KVM_[GS]ET_ONE_REG ioctls. The SPRs that are added here are: - DABR: Data address breakpoint register - DSCR: Data stream control register - PURR: Processor utilization of resources register - SPURR: Scaled PURR - DAR: Data address register - DSISR: Data storage interrupt status register - AMR: Authority mask register - UAMOR: User authority mask override register - MMCR0, MMCR1, MMCRA: Performance monitor unit control registers - PMC1..PMC8: Performance monitor unit counter registers In order to reduce code duplication between PR and HV KVM code, this moves the kvm_vcpu_ioctl_[gs]et_one_reg functions into book3s.c and centralizes the copying between user and kernel space there. The registers that are handled differently between PR and HV, and those that exist only in one flavor, are handled in kvmppc_[gs]et_one_reg() functions that are specific to each flavor. Signed-off-by: Paul Mackerras <paulus@samba.org> [agraf: minimal style fixes] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/kvm.h21
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h32
-rw-r--r--arch/powerpc/kvm/book3s.c68
-rw-r--r--arch/powerpc/kvm/book3s_hv.c76
-rw-r--r--arch/powerpc/kvm/book3s_pr.c23
5 files changed, 196 insertions, 24 deletions
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index 3c14202a3c84..9557576a5325 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -338,5 +338,26 @@ struct kvm_book3e_206_tlb_params {
338#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5) 338#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
339#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6) 339#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
340#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7) 340#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
341#define KVM_REG_PPC_DABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
342#define KVM_REG_PPC_DSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
343#define KVM_REG_PPC_PURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
344#define KVM_REG_PPC_SPURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
345#define KVM_REG_PPC_DAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
346#define KVM_REG_PPC_DSISR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
347#define KVM_REG_PPC_AMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
348#define KVM_REG_PPC_UAMOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
349
350#define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
351#define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
352#define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
353
354#define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
355#define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
356#define KVM_REG_PPC_PMC3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
357#define KVM_REG_PPC_PMC4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
358#define KVM_REG_PPC_PMC5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
359#define KVM_REG_PPC_PMC6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
360#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
361#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
341 362
342#endif /* __LINUX_KVM_POWERPC_H */ 363#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 3fb980d293e5..709f0ddae1f1 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -28,6 +28,7 @@
28#include <linux/types.h> 28#include <linux/types.h>
29#include <linux/kvm_types.h> 29#include <linux/kvm_types.h>
30#include <linux/kvm_host.h> 30#include <linux/kvm_host.h>
31#include <linux/bug.h>
31#ifdef CONFIG_PPC_BOOK3S 32#ifdef CONFIG_PPC_BOOK3S
32#include <asm/kvm_book3s.h> 33#include <asm/kvm_book3s.h>
33#else 34#else
@@ -196,6 +197,35 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)
196 return r; 197 return r;
197} 198}
198 199
200union kvmppc_one_reg {
201 u32 wval;
202 u64 dval;
203};
204
205#define one_reg_size(id) \
206 (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
207
208#define get_reg_val(id, reg) ({ \
209 union kvmppc_one_reg __u; \
210 switch (one_reg_size(id)) { \
211 case 4: __u.wval = (reg); break; \
212 case 8: __u.dval = (reg); break; \
213 default: BUG(); \
214 } \
215 __u; \
216})
217
218
219#define set_reg_val(id, val) ({ \
220 u64 __v; \
221 switch (one_reg_size(id)) { \
222 case 4: __v = (val).wval; break; \
223 case 8: __v = (val).dval; break; \
224 default: BUG(); \
225 } \
226 __v; \
227})
228
199void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); 229void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
200int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); 230int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
201 231
@@ -204,6 +234,8 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
204 234
205int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg); 235int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
206int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg); 236int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
237int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
238int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
207 239
208void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid); 240void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
209 241
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e94666566fa9..a5af28fc3a8f 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -485,6 +485,74 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
485 return -ENOTSUPP; 485 return -ENOTSUPP;
486} 486}
487 487
488int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
489{
490 int r;
491 union kvmppc_one_reg val;
492 int size;
493
494 size = one_reg_size(reg->id);
495 if (size > sizeof(val))
496 return -EINVAL;
497
498 r = kvmppc_get_one_reg(vcpu, reg->id, &val);
499
500 if (r == -EINVAL) {
501 r = 0;
502 switch (reg->id) {
503 case KVM_REG_PPC_DAR:
504 val = get_reg_val(reg->id, vcpu->arch.shared->dar);
505 break;
506 case KVM_REG_PPC_DSISR:
507 val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
508 break;
509 default:
510 r = -EINVAL;
511 break;
512 }
513 }
514 if (r)
515 return r;
516
517 if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
518 r = -EFAULT;
519
520 return r;
521}
522
523int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
524{
525 int r;
526 union kvmppc_one_reg val;
527 int size;
528
529 size = one_reg_size(reg->id);
530 if (size > sizeof(val))
531 return -EINVAL;
532
533 if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
534 return -EFAULT;
535
536 r = kvmppc_set_one_reg(vcpu, reg->id, &val);
537
538 if (r == -EINVAL) {
539 r = 0;
540 switch (reg->id) {
541 case KVM_REG_PPC_DAR:
542 vcpu->arch.shared->dar = set_reg_val(reg->id, val);
543 break;
544 case KVM_REG_PPC_DSISR:
545 vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
546 break;
547 default:
548 r = -EINVAL;
549 break;
550 }
551 }
552
553 return r;
554}
555
488int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, 556int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
489 struct kvm_translation *tr) 557 struct kvm_translation *tr)
490{ 558{
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c9ae3148c981..1cc6b77fa63d 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -544,36 +544,88 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
544 return 0; 544 return 0;
545} 545}
546 546
547int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 547int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
548{ 548{
549 int r = -EINVAL; 549 int r = 0;
550 long int i;
550 551
551 switch (reg->id) { 552 switch (id) {
552 case KVM_REG_PPC_HIOR: 553 case KVM_REG_PPC_HIOR:
553 r = put_user(0, (u64 __user *)reg->addr); 554 *val = get_reg_val(id, 0);
555 break;
556 case KVM_REG_PPC_DABR:
557 *val = get_reg_val(id, vcpu->arch.dabr);
558 break;
559 case KVM_REG_PPC_DSCR:
560 *val = get_reg_val(id, vcpu->arch.dscr);
561 break;
562 case KVM_REG_PPC_PURR:
563 *val = get_reg_val(id, vcpu->arch.purr);
564 break;
565 case KVM_REG_PPC_SPURR:
566 *val = get_reg_val(id, vcpu->arch.spurr);
567 break;
568 case KVM_REG_PPC_AMR:
569 *val = get_reg_val(id, vcpu->arch.amr);
570 break;
571 case KVM_REG_PPC_UAMOR:
572 *val = get_reg_val(id, vcpu->arch.uamor);
573 break;
574 case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
575 i = id - KVM_REG_PPC_MMCR0;
576 *val = get_reg_val(id, vcpu->arch.mmcr[i]);
577 break;
578 case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
579 i = id - KVM_REG_PPC_PMC1;
580 *val = get_reg_val(id, vcpu->arch.pmc[i]);
554 break; 581 break;
555 default: 582 default:
583 r = -EINVAL;
556 break; 584 break;
557 } 585 }
558 586
559 return r; 587 return r;
560} 588}
561 589
562int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 590int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
563{ 591{
564 int r = -EINVAL; 592 int r = 0;
593 long int i;
565 594
566 switch (reg->id) { 595 switch (id) {
567 case KVM_REG_PPC_HIOR: 596 case KVM_REG_PPC_HIOR:
568 {
569 u64 hior;
570 /* Only allow this to be set to zero */ 597 /* Only allow this to be set to zero */
571 r = get_user(hior, (u64 __user *)reg->addr); 598 if (set_reg_val(id, *val))
572 if (!r && (hior != 0))
573 r = -EINVAL; 599 r = -EINVAL;
574 break; 600 break;
575 } 601 case KVM_REG_PPC_DABR:
602 vcpu->arch.dabr = set_reg_val(id, *val);
603 break;
604 case KVM_REG_PPC_DSCR:
605 vcpu->arch.dscr = set_reg_val(id, *val);
606 break;
607 case KVM_REG_PPC_PURR:
608 vcpu->arch.purr = set_reg_val(id, *val);
609 break;
610 case KVM_REG_PPC_SPURR:
611 vcpu->arch.spurr = set_reg_val(id, *val);
612 break;
613 case KVM_REG_PPC_AMR:
614 vcpu->arch.amr = set_reg_val(id, *val);
615 break;
616 case KVM_REG_PPC_UAMOR:
617 vcpu->arch.uamor = set_reg_val(id, *val);
618 break;
619 case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
620 i = id - KVM_REG_PPC_MMCR0;
621 vcpu->arch.mmcr[i] = set_reg_val(id, *val);
622 break;
623 case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
624 i = id - KVM_REG_PPC_PMC1;
625 vcpu->arch.pmc[i] = set_reg_val(id, *val);
626 break;
576 default: 627 default:
628 r = -EINVAL;
577 break; 629 break;
578 } 630 }
579 631
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index bf3ec5d66d8c..c81109f3a376 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -945,34 +945,33 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
945 return 0; 945 return 0;
946} 946}
947 947
948int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 948int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
949{ 949{
950 int r = -EINVAL; 950 int r = 0;
951 951
952 switch (reg->id) { 952 switch (id) {
953 case KVM_REG_PPC_HIOR: 953 case KVM_REG_PPC_HIOR:
954 r = copy_to_user((u64 __user *)(long)reg->addr, 954 *val = get_reg_val(id, to_book3s(vcpu)->hior);
955 &to_book3s(vcpu)->hior, sizeof(u64));
956 break; 955 break;
957 default: 956 default:
957 r = -EINVAL;
958 break; 958 break;
959 } 959 }
960 960
961 return r; 961 return r;
962} 962}
963 963
964int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 964int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
965{ 965{
966 int r = -EINVAL; 966 int r = 0;
967 967
968 switch (reg->id) { 968 switch (id) {
969 case KVM_REG_PPC_HIOR: 969 case KVM_REG_PPC_HIOR:
970 r = copy_from_user(&to_book3s(vcpu)->hior, 970 to_book3s(vcpu)->hior = set_reg_val(id, *val);
971 (u64 __user *)(long)reg->addr, sizeof(u64)); 971 to_book3s(vcpu)->hior_explicit = true;
972 if (!r)
973 to_book3s(vcpu)->hior_explicit = true;
974 break; 972 break;
975 default: 973 default:
974 r = -EINVAL;
976 break; 975 break;
977 } 976 }
978 977