Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Paul Mackerras and committed by
Alexander Graf
a136a8bd 5bd1cf11

+215 -24
+19
Documentation/virtual/kvm/api.txt
··· 1740 1740 PPC | KVM_REG_PPC_IAC4 | 64 1741 1741 PPC | KVM_REG_PPC_DAC1 | 64 1742 1742 PPC | KVM_REG_PPC_DAC2 | 64 1743 + PPC | KVM_REG_PPC_DABR | 64 1744 + PPC | KVM_REG_PPC_DSCR | 64 1745 + PPC | KVM_REG_PPC_PURR | 64 1746 + PPC | KVM_REG_PPC_SPURR | 64 1747 + PPC | KVM_REG_PPC_DAR | 64 1748 + PPC | KVM_REG_PPC_DSISR | 32 1749 + PPC | KVM_REG_PPC_AMR | 64 1750 + PPC | KVM_REG_PPC_UAMOR | 64 1751 + PPC | KVM_REG_PPC_MMCR0 | 64 1752 + PPC | KVM_REG_PPC_MMCR1 | 64 1753 + PPC | KVM_REG_PPC_MMCRA | 64 1754 + PPC | KVM_REG_PPC_PMC1 | 32 1755 + PPC | KVM_REG_PPC_PMC2 | 32 1756 + PPC | KVM_REG_PPC_PMC3 | 32 1757 + PPC | KVM_REG_PPC_PMC4 | 32 1758 + PPC | KVM_REG_PPC_PMC5 | 32 1759 + PPC | KVM_REG_PPC_PMC6 | 32 1760 + PPC | KVM_REG_PPC_PMC7 | 32 1761 + PPC | KVM_REG_PPC_PMC8 | 32 1743 1762 1744 1763 4.69 KVM_GET_ONE_REG 1745 1764
+21
arch/powerpc/include/asm/kvm.h
··· 338 338 #define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5) 339 339 #define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6) 340 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 363 #endif /* __LINUX_KVM_POWERPC_H */
+32
arch/powerpc/include/asm/kvm_ppc.h
··· 28 28 #include <linux/types.h> 29 29 #include <linux/kvm_types.h> 30 30 #include <linux/kvm_host.h> 31 + #include <linux/bug.h> 31 32 #ifdef CONFIG_PPC_BOOK3S 32 33 #include <asm/kvm_book3s.h> 33 34 #else ··· 197 196 return r; 198 197 } 199 198 199 + union kvmppc_one_reg { 200 + u32 wval; 201 + u64 dval; 202 + }; 203 + 204 + #define one_reg_size(id) \ 205 + (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) 206 + 207 + #define get_reg_val(id, reg) ({ \ 208 + union kvmppc_one_reg __u; \ 209 + switch (one_reg_size(id)) { \ 210 + case 4: __u.wval = (reg); break; \ 211 + case 8: __u.dval = (reg); break; \ 212 + default: BUG(); \ 213 + } \ 214 + __u; \ 215 + }) 216 + 217 + 218 + #define set_reg_val(id, val) ({ \ 219 + u64 __v; \ 220 + switch (one_reg_size(id)) { \ 221 + case 4: __v = (val).wval; break; \ 222 + case 8: __v = (val).dval; break; \ 223 + default: BUG(); \ 224 + } \ 225 + __v; \ 226 + }) 227 + 200 228 void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); 201 229 int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); 202 230 ··· 234 204 235 205 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg); 236 206 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg); 207 + int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *); 208 + int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *); 237 209 238 210 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid); 239 211
+68
arch/powerpc/kvm/book3s.c
··· 485 485 return -ENOTSUPP; 486 486 } 487 487 488 + int 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 + 523 + int 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 + 488 556 int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, 489 557 struct kvm_translation *tr) 490 558 {
+64 -12
arch/powerpc/kvm/book3s_hv.c
··· 544 544 return 0; 545 545 } 546 546 547 - int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 547 + int 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 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 581 break; 555 582 default: 583 + r = -EINVAL; 556 584 break; 557 585 } 558 586 559 587 return r; 560 588 } 561 589 562 - int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 590 + int 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 596 case KVM_REG_PPC_HIOR: 568 - { 569 - u64 hior; 570 597 /* Only allow this to be set to zero */ 571 - r = get_user(hior, (u64 __user *)reg->addr); 572 - if (!r && (hior != 0)) 598 + if (set_reg_val(id, *val)) 573 599 r = -EINVAL; 574 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 627 default: 628 + r = -EINVAL; 577 629 break; 578 630 } 579 631
+11 -12
arch/powerpc/kvm/book3s_pr.c
··· 945 945 return 0; 946 946 } 947 947 948 - int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 948 + int 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 953 case KVM_REG_PPC_HIOR: 954 - r = copy_to_user((u64 __user *)(long)reg->addr, 955 - &to_book3s(vcpu)->hior, sizeof(u64)); 954 + *val = get_reg_val(id, to_book3s(vcpu)->hior); 956 955 break; 957 956 default: 957 + r = -EINVAL; 958 958 break; 959 959 } 960 960 961 961 return r; 962 962 } 963 963 964 - int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) 964 + int 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 969 case KVM_REG_PPC_HIOR: 970 - r = copy_from_user(&to_book3s(vcpu)->hior, 971 - (u64 __user *)(long)reg->addr, sizeof(u64)); 972 - if (!r) 973 - to_book3s(vcpu)->hior_explicit = true; 970 + to_book3s(vcpu)->hior = set_reg_val(id, *val); 971 + to_book3s(vcpu)->hior_explicit = true; 974 972 break; 975 973 default: 974 + r = -EINVAL; 976 975 break; 977 976 } 978 977