static void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val) { u64 pir = get_hard_smp_processor_id(cpu); mtspr(SPRN_LPCR, lpcr_val); opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val); }
static void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val) { u64 pir = get_hard_smp_processor_id(cpu); mtspr(SPRN_LPCR, lpcr_val); /* * Program the LPCR via stop-api only if the deepest stop state * can lose hypervisor context. */ if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT) opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val); }
static int pnv_save_sprs_for_deep_states(void) { int cpu; int rc; /* * hid0, hid1, hid4, hid5, hmeer and lpcr values are symmetric across * all cpus at boot. Get these reg values of current cpu and use the * same across all cpus. */ uint64_t lpcr_val = mfspr(SPRN_LPCR); uint64_t hid0_val = mfspr(SPRN_HID0); uint64_t hid1_val = mfspr(SPRN_HID1); uint64_t hid4_val = mfspr(SPRN_HID4); uint64_t hid5_val = mfspr(SPRN_HID5); uint64_t hmeer_val = mfspr(SPRN_HMEER); uint64_t msr_val = MSR_IDLE; uint64_t psscr_val = pnv_deepest_stop_psscr_val; for_each_present_cpu(cpu) { uint64_t pir = get_hard_smp_processor_id(cpu); uint64_t hsprg0_val = (uint64_t)paca_ptrs[cpu]; rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val); if (rc != 0) return rc; if (cpu_has_feature(CPU_FTR_ARCH_300)) { rc = opal_slw_set_reg(pir, P9_STOP_SPR_MSR, msr_val); if (rc) return rc; rc = opal_slw_set_reg(pir, P9_STOP_SPR_PSSCR, psscr_val); if (rc) return rc; } /* HIDs are per core registers */ if (cpu_thread_in_core(cpu) == 0) { rc = opal_slw_set_reg(pir, SPRN_HMEER, hmeer_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID0, hid0_val); if (rc != 0) return rc; /* Only p8 needs to set extra HID regiters */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) { rc = opal_slw_set_reg(pir, SPRN_HID1, hid1_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID4, hid4_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID5, hid5_val); if (rc != 0) return rc; } } } return 0; }
int pnv_save_sprs_for_winkle(void) { int cpu; int rc; /* * hid0, hid1, hid4, hid5, hmeer and lpcr values are symmetric accross * all cpus at boot. Get these reg values of current cpu and use the * same accross all cpus. */ uint64_t lpcr_val = mfspr(SPRN_LPCR); uint64_t hid0_val = mfspr(SPRN_HID0); uint64_t hid1_val = mfspr(SPRN_HID1); uint64_t hid4_val = mfspr(SPRN_HID4); uint64_t hid5_val = mfspr(SPRN_HID5); uint64_t hmeer_val = mfspr(SPRN_HMEER); for_each_possible_cpu(cpu) { uint64_t pir = get_hard_smp_processor_id(cpu); uint64_t hsprg0_val = (uint64_t)&paca[cpu]; /* * HSPRG0 is used to store the cpu's pointer to paca. Hence last * 3 bits are guaranteed to be 0. Program slw to restore HSPRG0 * with 63rd bit set, so that when a thread wakes up at 0x100 we * can use this bit to distinguish between fastsleep and * deep winkle. */ hsprg0_val |= 1; rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val); if (rc != 0) return rc; /* HIDs are per core registers */ if (cpu_thread_in_core(cpu) == 0) { rc = opal_slw_set_reg(pir, SPRN_HMEER, hmeer_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID0, hid0_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID1, hid1_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID4, hid4_val); if (rc != 0) return rc; rc = opal_slw_set_reg(pir, SPRN_HID5, hid5_val); if (rc != 0) return rc; } } return 0; }