powerpc/64s: Set reserved PCR bits
authorJordan Niethe <jniethe5@gmail.com>
Tue, 17 Sep 2019 00:46:05 +0000 (10:46 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 20 Sep 2019 22:36:53 +0000 (08:36 +1000)
Currently the reserved bits of the Processor Compatibility
Register (PCR) are cleared as per the Programming Note in Section
1.3.3 of version 3.0B of the Power ISA. This causes all new
architecture features to be made available when running on newer
processors with new architecture features added to the PCR as bits
must be set to disable a given feature.

For example to disable new features added as part of Version 2.07 of
the ISA the corresponding bit in the PCR needs to be set.

As new processor features generally require explicit kernel support
they should be disabled until such support is implemented. Therefore
kernels should set all unknown/reserved bits in the PCR such that any
new architecture features which the kernel does not currently know
about get disabled.

An update is planned to the ISA to clarify that the PCR is an
exception to the Programming Note on reserved bits in Section 1.3.3.

Signed-off-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
Tested-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190917004605.22471-2-alistair@popple.id.au
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/dt_cpu_ftrs.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_nested.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index 931939af95d19b637d5d5afc82e380f24e93d944..b3cbb1136bce0878148eb967dbd966755936dc76 100644 (file)
 #define   PCR_VEC_DIS  (__MASK(63-0))  /* Vec. disable (bit NA since POWER8) */
 #define   PCR_VSX_DIS  (__MASK(63-1))  /* VSX disable (bit NA since POWER8) */
 #define   PCR_TM_DIS   (__MASK(63-2))  /* Trans. memory disable (POWER8) */
+#define   PCR_HIGH_BITS        (PCR_VEC_DIS | PCR_VSX_DIS | PCR_TM_DIS)
 /*
  * These bits are used in the function kvmppc_set_arch_compat() to specify and
  * determine both the compatibility level which we want to emulate and the
 #define   PCR_ARCH_207 0x8             /* Architecture 2.07 */
 #define   PCR_ARCH_206 0x4             /* Architecture 2.06 */
 #define   PCR_ARCH_205 0x2             /* Architecture 2.05 */
+#define   PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205)
+#define   PCR_MASK     ~(PCR_HIGH_BITS | PCR_LOW_BITS) /* PCR Reserved Bits */
 #define        SPRN_HEIR       0x153   /* Hypervisor Emulated Instruction Register */
 #define SPRN_TLBINDEXR 0x154   /* P7 TLB control register */
 #define SPRN_TLBVPNR   0x155   /* P7 TLB control register */
index 3239a9fe6c1cf90c43033ece68c1e317053c735d..a460298c7ddb473b5a7978b64eb6e8a94701fc27 100644 (file)
@@ -23,6 +23,7 @@ _GLOBAL(__setup_cpu_power7)
        beqlr
        li      r0,0
        mtspr   SPRN_LPID,r0
+       LOAD_REG_IMMEDIATE(r0, PCR_MASK)
        mtspr   SPRN_PCR,r0
        mfspr   r3,SPRN_LPCR
        li      r4,(LPCR_LPES1 >> LPCR_LPES_SH)
@@ -37,6 +38,7 @@ _GLOBAL(__restore_cpu_power7)
        beqlr
        li      r0,0
        mtspr   SPRN_LPID,r0
+       LOAD_REG_IMMEDIATE(r0, PCR_MASK)
        mtspr   SPRN_PCR,r0
        mfspr   r3,SPRN_LPCR
        li      r4,(LPCR_LPES1 >> LPCR_LPES_SH)
@@ -54,6 +56,7 @@ _GLOBAL(__setup_cpu_power8)
        beqlr
        li      r0,0
        mtspr   SPRN_LPID,r0
+       LOAD_REG_IMMEDIATE(r0, PCR_MASK)
        mtspr   SPRN_PCR,r0
        mfspr   r3,SPRN_LPCR
        ori     r3, r3, LPCR_PECEDH
@@ -76,6 +79,7 @@ _GLOBAL(__restore_cpu_power8)
        beqlr
        li      r0,0
        mtspr   SPRN_LPID,r0
+       LOAD_REG_IMMEDIATE(r0, PCR_MASK)
        mtspr   SPRN_PCR,r0
        mfspr   r3,SPRN_LPCR
        ori     r3, r3, LPCR_PECEDH
@@ -98,6 +102,7 @@ _GLOBAL(__setup_cpu_power9)
        mtspr   SPRN_PSSCR,r0
        mtspr   SPRN_LPID,r0
        mtspr   SPRN_PID,r0
+       LOAD_REG_IMMEDIATE(r0, PCR_MASK)
        mtspr   SPRN_PCR,r0
        mfspr   r3,SPRN_LPCR
        LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE  | LPCR_HEIC)
@@ -123,6 +128,7 @@ _GLOBAL(__restore_cpu_power9)
        mtspr   SPRN_PSSCR,r0
        mtspr   SPRN_LPID,r0
        mtspr   SPRN_PID,r0
+       LOAD_REG_IMMEDIATE(r0, PCR_MASK)
        mtspr   SPRN_PCR,r0
        mfspr   r3,SPRN_LPCR
        LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
index bd95318d2202c114e649633d8b06a932617f289e..bceee2fde885805f2039bbf1d3d70b21d6ee2bbb 100644 (file)
@@ -101,7 +101,7 @@ static void __restore_cpu_cpufeatures(void)
        if (hv_mode) {
                mtspr(SPRN_LPID, 0);
                mtspr(SPRN_HFSCR, system_registers.hfscr);
-               mtspr(SPRN_PCR, 0);
+               mtspr(SPRN_PCR, PCR_MASK);
        }
        mtspr(SPRN_FSCR, system_registers.fscr);
 
@@ -144,6 +144,7 @@ static void __init cpufeatures_setup_cpu(void)
                mtspr(SPRN_HFSCR, 0);
        }
        mtspr(SPRN_FSCR, 0);
+       mtspr(SPRN_PCR, PCR_MASK);
 
        /*
         * LPCR does not get cleared, to match behaviour with secondaries
index efd8f93bc9dc1272686055f94d1cdbcee8f61d65..709cf1fd4cf466773da3a0021cf03777e4a58ef6 100644 (file)
@@ -401,8 +401,11 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
 
        spin_lock(&vc->lock);
        vc->arch_compat = arch_compat;
-       /* Set all PCR bits for which guest_pcr_bit <= bit < host_pcr_bit */
-       vc->pcr = host_pcr_bit - guest_pcr_bit;
+       /*
+        * Set all PCR bits for which guest_pcr_bit <= bit < host_pcr_bit
+        * Also set all reserved PCR bits
+        */
+       vc->pcr = (host_pcr_bit - guest_pcr_bit) | PCR_MASK;
        spin_unlock(&vc->lock);
 
        return 0;
@@ -3410,7 +3413,7 @@ static int kvmhv_load_hv_regs_and_go(struct kvm_vcpu *vcpu, u64 time_limit,
        }
 
        if (vc->pcr)
-               mtspr(SPRN_PCR, vc->pcr);
+               mtspr(SPRN_PCR, vc->pcr | PCR_MASK);
        mtspr(SPRN_DPDES, vc->dpdes);
        mtspr(SPRN_VTB, vc->vtb);
 
@@ -3490,7 +3493,7 @@ static int kvmhv_load_hv_regs_and_go(struct kvm_vcpu *vcpu, u64 time_limit,
        vc->vtb = mfspr(SPRN_VTB);
        mtspr(SPRN_DPDES, 0);
        if (vc->pcr)
-               mtspr(SPRN_PCR, 0);
+               mtspr(SPRN_PCR, PCR_MASK);
 
        if (vc->tb_offset_applied) {
                u64 new_tb = mftb() - vc->tb_offset_applied;
index fff90f2c3de2100f67c627f0dfbc39192d501f5d..cdf30c6eaf54268d7258490f8a76d951ad7aa9fe 100644 (file)
@@ -29,7 +29,7 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
-       hr->pcr = vc->pcr;
+       hr->pcr = vc->pcr | PCR_MASK;
        hr->dpdes = vc->dpdes;
        hr->hfscr = vcpu->arch.hfscr;
        hr->tb_offset = vc->tb_offset;
@@ -65,7 +65,7 @@ static void byteswap_hv_regs(struct hv_guest_state *hr)
        hr->lpid = swab32(hr->lpid);
        hr->vcpu_token = swab32(hr->vcpu_token);
        hr->lpcr = swab64(hr->lpcr);
-       hr->pcr = swab64(hr->pcr);
+       hr->pcr = swab64(hr->pcr) | PCR_MASK;
        hr->amor = swab64(hr->amor);
        hr->dpdes = swab64(hr->dpdes);
        hr->hfscr = swab64(hr->hfscr);
@@ -148,7 +148,7 @@ static void restore_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
-       vc->pcr = hr->pcr;
+       vc->pcr = hr->pcr | PCR_MASK;
        vc->dpdes = hr->dpdes;
        vcpu->arch.hfscr = hr->hfscr;
        vcpu->arch.dawr = hr->dawr0;
index 9a05b0d932efa53045444b02c8372573feabcb46..74a9cfe84aeedfb945628aa31ec0bae0348e7eec 100644 (file)
@@ -644,8 +644,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
 
        /* Load guest PCR value to select appropriate compat mode */
 37:    ld      r7, VCORE_PCR(r5)
-       cmpdi   r7, 0
+       LOAD_REG_IMMEDIATE(r6, PCR_MASK)
+       cmpld   r7, r6
        beq     38f
+       or      r7, r7, r6
        mtspr   SPRN_PCR, r7
 38:
 
@@ -1913,10 +1915,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 
        /* Reset PCR */
        ld      r0, VCORE_PCR(r5)
-       cmpdi   r0, 0
+       LOAD_REG_IMMEDIATE(r6, PCR_MASK)
+       cmpld   r0, r6
        beq     18f
-       li      r0, 0
-       mtspr   SPRN_PCR, r0
+       mtspr   SPRN_PCR, r6
 18:
        /* Signal secondary CPUs to continue */
        stb     r0,VCORE_IN_GUEST(r5)