Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2020, Jordan Niethe, IBM Corporation.
0004  *
0005  * This file contains low level CPU setup functions.
0006  * Originally written in assembly by Benjamin Herrenschmidt & various other
0007  * authors.
0008  */
0009 
0010 #include <asm/reg.h>
0011 #include <asm/synch.h>
0012 #include <linux/bitops.h>
0013 #include <asm/cputable.h>
0014 #include <asm/cpu_setup_power.h>
0015 
0016 /* Disable CPU_FTR_HVMODE and return false if MSR:HV is not set */
0017 static bool init_hvmode_206(struct cpu_spec *t)
0018 {
0019     u64 msr;
0020 
0021     msr = mfmsr();
0022     if (msr & MSR_HV)
0023         return true;
0024 
0025     t->cpu_features &= ~(CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST);
0026     return false;
0027 }
0028 
0029 static void init_LPCR_ISA300(u64 lpcr, u64 lpes)
0030 {
0031     /* POWER9 has no VRMASD */
0032     lpcr |= (lpes << LPCR_LPES_SH) & LPCR_LPES;
0033     lpcr |= LPCR_PECE0|LPCR_PECE1|LPCR_PECE2;
0034     lpcr |= (4ull << LPCR_DPFD_SH) & LPCR_DPFD;
0035     lpcr &= ~LPCR_HDICE;    /* clear HDICE */
0036     lpcr |= (4ull << LPCR_VC_SH);
0037     mtspr(SPRN_LPCR, lpcr);
0038     isync();
0039 }
0040 
0041 /*
0042  * Setup a sane LPCR:
0043  *   Called with initial LPCR and desired LPES 2-bit value
0044  *
0045  *   LPES = 0b01 (HSRR0/1 used for 0x500)
0046  *   PECE = 0b111
0047  *   DPFD = 4
0048  *   HDICE = 0
0049  *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
0050  *   VRMASD = 0b10000 (L=1, LP=00)
0051  *
0052  * Other bits untouched for now
0053  */
0054 static void init_LPCR_ISA206(u64 lpcr, u64 lpes)
0055 {
0056     lpcr |= (0x10ull << LPCR_VRMASD_SH) & LPCR_VRMASD;
0057     init_LPCR_ISA300(lpcr, lpes);
0058 }
0059 
0060 static void init_FSCR(void)
0061 {
0062     u64 fscr;
0063 
0064     fscr = mfspr(SPRN_FSCR);
0065     fscr |= FSCR_TAR|FSCR_EBB;
0066     mtspr(SPRN_FSCR, fscr);
0067 }
0068 
0069 static void init_FSCR_power9(void)
0070 {
0071     u64 fscr;
0072 
0073     fscr = mfspr(SPRN_FSCR);
0074     fscr |= FSCR_SCV;
0075     mtspr(SPRN_FSCR, fscr);
0076     init_FSCR();
0077 }
0078 
0079 static void init_FSCR_power10(void)
0080 {
0081     u64 fscr;
0082 
0083     fscr = mfspr(SPRN_FSCR);
0084     fscr |= FSCR_PREFIX;
0085     mtspr(SPRN_FSCR, fscr);
0086     init_FSCR_power9();
0087 }
0088 
0089 static void init_HFSCR(void)
0090 {
0091     u64 hfscr;
0092 
0093     hfscr = mfspr(SPRN_HFSCR);
0094     hfscr |= HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|HFSCR_DSCR|\
0095          HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP;
0096     mtspr(SPRN_HFSCR, hfscr);
0097 }
0098 
0099 static void init_PMU_HV(void)
0100 {
0101     mtspr(SPRN_MMCRC, 0);
0102 }
0103 
0104 static void init_PMU_HV_ISA207(void)
0105 {
0106     mtspr(SPRN_MMCRH, 0);
0107 }
0108 
0109 static void init_PMU(void)
0110 {
0111     mtspr(SPRN_MMCRA, 0);
0112     mtspr(SPRN_MMCR0, MMCR0_FC);
0113     mtspr(SPRN_MMCR1, 0);
0114     mtspr(SPRN_MMCR2, 0);
0115 }
0116 
0117 static void init_PMU_ISA207(void)
0118 {
0119     mtspr(SPRN_MMCRS, 0);
0120 }
0121 
0122 static void init_PMU_ISA31(void)
0123 {
0124     mtspr(SPRN_MMCR3, 0);
0125     mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
0126     mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT);
0127 }
0128 
0129 /*
0130  * Note that we can be called twice of pseudo-PVRs.
0131  * The parameter offset is not used.
0132  */
0133 
0134 void __setup_cpu_power7(unsigned long offset, struct cpu_spec *t)
0135 {
0136     if (!init_hvmode_206(t))
0137         return;
0138 
0139     mtspr(SPRN_LPID, 0);
0140     mtspr(SPRN_AMOR, ~0);
0141     mtspr(SPRN_PCR, PCR_MASK);
0142     init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
0143 }
0144 
0145 void __restore_cpu_power7(void)
0146 {
0147     u64 msr;
0148 
0149     msr = mfmsr();
0150     if (!(msr & MSR_HV))
0151         return;
0152 
0153     mtspr(SPRN_LPID, 0);
0154     mtspr(SPRN_AMOR, ~0);
0155     mtspr(SPRN_PCR, PCR_MASK);
0156     init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
0157 }
0158 
0159 void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t)
0160 {
0161     init_FSCR();
0162     init_PMU();
0163     init_PMU_ISA207();
0164 
0165     if (!init_hvmode_206(t))
0166         return;
0167 
0168     mtspr(SPRN_LPID, 0);
0169     mtspr(SPRN_AMOR, ~0);
0170     mtspr(SPRN_PCR, PCR_MASK);
0171     init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
0172     init_HFSCR();
0173     init_PMU_HV();
0174     init_PMU_HV_ISA207();
0175 }
0176 
0177 void __restore_cpu_power8(void)
0178 {
0179     u64 msr;
0180 
0181     init_FSCR();
0182     init_PMU();
0183     init_PMU_ISA207();
0184 
0185     msr = mfmsr();
0186     if (!(msr & MSR_HV))
0187         return;
0188 
0189     mtspr(SPRN_LPID, 0);
0190     mtspr(SPRN_AMOR, ~0);
0191     mtspr(SPRN_PCR, PCR_MASK);
0192     init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
0193     init_HFSCR();
0194     init_PMU_HV();
0195     init_PMU_HV_ISA207();
0196 }
0197 
0198 void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t)
0199 {
0200     init_FSCR_power9();
0201     init_PMU();
0202 
0203     if (!init_hvmode_206(t))
0204         return;
0205 
0206     mtspr(SPRN_PSSCR, 0);
0207     mtspr(SPRN_LPID, 0);
0208     mtspr(SPRN_PID, 0);
0209     mtspr(SPRN_AMOR, ~0);
0210     mtspr(SPRN_PCR, PCR_MASK);
0211     init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0212              LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0213     init_HFSCR();
0214     init_PMU_HV();
0215 }
0216 
0217 void __restore_cpu_power9(void)
0218 {
0219     u64 msr;
0220 
0221     init_FSCR_power9();
0222     init_PMU();
0223 
0224     msr = mfmsr();
0225     if (!(msr & MSR_HV))
0226         return;
0227 
0228     mtspr(SPRN_PSSCR, 0);
0229     mtspr(SPRN_LPID, 0);
0230     mtspr(SPRN_PID, 0);
0231     mtspr(SPRN_AMOR, ~0);
0232     mtspr(SPRN_PCR, PCR_MASK);
0233     init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0234              LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0235     init_HFSCR();
0236     init_PMU_HV();
0237 }
0238 
0239 void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
0240 {
0241     init_FSCR_power10();
0242     init_PMU();
0243     init_PMU_ISA31();
0244 
0245     if (!init_hvmode_206(t))
0246         return;
0247 
0248     mtspr(SPRN_PSSCR, 0);
0249     mtspr(SPRN_LPID, 0);
0250     mtspr(SPRN_PID, 0);
0251     mtspr(SPRN_AMOR, ~0);
0252     mtspr(SPRN_PCR, PCR_MASK);
0253     init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0254              LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0255     init_HFSCR();
0256     init_PMU_HV();
0257 }
0258 
0259 void __restore_cpu_power10(void)
0260 {
0261     u64 msr;
0262 
0263     init_FSCR_power10();
0264     init_PMU();
0265     init_PMU_ISA31();
0266 
0267     msr = mfmsr();
0268     if (!(msr & MSR_HV))
0269         return;
0270 
0271     mtspr(SPRN_PSSCR, 0);
0272     mtspr(SPRN_LPID, 0);
0273     mtspr(SPRN_PID, 0);
0274     mtspr(SPRN_AMOR, ~0);
0275     mtspr(SPRN_PCR, PCR_MASK);
0276     init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
0277              LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
0278     init_HFSCR();
0279     init_PMU_HV();
0280 }