coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
cpu_hybrid.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #include <acpi/acpigen.h>
3 #include <intelblocks/acpi.h>
4 #include <soc/cpu.h>
5 #include <smp/spinlock.h>
6 #include <device/device.h>
7 #include <device/path.h>
8 #include <cpu/x86/lapic.h>
9 #include <cpu/x86/mp.h>
10 
11 #define CPPC_NOM_FREQ_IDX 22
12 #define CPPC_NOM_PERF_IDX 3
13 
17 };
18 
20 static u8 global_cpu_type[CONFIG_MAX_CPUS];
21 
22 static bool is_big_core(void)
23 {
25 }
26 
27 static u32 get_cpu_index(void)
28 {
29  u32 cpu_index = 0;
30  struct device *dev;
31  u32 my_apic_id = lapicid();
32 
33  for (dev = dev_find_lapic(0); dev; dev = dev->next) {
34  if (my_apic_id > dev->path.apic.apic_id)
35  cpu_index++;
36  }
37 
38  return cpu_index;
39 }
40 
41 /*
42  * This function determines the type (big or small) of the CPU that is executing
43  * it and stores the information (in a thread-safe manner) in an global_cpu_type
44  * array.
45  * It requires the SoC to implement a function `get_soc_cpu_type()` which will be
46  * called in a critical section to determine the type of the executing CPU.
47  */
48 static void set_cpu_type(void *unused)
49 {
50  spin_lock(&cpu_lock);
52 
53  if (is_big_core())
55 
56  spin_unlock(&cpu_lock);
57 }
58 
59 static void run_set_cpu_type(void *unused)
60 {
62  printk(BIOS_ERR, "cpu_hybrid: Failed to set global_cpu_type with CPU type info\n");
63  return;
64  }
65 }
66 
67 static void acpi_get_cpu_nomi_perf(u16 *small_core_nom_perf, u16 *big_core_nom_perf)
68 {
69  u16 big_core_scal_factor, small_core_scal_factor;
70  u8 max_non_turbo_ratio = cpu_get_max_non_turbo_ratio();
71 
72  soc_get_scaling_factor(&big_core_scal_factor, &small_core_scal_factor);
73 
74  *big_core_nom_perf = (u16)((max_non_turbo_ratio * big_core_scal_factor) / 100);
75 
76  *small_core_nom_perf = (u16)((max_non_turbo_ratio * small_core_scal_factor) / 100);
77 }
78 
80 {
82 }
83 
84 /* Updates Nominal Frequency and Nominal Performance */
85 static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core_id)
86 {
87  u16 small_core_nom_perf, big_core_nom_perf;
88 
90  return;
91 
92  acpi_get_cpu_nomi_perf(&small_core_nom_perf, &big_core_nom_perf);
93 
94  if (global_cpu_type[core_id] == CPU_TYPE_BIG)
95  acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, big_core_nom_perf);
96  else
98  small_core_nom_perf);
99 
100  /* Update CPU's nominal frequency */
103 }
104 
106 {
107  char pkg_path[16];
108 
109  if (core_id == 0)
110  snprintf(pkg_path, sizeof(pkg_path), CPPC_PACKAGE_NAME, 0);
111  else
112  snprintf(pkg_path, sizeof(pkg_path),
113  CONFIG_ACPI_CPU_STRING "." CPPC_PACKAGE_NAME, 0);
114 
115  acpigen_write_method("_CPC", 0);
116 
117  /* Update nominal performance and nominal frequency */
118  acpigen_cppc_update_nominal_freq_perf(pkg_path, core_id);
120  acpigen_emit_namestring(pkg_path);
121  acpigen_pop_len();
122 }
123 
void acpigen_emit_namestring(const char *namepath)
Definition: acpigen.c:275
void acpigen_pop_len(void)
Definition: acpigen.c:37
void acpigen_set_package_element_int(const char *package, unsigned int element, uint64_t src)
Definition: acpigen.c:368
void acpigen_emit_byte(unsigned char b)
Definition: acpigen.c:61
void acpigen_write_method(const char *name, int nargs)
Definition: acpigen.c:758
int cpu_index(void)
Definition: cpu.c:332
@ BS_DEV_INIT_CHIPS
Definition: bootstate.h:79
@ BS_ON_EXIT
Definition: bootstate.h:96
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
enum cb_err mp_run_on_all_cpus(void(*func)(void *), void *arg)
Definition: mp_init.c:1002
static void run_set_cpu_type(void *unused)
Definition: cpu_hybrid.c:59
cpu_perf_eff_type
Definition: cpu_hybrid.c:14
@ CPU_TYPE_SMALL
Definition: cpu_hybrid.c:15
@ CPU_TYPE_BIG
Definition: cpu_hybrid.c:16
static u8 global_cpu_type[CONFIG_MAX_CPUS]
Definition: cpu_hybrid.c:20
static void acpi_get_cpu_nomi_perf(u16 *small_core_nom_perf, u16 *big_core_nom_perf)
Definition: cpu_hybrid.c:67
static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core_id)
Definition: cpu_hybrid.c:85
void acpigen_write_CPPC_hybrid_method(s32 core_id)
Definition: cpu_hybrid.c:105
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, run_set_cpu_type, NULL)
static void set_cpu_type(void *unused)
Definition: cpu_hybrid.c:48
#define CPPC_NOM_FREQ_IDX
Definition: cpu_hybrid.c:11
static u16 acpi_get_cpu_nominal_freq(void)
Definition: cpu_hybrid.c:79
#define CPPC_NOM_PERF_IDX
Definition: cpu_hybrid.c:12
static u32 get_cpu_index(void)
Definition: cpu_hybrid.c:27
DECLARE_SPIN_LOCK(cpu_lock)
static bool is_big_core(void)
Definition: cpu_hybrid.c:22
uint32_t cpu_get_bus_frequency(void)
Definition: cpulib.c:223
uint8_t cpu_get_max_non_turbo_ratio(void)
Definition: cpulib.c:305
struct device * dev_find_lapic(unsigned int apic_id)
Given a Local APIC ID, find the device structure.
Definition: device_util.c:17
#define CPPC_PACKAGE_NAME
Definition: acpigen.h:238
@ RETURN_OP
Definition: acpigen.h:146
#define spin_lock(lock)
Definition: spinlock.h:11
#define spin_unlock(lock)
Definition: spinlock.h:12
static __always_inline unsigned int lapicid(void)
Definition: lapic.h:136
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
enum core_type get_soc_cpu_type(void)
Definition: cpu.c:77
bool soc_is_nominal_freq_supported(void)
Definition: cpu.c:98
void soc_get_scaling_factor(u16 *big_core_scal_factor, u16 *small_core_scal_factor)
Definition: cpu.c:92
@ CPUID_CORE_TYPE_INTEL_CORE
Definition: acpi.h:17
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
int32_t s32
Definition: stdint.h:50
unsigned int apic_id
Definition: path.h:72
struct apic_path apic
Definition: path.h:119
Definition: device.h:107
struct device_path path
Definition: device.h:115
DEVTREE_CONST struct device * next
Definition: device.h:113
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35