/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include bool cpu_soc_is_in_untrusted_mode(void) { msr_t msr; msr = rdmsr(MSR_BIOS_DONE); return !!(msr.lo & ENABLE_IA_UNTRUSTED); } void cpu_soc_bios_done(void) { msr_t msr; msr = rdmsr(MSR_BIOS_DONE); msr.lo |= ENABLE_IA_UNTRUSTED; wrmsr(MSR_BIOS_DONE, msr); } uint8_t get_supported_lpm_mask(void) { return LPM_S0i2_0 | LPM_S0i2_1 | LPM_S0i2_2; } static void soc_fsp_load(void) { fsps_load(); } static void configure_misc(void) { msr_t msr; const struct soc_intel_pantherlake_config *conf = config_of_soc(); msr = rdmsr(IA32_MISC_ENABLE); msr.lo |= FAST_STRINGS_ENABLE_BIT; msr.lo |= TM1_TM2_EMTTM_ENABLE_BIT; wrmsr(IA32_MISC_ENABLE, msr); /* Set EIST status */ cpu_set_eist(conf->eist_enable); /* Disable Thermal interrupts */ msr.lo = 0; msr.hi = 0; wrmsr(IA32_THERM_INTERRUPT, msr); /* Enable package critical interrupt only */ msr.lo = CRITICAL_TEMP_INTERRUPT_ENABLE; msr.hi = 0; wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr); /* Enable PROCHOT and Power Performance Platform Override */ msr = rdmsr(MSR_POWER_CTL); msr.lo |= ENABLE_BIDIR_PROCHOT; msr.lo |= VR_THERM_ALERT_DISABLE_LOCK; msr.lo |= PWR_PERF_PLATFORM_OVR; wrmsr(MSR_POWER_CTL, msr); } enum core_type get_soc_cpu_type(void) { if (cpu_is_hybrid_supported()) return cpu_get_cpu_type(); return CPUID_CORE_TYPE_INTEL_CORE; } bool soc_is_nominal_freq_supported(void) { return true; } static void enable_x2apic(void) { if (!CONFIG(X2APIC_LATE_WORKAROUND)) return; enable_lapic_mode(true); } /* All CPUs including BSP will run the following function. */ void soc_core_init(struct device *cpu) { /* Clear out pending MCEs */ mca_configure(); enable_x2apic(); enable_lapic_tpr(); /* Configure Enhanced SpeedStep and Thermal Sensors */ configure_misc(); enable_pm_timer_emulation(); /* Enable Direct Cache Access */ configure_dca_cap(); /* Set energy policy */ set_energy_perf_bias(ENERGY_POLICY_NORMAL); const struct soc_intel_pantherlake_config *conf = config_of_soc(); /* Set energy-performance preference */ if (conf != NULL && conf->enable_energy_perf_pref) { if (check_energy_perf_cap()) set_energy_perf_pref(conf->energy_perf_pref_value); } /* Enable Turbo */ enable_turbo(); /* Set core type in struct cpu_info */ set_dev_core_type(); if (CONFIG(INTEL_TME) && is_tme_supported()) set_tme_core_activate(); /* TODO: Add support for DROP_CPU_FEATURE_PROGRAM_IN_FSP */ } static void per_cpu_smm_trigger(void) { /* Relocate the SMM handler. */ smm_relocate(); } static void pre_mp_init(void) { soc_fsp_load(); const struct soc_intel_pantherlake_config *conf = config_of_soc(); if (conf == NULL) { printk(BIOS_ERR, "Configuration could not be retrieved.\n"); return; } if (conf->enable_energy_perf_pref) { if (check_energy_perf_cap()) enable_energy_perf_pref(); else printk(BIOS_WARNING, "Energy Performance Preference not supported!\n"); } } static void post_mp_init(void) { /* Set Max Ratio */ cpu_set_max_ratio(); /* * 1. Now that all APs have been relocated as well as the BSP let SMIs * start flowing. * 2. Skip enabling power button SMI and enable it after BS_CHIPS_INIT * to avoid shutdown hang due to lack of init on certain IP in FSP-S. */ global_smi_enable_no_pwrbtn(); } static const struct mp_ops mp_ops = { /* * Skip Pre MP init MTRR programming as MTRRs are mirrored from BSP, * that are set prior to ramstage. * Real MTRRs programming are being done after resource allocation. */ .pre_mp_init = pre_mp_init, .get_cpu_count = get_cpu_count, .get_smm_info = smm_info, .get_microcode_info = get_microcode_info, .pre_mp_smm_init = smm_initialize, .per_cpu_smm_trigger = per_cpu_smm_trigger, .relocation_handler = smm_relocation_handler, .post_mp_init = post_mp_init, }; void mp_init_cpus(struct bus *cpu_bus) { if (mp_init_with_smm(cpu_bus, &mp_ops)) printk(BIOS_ERR, "MP initialization failure.\n"); /* Thermal throttle activation offset */ configure_tcc_thermal_target(); } int soc_skip_ucode_update(u32 current_patch_id, u32 new_patch_id) { if (!CONFIG(CHROMEOS)) return 0; /* * Locked RO Descriptor Implications: * * - A locked descriptor signals the RO binary is fixed; the FIT will load the * RO's microcode during system reset. * - Attempts to load newer microcode from the RW CBFS will cause a boot-time * delay (~60ms, core-dependent), as the microcode must be reloaded on BSP+APs. * - The kernel can load microcode updates without impacting AP FW boot time. * - Skipping RW CBFS microcode loading is low-risk when the RO is locked, * prioritizing fast boot times. */ if (CONFIG(LOCK_MANAGEMENT_ENGINE) && current_patch_id) return 1; return 0; }