aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2014-01-08 05:25:29 -0500
committerAlexander Graf <agraf@suse.de>2014-01-27 10:01:15 -0500
commit8563bf52d509213e746295341ab52896b562ca5e (patch)
tree2f8914e14e13f46c773f979061a5bfc060def279
parent5d00f66b865e3782c5852cdafe1cea11a292a81e (diff)
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>
-rw-r--r--Documentation/virtual/kvm/api.txt1
-rw-r--r--arch/powerpc/include/asm/kvm_host.h1
-rw-r--r--arch/powerpc/include/asm/reg.h18
-rw-r--r--arch/powerpc/include/uapi/asm/kvm.h2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kvm/book3s_hv.c6
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S32
7 files changed, 52 insertions, 9 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index a30035dd4c26..5056baf574f4 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1838,6 +1838,7 @@ registers, find a list below:
1838 PPC | KVM_REG_PPC_LPCR | 64 1838 PPC | KVM_REG_PPC_LPCR | 64
1839 PPC | KVM_REG_PPC_PPR | 64 1839 PPC | KVM_REG_PPC_PPR | 64
1840 PPC | KVM_REG_PPC_ARCH_COMPAT 32 1840 PPC | KVM_REG_PPC_ARCH_COMPAT 32
1841 PPC | KVM_REG_PPC_DABRX | 32
1841 PPC | KVM_REG_PPC_TM_GPR0 | 64 1842 PPC | KVM_REG_PPC_TM_GPR0 | 64
1842 ... 1843 ...
1843 PPC | KVM_REG_PPC_TM_GPR31 | 64 1844 PPC | KVM_REG_PPC_TM_GPR31 | 64
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 81c92d1d7978..d161bc09153b 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -466,6 +466,7 @@ struct kvm_vcpu_arch {
466 ulong uamor; 466 ulong uamor;
467 ulong iamr; 467 ulong iamr;
468 u32 ctrl; 468 u32 ctrl;
469 u32 dabrx;
469 ulong dabr; 470 ulong dabr;
470 ulong dawr; 471 ulong dawr;
471 ulong dawrx; 472 ulong dawrx;
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 05ecb072540c..adf644a80a3e 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -229,16 +229,20 @@
229#define CIABR_PRIV_SUPER 2 229#define CIABR_PRIV_SUPER 2
230#define CIABR_PRIV_HYPER 3 230#define CIABR_PRIV_HYPER 3
231#define SPRN_DAWRX 0xBC 231#define SPRN_DAWRX 0xBC
232#define DAWRX_USER (1UL << 0) 232#define DAWRX_USER __MASK(0)
233#define DAWRX_KERNEL (1UL << 1) 233#define DAWRX_KERNEL __MASK(1)
234#define DAWRX_HYP (1UL << 2) 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#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ 239#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
236#define SPRN_DABR2 0x13D /* e300 */ 240#define SPRN_DABR2 0x13D /* e300 */
237#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */ 241#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */
238#define DABRX_USER (1UL << 0) 242#define DABRX_USER __MASK(0)
239#define DABRX_KERNEL (1UL << 1) 243#define DABRX_KERNEL __MASK(1)
240#define DABRX_HYP (1UL << 2) 244#define DABRX_HYP __MASK(2)
241#define DABRX_BTI (1UL << 3) 245#define DABRX_BTI __MASK(3)
242#define DABRX_ALL (DABRX_BTI | DABRX_HYP | DABRX_KERNEL | DABRX_USER) 246#define DABRX_ALL (DABRX_BTI | DABRX_HYP | DABRX_KERNEL | DABRX_USER)
243#define SPRN_DAR 0x013 /* Data Address Register */ 247#define SPRN_DAR 0x013 /* Data Address Register */
244#define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */ 248#define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index a586fb9b77bd..a6665be4f3ab 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -554,6 +554,8 @@ struct kvm_get_htab_header {
554/* Architecture compatibility level */ 554/* Architecture compatibility level */
555#define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7) 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/* Transactional Memory checkpointed state: 559/* Transactional Memory checkpointed state:
558 * This is all GPRs, all VSX regs and a subset of SPRs 560 * This is all GPRs, all VSX regs and a subset of SPRs
559 */ 561 */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 043900abbbb0..239a857f1141 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -493,6 +493,7 @@ int main(void)
493 DEFINE(VCPU_IAMR, offsetof(struct kvm_vcpu, arch.iamr)); 493 DEFINE(VCPU_IAMR, offsetof(struct kvm_vcpu, arch.iamr));
494 DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl)); 494 DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
495 DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr)); 495 DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
496 DEFINE(VCPU_DABRX, offsetof(struct kvm_vcpu, arch.dabrx));
496 DEFINE(VCPU_DAWR, offsetof(struct kvm_vcpu, arch.dawr)); 497 DEFINE(VCPU_DAWR, offsetof(struct kvm_vcpu, arch.dawr));
497 DEFINE(VCPU_DAWRX, offsetof(struct kvm_vcpu, arch.dawrx)); 498 DEFINE(VCPU_DAWRX, offsetof(struct kvm_vcpu, arch.dawrx));
498 DEFINE(VCPU_CIABR, offsetof(struct kvm_vcpu, arch.ciabr)); 499 DEFINE(VCPU_CIABR, offsetof(struct kvm_vcpu, arch.ciabr));
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 216049ff7368..eb4eed4a7173 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -812,6 +812,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
812 case KVM_REG_PPC_DABR: 812 case KVM_REG_PPC_DABR:
813 *val = get_reg_val(id, vcpu->arch.dabr); 813 *val = get_reg_val(id, vcpu->arch.dabr);
814 break; 814 break;
815 case KVM_REG_PPC_DABRX:
816 *val = get_reg_val(id, vcpu->arch.dabrx);
817 break;
815 case KVM_REG_PPC_DSCR: 818 case KVM_REG_PPC_DSCR:
816 *val = get_reg_val(id, vcpu->arch.dscr); 819 *val = get_reg_val(id, vcpu->arch.dscr);
817 break; 820 break;
@@ -967,6 +970,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
967 case KVM_REG_PPC_DABR: 970 case KVM_REG_PPC_DABR:
968 vcpu->arch.dabr = set_reg_val(id, *val); 971 vcpu->arch.dabr = set_reg_val(id, *val);
969 break; 972 break;
973 case KVM_REG_PPC_DABRX:
974 vcpu->arch.dabrx = set_reg_val(id, *val) & ~DABRX_HYP;
975 break;
970 case KVM_REG_PPC_DSCR: 976 case KVM_REG_PPC_DSCR:
971 vcpu->arch.dscr = set_reg_val(id, *val); 977 vcpu->arch.dscr = set_reg_val(id, *val);
972 break; 978 break;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index eae4ab9b9135..56299349e94b 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -585,7 +585,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
585BEGIN_FTR_SECTION 585BEGIN_FTR_SECTION
586 /* Set partition DABR */ 586 /* Set partition DABR */
587 /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ 587 /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */
588 li r5,3 588 lwz r5,VCPU_DABRX(r4)
589 ld r6,VCPU_DABR(r4) 589 ld r6,VCPU_DABR(r4)
590 mtspr SPRN_DABRX,r5 590 mtspr SPRN_DABRX,r5
591 mtspr SPRN_DABR,r6 591 mtspr SPRN_DABR,r6
@@ -1763,24 +1763,52 @@ hcall_real_table:
1763 .long 0 /* 0x11c */ 1763 .long 0 /* 0x11c */
1764 .long 0 /* 0x120 */ 1764 .long 0 /* 0x120 */
1765 .long .kvmppc_h_bulk_remove - hcall_real_table 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
1766hcall_real_table_end: 1770hcall_real_table_end:
1767 1771
1768ignore_hdec: 1772ignore_hdec:
1769 mr r4,r9 1773 mr r4,r9
1770 b fast_guest_return 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
17826: li r3, H_PARAMETER
1783 blr
1784
1772_GLOBAL(kvmppc_h_set_dabr) 1785_GLOBAL(kvmppc_h_set_dabr)
1786 li r5, DABRX_USER | DABRX_KERNEL
17873:
1773BEGIN_FTR_SECTION 1788BEGIN_FTR_SECTION
1774 b 2f 1789 b 2f
1775END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) 1790END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
1776 std r4,VCPU_DABR(r3) 1791 std r4,VCPU_DABR(r3)
1792 stw r5, VCPU_DABRX(r3)
1793 mtspr SPRN_DABRX, r5
1777 /* Work around P7 bug where DABR can get corrupted on mtspr */ 1794 /* Work around P7 bug where DABR can get corrupted on mtspr */
17781: mtspr SPRN_DABR,r4 17951: mtspr SPRN_DABR,r4
1779 mfspr r5, SPRN_DABR 1796 mfspr r5, SPRN_DABR
1780 cmpd r4, r5 1797 cmpd r4, r5
1781 bne 1b 1798 bne 1b
1782 isync 1799 isync
17832: 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 */
18042: 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 blr 1812 blr
1785 1813
1786_GLOBAL(kvmppc_h_cede) 1814_GLOBAL(kvmppc_h_cede)