]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: PPC: Book3S: Treat VTB as a per-subcore register, not per-thread
authorPaul Mackerras <paulus@ozlabs.org>
Thu, 15 Sep 2016 03:42:52 +0000 (13:42 +1000)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 23 Feb 2017 03:54:04 +0000 (03:54 +0000)
commit 88b02cf97bb7e742db3e31671d54177e3e19fd89 upstream.

POWER8 has one virtual timebase (VTB) register per subcore, not one
per CPU thread.  The HV KVM code currently treats VTB as a per-thread
register, which can lead to spurious soft lockup messages from guests
which use the VTB as the time source for the soft lockup detector.
(CPUs before POWER8 did not have the VTB register.)

For HV KVM, this fixes the problem by making only the primary thread
in each virtual core save and restore the VTB value.  With this,
the VTB state becomes part of the kvmppc_vcore structure.  This
also means that "piggybacking" of multiple virtual cores onto one
subcore is not possible on POWER8, because then the virtual cores
would share a single VTB register.

PR KVM emulates a VTB register, which is per-vcpu because PR KVM
has no notion of CPU threads or SMT.  For PR KVM we move the VTB
state into the kvmppc_vcpu_book3s struct.

Reported-by: Thomas Huth <thuth@redhat.com>
Tested-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
[bwh: Backported to 3.16:
 - Adjust filenames, context
 - Drop changes to kvmppc_core_emulate_mfspr_pr(), can_piggyback_subcore(),
   kvmppc_copy_from_svcpu()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr.c

index f52f65694527ea7b42ceb1df485039fc9abba623..0689091f95055b7ec0dd5615240b9260be4beb45 100644 (file)
@@ -83,6 +83,7 @@ struct kvmppc_vcpu_book3s {
        u64 sdr1;
        u64 hior;
        u64 msr_mask;
+       u64 vtb;
        u64 purr_offset;
        u64 spurr_offset;
 #ifdef CONFIG_PPC_BOOK3S_32
index bb66d8b8efdf073fb2a54c39b9d1dd984be713cd..2149dbcf893128e052da3f6ef3478fc5694d7476 100644 (file)
@@ -305,6 +305,7 @@ struct kvmppc_vcore {
        u32 arch_compat;
        ulong pcr;
        ulong dpdes;            /* doorbell state (POWER8) */
+       ulong vtb;              /* virtual timebase */
 };
 
 #define VCORE_ENTRY_COUNT(vc)  ((vc)->entry_exit_count & 0xff)
@@ -462,7 +463,6 @@ struct kvm_vcpu_arch {
        ulong purr;
        ulong spurr;
        ulong ic;
-       ulong vtb;
        ulong dscr;
        ulong amr;
        ulong uamor;
index f5995a912213f7cf9ecc9c1a2c083bfa7697f3f4..88abea8898765bf4c9414378f31c1f51593ca08a 100644 (file)
@@ -506,7 +506,6 @@ int main(void)
        DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
        DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
        DEFINE(VCPU_IC, offsetof(struct kvm_vcpu, arch.ic));
-       DEFINE(VCPU_VTB, offsetof(struct kvm_vcpu, arch.vtb));
        DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
        DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr));
        DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
@@ -560,6 +559,7 @@ int main(void)
        DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr));
        DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr));
        DEFINE(VCORE_DPDES, offsetof(struct kvmppc_vcore, dpdes));
+       DEFINE(VCORE_VTB, offsetof(struct kvmppc_vcore, vtb));
        DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
        DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
        DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
index 89d4ebd8152b4b0609492f6ba229847bfb6cf3a2..a416b6bb0d6a2f89cbfc186e4127a54926b15c09 100644 (file)
@@ -909,7 +909,7 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
                *val = get_reg_val(id, vcpu->arch.ic);
                break;
        case KVM_REG_PPC_VTB:
-               *val = get_reg_val(id, vcpu->arch.vtb);
+               *val = get_reg_val(id, vcpu->arch.vcore->vtb);
                break;
        case KVM_REG_PPC_CSIGR:
                *val = get_reg_val(id, vcpu->arch.csigr);
@@ -1110,7 +1110,7 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
                vcpu->arch.ic = set_reg_val(id, *val);
                break;
        case KVM_REG_PPC_VTB:
-               vcpu->arch.vtb = set_reg_val(id, *val);
+               vcpu->arch.vcore->vtb = set_reg_val(id, *val);
                break;
        case KVM_REG_PPC_CSIGR:
                vcpu->arch.csigr = set_reg_val(id, *val);
index 2f0c1394efa8deb810009bdb661d2f7e0324e43f..ab69a5f242d1c07581f7e7e66fc4faa848e1f95d 100644 (file)
@@ -457,9 +457,11 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_207S)
 38:
 
 BEGIN_FTR_SECTION
-       /* DPDES is shared between threads */
+       /* DPDES and VTB are shared between threads */
        ld      r8, VCORE_DPDES(r5)
+       ld      r7, VCORE_VTB(r5)
        mtspr   SPRN_DPDES, r8
+       mtspr   SPRN_VTB, r7
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 
        li      r0,1
@@ -736,10 +738,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
        mtspr   SPRN_CIABR, r7
        mtspr   SPRN_TAR, r8
        ld      r5, VCPU_IC(r4)
-       ld      r6, VCPU_VTB(r4)
-       mtspr   SPRN_IC, r5
-       mtspr   SPRN_VTB, r6
        ld      r8, VCPU_EBBHR(r4)
+       mtspr   SPRN_IC, r5
        mtspr   SPRN_EBBHR, r8
        ld      r5, VCPU_EBBRR(r4)
        ld      r6, VCPU_BESCR(r4)
@@ -1147,10 +1147,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
        stw     r6, VCPU_PSPB(r9)
        std     r7, VCPU_FSCR(r9)
        mfspr   r5, SPRN_IC
-       mfspr   r6, SPRN_VTB
        mfspr   r7, SPRN_TAR
        std     r5, VCPU_IC(r9)
-       std     r6, VCPU_VTB(r9)
        std     r7, VCPU_TAR(r9)
        mfspr   r8, SPRN_EBBHR
        std     r8, VCPU_EBBHR(r9)
@@ -1442,9 +1440,11 @@ secondary_too_late:
        isync
 
 BEGIN_FTR_SECTION
-       /* DPDES is shared between threads */
+       /* DPDES and VTB are shared between threads */
        mfspr   r7, SPRN_DPDES
+       mfspr   r8, SPRN_VTB
        std     r7, VCORE_DPDES(r5)
+       std     r8, VCORE_VTB(r5)
        /* clear DPDES so we don't get guest doorbells in the host */
        li      r8, 0
        mtspr   SPRN_DPDES, r8
index 66b7afec250fa5a0abeb18ea9266eb78ae99229f..e587264c2e8cef19c49fc16eacb2d5d7da42c04f 100644 (file)
@@ -1232,6 +1232,9 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_HIOR:
                *val = get_reg_val(id, to_book3s(vcpu)->hior);
                break;
+       case KVM_REG_PPC_VTB:
+               *val = get_reg_val(id, to_book3s(vcpu)->vtb);
+               break;
        case KVM_REG_PPC_LPCR:
        case KVM_REG_PPC_LPCR_64:
                /*
@@ -1268,6 +1271,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
                to_book3s(vcpu)->hior = set_reg_val(id, *val);
                to_book3s(vcpu)->hior_explicit = true;
                break;
+       case KVM_REG_PPC_VTB:
+               to_book3s(vcpu)->vtb = set_reg_val(id, *val);
+               break;
        case KVM_REG_PPC_LPCR:
        case KVM_REG_PPC_LPCR_64:
                kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));