KVM: PPC: Book3S: Get/set guest SPRs using the GET/SET_ONE_REG interface
Subsystems (4)
PATCH v5 1/3 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.
---
v5: Use get/set_reg_val rather than get/set_one_reg
Documentation/virtual/kvm/api.txt | 19 +++++++++ arch/powerpc/include/asm/kvm.h | 21 ++++++++++ arch/powerpc/include/asm/kvm_ppc.h | 32 +++++++++++++++ arch/powerpc/kvm/book3s.c | 68 ++++++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_hv.c | 76 ++++++++++++++++++++++++++++++------ arch/powerpc/kvm/book3s_pr.c | 23 ++++++----- 6 files changed, 215 insertions(+), 24 deletions(-)
Documentation/virtual/kvm/api.txt +19 -0
@@ -1740,6 +1740,25 @@ registers, find a list below: PPC | KVM_REG_PPC_IAC4 | 64 PPC | KVM_REG_PPC_DAC1 | 64 PPC | KVM_REG_PPC_DAC2 | 64 + PPC | KVM_REG_PPC_DABR | 64 + PPC | KVM_REG_PPC_DSCR | 64 + PPC | KVM_REG_PPC_PURR | 64 + PPC | KVM_REG_PPC_SPURR | 64 + PPC | KVM_REG_PPC_DAR | 64 + PPC | KVM_REG_PPC_DSISR | 32 + PPC | KVM_REG_PPC_AMR | 64 + PPC | KVM_REG_PPC_UAMOR | 64 + PPC | KVM_REG_PPC_MMCR0 | 64 + PPC | KVM_REG_PPC_MMCR1 | 64 + PPC | KVM_REG_PPC_MMCRA | 64 + PPC | KVM_REG_PPC_PMC1 | 32 + PPC | KVM_REG_PPC_PMC2 | 32 + PPC | KVM_REG_PPC_PMC3 | 32 + PPC | KVM_REG_PPC_PMC4 | 32 + PPC | KVM_REG_PPC_PMC5 | 32 + PPC | KVM_REG_PPC_PMC6 | 32 + PPC | KVM_REG_PPC_PMC7 | 32 + PPC | KVM_REG_PPC_PMC8 | 32 4.69 KVM_GET_ONE_REG
arch/powerpc/include/asm/kvm.h +21 -0
@@ -338,5 +338,26 @@ struct kvm_book3e_206_tlb_params {#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7) +#define KVM_REG_PPC_DABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8) +#define KVM_REG_PPC_DSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9) +#define KVM_REG_PPC_PURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa) +#define KVM_REG_PPC_SPURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb) +#define KVM_REG_PPC_DAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc) +#define KVM_REG_PPC_DSISR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd) +#define KVM_REG_PPC_AMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe) +#define KVM_REG_PPC_UAMOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf) + +#define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10) +#define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11) +#define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12) + +#define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18) +#define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19) +#define KVM_REG_PPC_PMC3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a) +#define KVM_REG_PPC_PMC4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b) +#define KVM_REG_PPC_PMC5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c) +#define KVM_REG_PPC_PMC6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d) +#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e) +#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)#endif /* __LINUX_KVM_POWERPC_H */
arch/powerpc/include/asm/kvm_ppc.h +32 -0
@@ -28,6 +28,7 @@#include <linux/types.h> #include <linux/kvm_types.h> #include <linux/kvm_host.h> +#include <linux/bug.h> #ifdef CONFIG_PPC_BOOK3S #include <asm/kvm_book3s.h> #else
@@ -196,6 +197,35 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)return r; } +union kvmppc_one_reg { +u32 wval; +u64 dval; +}; + +#define one_reg_size (id) \ + (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) + +#define get_reg_val (id, reg) ({ \ + union kvmppc_one_reg __u; \ + switch (one_reg_size(id)) { \ + case 4: __u.wval = (reg); break; \ + case 8: __u.dval = (reg); break; \ + default: BUG(); \ + } \ + __u; \ +}) + + +#define set_reg_val (id, val) ({ \ + u64 __v; \ + switch (one_reg_size(id)) { \ + case 4: __v = (val).wval; break; \ + case 8: __v = (val).dval; break; \ + default: BUG(); \ + } \ + __v; \ +}) +void kvmppc_core_get_sregs (struct kvm_vcpu *vcpu,struct kvm_sregs *sregs);int kvmppc_core_set_sregs (struct kvm_vcpu *vcpu,struct kvm_sregs *sregs);
@@ -204,6 +234,8 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);int kvm_vcpu_ioctl_get_one_reg (struct kvm_vcpu *vcpu,struct kvm_one_reg *reg);int kvm_vcpu_ioctl_set_one_reg (struct kvm_vcpu *vcpu,struct kvm_one_reg *reg); +int kvmppc_get_one_reg (struct kvm_vcpu *vcpu,u64 id,union kvmppc_one_reg *); +int kvmppc_set_one_reg (struct kvm_vcpu *vcpu,u64 id,union kvmppc_one_reg *);void kvmppc_set_pid (struct kvm_vcpu *vcpu,u32 pid);
arch/powerpc/kvm/book3s.c +68 -0
74 lines not on this page · raw message
arch/powerpc/kvm/book3s_hv.c +64 -12
100 lines not on this page · raw message
arch/powerpc/kvm/book3s_pr.c +11 -12
@@ -945,34 +945,33 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,return 0 ; } -int kvm_vcpu_ioctl_get_one_reg (struct kvm_vcpu *vcpu,struct kvm_one_reg *reg) +int kvmppc_get_one_reg (struct kvm_vcpu *vcpu,u64 id,union kvmppc_one_reg *val) { -int r = -EINVAL ; +int r =0 ; -switch (reg->id) { +switch (id) {case KVM_REG_PPC_HIOR : - r =copy_to_user ((u64 __user *)(long )reg->addr, - &to_book3s (vcpu)->hior,sizeof (u64)); + *val =get_reg_val (id,to_book3s (vcpu)->hior);break ;default : + r = -EINVAL ;break ; }return r; } -int kvm_vcpu_ioctl_set_one_reg (struct kvm_vcpu *vcpu,struct kvm_one_reg *reg) +int kvmppc_set_one_reg (struct kvm_vcpu *vcpu,u64 id,union kvmppc_one_reg *val) { -int r = -EINVAL ; +int r =0 ; -switch (reg->id) { +switch (id) {case KVM_REG_PPC_HIOR : - r =copy_from_user (&to_book3s (vcpu)->hior, - (u64 __user *)(long )reg->addr,sizeof (u64)); -if (!r) -to_book3s (vcpu)->hior_explicit = true; +to_book3s (vcpu)->hior =set_reg_val (id, *val); +to_book3s (vcpu)->hior_explicit = true;break ;default : + r = -EINVAL ;break ; }
Signature · 1 line
1.7.10.4
PATCH v5 2/3 KVM: PPC: Book3S: Get/set guest FP regs using the GET/SET_ONE_REG interface
This enables userspace to get and set all the guest floating-point state using the KVM_[GS]ET_ONE_REG ioctls. The floating-point state includes all of the traditional floating-point registers and the FPSCR (floating point status/control register), all the VMX/Altivec vector registers and the VSCR (vector status/control register), and on POWER7, the vector-scalar registers (note that each FP register is the high-order half of the corresponding VSR).
Most of these are implemented in common Book 3S code, except for VSX on POWER7. Because HV and PR differ in how they store the FP and VSX registers on POWER7, the code for these cases is not common. On POWER7, the FP registers are the upper halves of the VSX registers vsr0 - vsr31. PR KVM stores vsr0 - vsr31 in two halves, with the upper halves in the arch.fpr[] array and the lower halves in the arch.vsr[] array, whereas HV KVM on POWER7 stores the whole VSX register in arch.vsr[].
--- Documentation/virtual/kvm/api.txt | 11 +++++++++ arch/powerpc/include/asm/kvm.h | 20 +++++++++++++++ arch/powerpc/include/asm/kvm_ppc.h | 2 ++ arch/powerpc/kvm/book3s.c | 48 ++++++++++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_hv.c | 42 +++++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_pr.c | 24 ++++++++++++++++++ 6 files changed, 147 insertions(+)
Documentation/virtual/kvm/api.txt +11 -0
@@ -1759,6 +1759,17 @@ registers, find a list below: PPC | KVM_REG_PPC_PMC6 | 32 PPC | KVM_REG_PPC_PMC7 | 32 PPC | KVM_REG_PPC_PMC8 | 32 + PPC | KVM_REG_PPC_FPR0 | 64 + ... + PPC | KVM_REG_PPC_FPR31 | 64 + PPC | KVM_REG_PPC_VR0 | 128 + ... + PPC | KVM_REG_PPC_VR31 | 128 + PPC | KVM_REG_PPC_VSR0 | 128 + ... + PPC | KVM_REG_PPC_VSR31 | 128 + PPC | KVM_REG_PPC_FPSCR | 64 + PPC | KVM_REG_PPC_VSCR | 32 4.69 KVM_GET_ONE_REG
arch/powerpc/include/asm/kvm.h +20 -0
@@ -360,4 +360,24 @@ struct kvm_book3e_206_tlb_params {#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f) +/* 32 floating-point registers */ +#define KVM_REG_PPC_FPR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20) +#define KVM_REG_PPC_FPR (n) (KVM_REG_PPC_FPR0 + (n)) +#define KVM_REG_PPC_FPR31 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f) + +/* 32 VMX/Altivec vector registers */ +#define KVM_REG_PPC_VR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40) +#define KVM_REG_PPC_VR (n) (KVM_REG_PPC_VR0 + (n)) +#define KVM_REG_PPC_VR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f) + +/* 32 double-width FP registers for VSX */ +/* High-order halves overlap with FP regs */ +#define KVM_REG_PPC_VSR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60) +#define KVM_REG_PPC_VSR (n) (KVM_REG_PPC_VSR0 + (n)) +#define KVM_REG_PPC_VSR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f) + +/* FP and vector status/control registers */ +#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80) +#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81) +#endif /* __LINUX_KVM_POWERPC_H */
arch/powerpc/include/asm/kvm_ppc.h +2 -0
@@ -200,6 +200,8 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)union kvmppc_one_reg {u32 wval;u64 dval; +vector128 vval; +u64 vsxval[2 ]; };#define one_reg_size (id) \
arch/powerpc/kvm/book3s.c +48 -0
72 lines not on this page · raw message
arch/powerpc/kvm/book3s_hv.c +42 -0
54 lines not on this page · raw message
arch/powerpc/kvm/book3s_pr.c +24 -0
@@ -953,6 +953,18 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)case KVM_REG_PPC_HIOR : *val =get_reg_val (id,to_book3s (vcpu)->hior);break ; +#ifdef CONFIG_VSX + case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: { +long int i = reg->id -KVM_REG_PPC_VSR0 ; + +if (!cpu_has_feature (CPU_FTR_VSX )) { + r = -ENXIO ; +break ; + } + val->vsxval[0 ] = vcpu->arch.fpr[i]; + val->vsxval[1 ] = vcpu->arch.vsr[i]; +break ; +#endif /* CONFIG_VSX */ default : r = -EINVAL ;break ;
@@ -970,6 +982,18 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)to_book3s (vcpu)->hior =set_reg_val (id, *val);to_book3s (vcpu)->hior_explicit = true;break ; +#ifdef CONFIG_VSX + case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: { +long int i = reg->id -KVM_REG_PPC_VSR0 ; + +if (!cpu_has_feature (CPU_FTR_VSX )) { + r = -ENXIO ; +break ; + } + vcpu->arch.fpr[i] = val->vsxval[0 ]; + vcpu->arch.vsr[i] = val->vsxval[1 ]; +break ; +#endif /* CONFIG_VSX */ default : r = -EINVAL ;break ;
Signature · 1 line
1.7.10.4
PATCH v5 3/3 KVM: PPC: Book3S HV: Provide a way for userspace to get/set per-vCPU areas
In reply to Paul MackerrasThe PAPR paravirtualization interface lets guests register three different types of per-vCPU buffer areas in its memory for communication with the hypervisor. These are called virtual processor areas (VPAs). Currently the hypercalls to register and unregister VPAs are handled by KVM in the kernel, and userspace has no way to know about or save and restore these registrations across a migration.
This adds "register" codes for these three areas that userspace can use with the KVM_GET/SET_ONE_REG ioctls to see what addresses have been registered, and to register or unregister them. This will be needed for guest hibernation and migration, and is also needed so that userspace can unregister them on reset (otherwise we corrupt guest memory after reboot by writing to the VPAs registered by the previous kernel).
The "register" for the VPA is a 64-bit value containing the address, since the length of the VPA is fixed. The "registers" for the SLB shadow buffer and dispatch trace log (DTL) are 128 bits long, consisting of the guest physical address in the high (first) 64 bits and the length in the low 64 bits.
This also fixes a bug where we were calling init_vpa unconditionally, leading to an oops when unregistering the VPA.
--- Documentation/virtual/kvm/api.txt | 3 ++ arch/powerpc/include/asm/kvm.h | 6 ++++ arch/powerpc/include/asm/kvm_ppc.h | 4 +++ arch/powerpc/kvm/book3s_hv.c | 64 +++++++++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +3 -0
@@ -1770,6 +1770,9 @@ registers, find a list below: PPC | KVM_REG_PPC_VSR31 | 128 PPC | KVM_REG_PPC_FPSCR | 64 PPC | KVM_REG_PPC_VSCR | 32 + PPC | KVM_REG_PPC_VPA_ADDR | 64 + PPC | KVM_REG_PPC_VPA_SLB | 128 + PPC | KVM_REG_PPC_VPA_DTL | 128 4.69 KVM_GET_ONE_REG
arch/powerpc/include/asm/kvm.h +6 -0
@@ -380,4 +380,10 @@ struct kvm_book3e_206_tlb_params {#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81) +/* Virtual processor areas */ +/* For SLB & DTL, address in high (first) half, length in low half */ +#define KVM_REG_PPC_VPA_ADDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82) +#define KVM_REG_PPC_VPA_SLB (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83) +#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84) +#endif /* __LINUX_KVM_POWERPC_H */
arch/powerpc/include/asm/kvm_ppc.h +4 -0
@@ -202,6 +202,10 @@ union kvmppc_one_reg {u64 dval;vector128 vval;u64 vsxval[2 ]; +struct { +u64 addr; +u64 length; + } vpaval; };#define one_reg_size (id) \
arch/powerpc/kvm/book3s_hv.c +63 -1
94 lines not on this page · raw message
Signature · 1 line
1.7.10.4
Alexander Graf
AppliedQuoted 19 lines · Paul Mackerras
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
Quoted 8 lines
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.cand 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 <[email protected]>
Thanks, applied all 3 to kvm-ppc-next.
Alex