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

KVM: PPC: Book3S HV: Add support for DABRX register on POWER7

The DABRX (DABR extension) register on POWER7 processors provides finer
control over which accesses cause a data breakpoint interrupt. It
contains 3 bits which indicate whether to enable accesses in user,
kernel and hypervisor modes respectively to cause data breakpoint
interrupts, plus one bit that enables both real mode and virtual mode
accesses to cause interrupts. Currently, KVM sets DABRX to allow
both kernel and user accesses to cause interrupts while in the guest.

This adds support for the guest to specify other values for DABRX.
PAPR defines a H_SET_XDABR hcall to allow the guest to set both DABR
and DABRX with one call. This adds a real-mode implementation of
H_SET_XDABR, which shares most of its code with the existing H_SET_DABR
implementation. To support this, we add a per-vcpu field to store the
DABRX value plus code to get and set it via the ONE_REG interface.

For Linux guests to use this new hcall, userspace needs to add
"hcall-xdabr" to the set of strings in the /chosen/hypertas-functions
property in the device tree. If userspace does this and then migrates
the guest to a host where the kernel doesn't include this patch, then
userspace will need to implement H_SET_XDABR by writing the specified
DABR value to the DABR using the ONE_REG interface. In that case, the
old kernel will set DABRX to DABRX_USER | DABRX_KERNEL. That should
still work correctly, at least for Linux guests, since Linux guests
cope with getting data breakpoint interrupts in modes that weren't
requested by just ignoring the interrupt, and Linux guests never set
DABRX_BTI.

The other thing this does is to make H_SET_DABR and H_SET_XDABR work
on POWER8, which has the DAWR and DAWRX instead of DABR/X. Guests that
know about POWER8 should use H_SET_MODE rather than H_SET_[X]DABR, but
guests running in POWER7 compatibility mode will still use H_SET_[X]DABR.
For them, this adds the logic to convert DABR/X values into DAWR/X values
on POWER8.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>

authored by

Paul Mackerras and committed by
Alexander Graf
8563bf52 5d00f66b

+52 -9
+1
Documentation/virtual/kvm/api.txt
··· 1838 1838 PPC | KVM_REG_PPC_LPCR | 64 1839 1839 PPC | KVM_REG_PPC_PPR | 64 1840 1840 PPC | KVM_REG_PPC_ARCH_COMPAT 32 1841 + PPC | KVM_REG_PPC_DABRX | 32 1841 1842 PPC | KVM_REG_PPC_TM_GPR0 | 64 1842 1843 ... 1843 1844 PPC | KVM_REG_PPC_TM_GPR31 | 64
+1
arch/powerpc/include/asm/kvm_host.h
··· 466 466 ulong uamor; 467 467 ulong iamr; 468 468 u32 ctrl; 469 + u32 dabrx; 469 470 ulong dabr; 470 471 ulong dawr; 471 472 ulong dawrx;
+11 -7
arch/powerpc/include/asm/reg.h
··· 229 229 #define CIABR_PRIV_SUPER 2 230 230 #define CIABR_PRIV_HYPER 3 231 231 #define SPRN_DAWRX 0xBC 232 - #define DAWRX_USER (1UL << 0) 233 - #define DAWRX_KERNEL (1UL << 1) 234 - #define DAWRX_HYP (1UL << 2) 232 + #define DAWRX_USER __MASK(0) 233 + #define DAWRX_KERNEL __MASK(1) 234 + #define DAWRX_HYP __MASK(2) 235 + #define DAWRX_WTI __MASK(3) 236 + #define DAWRX_WT __MASK(4) 237 + #define DAWRX_DR __MASK(5) 238 + #define DAWRX_DW __MASK(6) 235 239 #define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ 236 240 #define SPRN_DABR2 0x13D /* e300 */ 237 241 #define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */ 238 - #define DABRX_USER (1UL << 0) 239 - #define DABRX_KERNEL (1UL << 1) 240 - #define DABRX_HYP (1UL << 2) 241 - #define DABRX_BTI (1UL << 3) 242 + #define DABRX_USER __MASK(0) 243 + #define DABRX_KERNEL __MASK(1) 244 + #define DABRX_HYP __MASK(2) 245 + #define DABRX_BTI __MASK(3) 242 246 #define DABRX_ALL (DABRX_BTI | DABRX_HYP | DABRX_KERNEL | DABRX_USER) 243 247 #define SPRN_DAR 0x013 /* Data Address Register */ 244 248 #define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */
+2
arch/powerpc/include/uapi/asm/kvm.h
··· 554 554 /* Architecture compatibility level */ 555 555 #define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7) 556 556 557 + #define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8) 558 + 557 559 /* Transactional Memory checkpointed state: 558 560 * This is all GPRs, all VSX regs and a subset of SPRs 559 561 */
+1
arch/powerpc/kernel/asm-offsets.c
··· 493 493 DEFINE(VCPU_IAMR, offsetof(struct kvm_vcpu, arch.iamr)); 494 494 DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl)); 495 495 DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr)); 496 + DEFINE(VCPU_DABRX, offsetof(struct kvm_vcpu, arch.dabrx)); 496 497 DEFINE(VCPU_DAWR, offsetof(struct kvm_vcpu, arch.dawr)); 497 498 DEFINE(VCPU_DAWRX, offsetof(struct kvm_vcpu, arch.dawrx)); 498 499 DEFINE(VCPU_CIABR, offsetof(struct kvm_vcpu, arch.ciabr));
+6
arch/powerpc/kvm/book3s_hv.c
··· 812 812 case KVM_REG_PPC_DABR: 813 813 *val = get_reg_val(id, vcpu->arch.dabr); 814 814 break; 815 + case KVM_REG_PPC_DABRX: 816 + *val = get_reg_val(id, vcpu->arch.dabrx); 817 + break; 815 818 case KVM_REG_PPC_DSCR: 816 819 *val = get_reg_val(id, vcpu->arch.dscr); 817 820 break; ··· 969 966 break; 970 967 case KVM_REG_PPC_DABR: 971 968 vcpu->arch.dabr = set_reg_val(id, *val); 969 + break; 970 + case KVM_REG_PPC_DABRX: 971 + vcpu->arch.dabrx = set_reg_val(id, *val) & ~DABRX_HYP; 972 972 break; 973 973 case KVM_REG_PPC_DSCR: 974 974 vcpu->arch.dscr = set_reg_val(id, *val);
+30 -2
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 585 585 BEGIN_FTR_SECTION 586 586 /* Set partition DABR */ 587 587 /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ 588 - li r5,3 588 + lwz r5,VCPU_DABRX(r4) 589 589 ld r6,VCPU_DABR(r4) 590 590 mtspr SPRN_DABRX,r5 591 591 mtspr SPRN_DABR,r6 ··· 1763 1763 .long 0 /* 0x11c */ 1764 1764 .long 0 /* 0x120 */ 1765 1765 .long .kvmppc_h_bulk_remove - hcall_real_table 1766 + .long 0 /* 0x128 */ 1767 + .long 0 /* 0x12c */ 1768 + .long 0 /* 0x130 */ 1769 + .long .kvmppc_h_set_xdabr - hcall_real_table 1766 1770 hcall_real_table_end: 1767 1771 1768 1772 ignore_hdec: 1769 1773 mr r4,r9 1770 1774 b fast_guest_return 1771 1775 1776 + _GLOBAL(kvmppc_h_set_xdabr) 1777 + andi. r0, r5, DABRX_USER | DABRX_KERNEL 1778 + beq 6f 1779 + li r0, DABRX_USER | DABRX_KERNEL | DABRX_BTI 1780 + andc. r0, r5, r0 1781 + beq 3f 1782 + 6: li r3, H_PARAMETER 1783 + blr 1784 + 1772 1785 _GLOBAL(kvmppc_h_set_dabr) 1786 + li r5, DABRX_USER | DABRX_KERNEL 1787 + 3: 1773 1788 BEGIN_FTR_SECTION 1774 1789 b 2f 1775 1790 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) 1776 1791 std r4,VCPU_DABR(r3) 1792 + stw r5, VCPU_DABRX(r3) 1793 + mtspr SPRN_DABRX, r5 1777 1794 /* Work around P7 bug where DABR can get corrupted on mtspr */ 1778 1795 1: mtspr SPRN_DABR,r4 1779 1796 mfspr r5, SPRN_DABR 1780 1797 cmpd r4, r5 1781 1798 bne 1b 1782 1799 isync 1783 - 2: li r3,0 1800 + li r3,0 1801 + blr 1802 + 1803 + /* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */ 1804 + 2: rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW 1805 + rlwimi r5, r4, 1, DAWRX_WT 1806 + clrrdi r4, r4, 3 1807 + std r4, VCPU_DAWR(r3) 1808 + std r5, VCPU_DAWRX(r3) 1809 + mtspr SPRN_DAWR, r4 1810 + mtspr SPRN_DAWRX, r5 1811 + li r3, 0 1784 1812 blr 1785 1813 1786 1814 _GLOBAL(kvmppc_h_cede)