coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <commonlib/sort.h>
5 #include <console/console.h>
6 #include <delay.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <intelblocks/cpulib.h>
10 #include <soc/pci_devs.h>
11 #include <soc/msr.h>
12 #include <soc/soc_util.h>
13 #include <soc/util.h>
14 #include <timer.h>
15 
17 {
18  if (stack >= MAX_IIO_STACK) {
19  printk(BIOS_ERR, "%s: Stack %u does not exist!\n", __func__, stack);
20  return 0;
21  }
24  return pci_io_read_config32(dev, offset) >> (8 * (stack % 4)) & 0xff;
25 }
26 
28 {
29  uint32_t pam0123_unlock_dram = 0x33333330;
30  uint32_t pam456_unlock_dram = 0x00333333;
31  uint32_t bus1 = get_stack_busno(1);
32 
34  SAD_ALL_PAM0123_CSR, pam0123_unlock_dram);
36  SAD_ALL_PAM456_CSR, pam456_unlock_dram);
37 
42  printk(BIOS_DEBUG, "%s:%s pam0123_csr: 0x%x, pam456_csr: 0x%x\n",
43  __FILE__, __func__, reg1, reg2);
44 }
45 
47 {
48  msr_t ppin = {0};
49  msr_t msr;
50 
51  /* If MSR_PLATFORM_INFO PPIN_CAP is 0, PPIN capability is not supported */
52  msr = rdmsr(MSR_PLATFORM_INFO);
53  if ((msr.lo & MSR_PPIN_CAP) == 0) {
54  printk(BIOS_ERR, "MSR_PPIN_CAP is 0, PPIN is not supported\n");
55  return ppin;
56  }
57 
58  /* Access to MSR_PPIN is permitted only if MSR_PPIN_CTL LOCK is 0 and ENABLE is 1 */
59  msr = rdmsr(MSR_PPIN_CTL);
60  if (msr.lo & MSR_PPIN_CTL_LOCK) {
61  printk(BIOS_ERR, "MSR_PPIN_CTL_LOCK is 1, PPIN access is not allowed\n");
62  return ppin;
63  }
64 
65  if ((msr.lo & MSR_PPIN_CTL_ENABLE) == 0) {
66  /* Set MSR_PPIN_CTL ENABLE to 1 */
67  msr.lo |= MSR_PPIN_CTL_ENABLE;
68  wrmsr(MSR_PPIN_CTL, msr);
69  }
70  ppin = rdmsr(MSR_PPIN);
71  /* Set enable to 0 after reading MSR_PPIN */
72  msr.lo &= ~MSR_PPIN_CTL_ENABLE;
73  wrmsr(MSR_PPIN_CTL, msr);
74  return ppin;
75 }
76 
77 static unsigned int get_threads_per_package(void)
78 {
79  unsigned int core_count, thread_count;
80  cpu_read_topology(&core_count, &thread_count);
81  return thread_count;
82 }
83 
85 {
87 }
88 
89 const IIO_UDS *get_iio_uds(void)
90 {
91  size_t hob_size;
92  static const IIO_UDS *hob;
93  const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
94 
95  if (hob != NULL)
96  return hob;
97 
98  hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size);
99  assert(hob != NULL && hob_size != 0);
100  return hob;
101 }
102 
104 {
105  const IIO_UDS *hob = get_iio_uds();
106 
107  // copy IIO Stack info from FSP HOB
108  info->no_of_stacks = 0;
109  for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
110  for (int x = 0; x < MAX_IIO_STACK; ++x) {
111  const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
112  if (!is_iio_stack_res(ri))
113  continue;
114  assert(info->no_of_stacks < (CONFIG_MAX_SOCKET * MAX_IIO_STACK));
115  memcpy(&info->res[info->no_of_stacks++], ri, sizeof(STACK_RES));
116  }
117  }
118 }
119 
120 unsigned int soc_get_num_cpus(void)
121 {
122  /* The FSP IIO UDS HOB has field numCpus, it is actually socket count */
123  return get_iio_uds()->SystemStatus.numCpus;
124 }
125 
126 #if ENV_RAMSTAGE /* Setting devtree variables is only allowed in ramstage. */
127 static void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits)
128 {
129  register int ecx;
130  struct cpuid_result cpuid_regs;
131 
132  /* get max index of CPUID */
133  cpuid_regs = cpuid(0);
134  assert(cpuid_regs.eax >= 0xb); /* cpuid_regs.eax is max input value for cpuid */
135 
136  *thread_bits = *core_bits = 0;
137  ecx = 0;
138  while (1) {
139  cpuid_regs = cpuid_ext(0xb, ecx);
140  if (ecx == 0) {
141  *thread_bits = (cpuid_regs.eax & 0x1f);
142  } else {
143  *core_bits = (cpuid_regs.eax & 0x1f) - *thread_bits;
144  break;
145  }
146  ecx++;
147  }
148 }
149 
150 static void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, uint32_t thread_bits,
151  uint8_t *package, uint8_t *core, uint8_t *thread)
152 {
153  if (package != NULL)
154  *package = (apicid >> (thread_bits + core_bits));
155  if (core != NULL)
156  *core = (uint32_t)((apicid >> thread_bits) & ~((~0) << core_bits));
157  if (thread != NULL)
158  *thread = (uint32_t)(apicid & ~((~0) << thread_bits));
159 }
160 
161 void xeonsp_init_cpu_config(void)
162 {
163  struct device *dev;
164  int apic_ids[CONFIG_MAX_CPUS] = {0}, apic_ids_by_thread[CONFIG_MAX_CPUS] = {0};
165  int num_apics = 0;
166  uint32_t core_bits, thread_bits;
167  unsigned int core_count, thread_count;
168  unsigned int num_sockets;
169 
170  /*
171  * sort APIC ids in ascending order to identify apicid ranges for
172  * each numa domain
173  */
174  for (dev = all_devices; dev; dev = dev->next) {
175  if ((dev->path.type != DEVICE_PATH_APIC) ||
176  (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
177  continue;
178  }
179  if (!dev->enabled)
180  continue;
181  if (num_apics >= ARRAY_SIZE(apic_ids))
182  break;
183  apic_ids[num_apics++] = dev->path.apic.apic_id;
184  }
185  if (num_apics > 1)
186  bubblesort(apic_ids, num_apics, NUM_ASCENDING);
187 
188  num_sockets = soc_get_num_cpus();
189  cpu_read_topology(&core_count, &thread_count);
190  assert(num_apics == (num_sockets * thread_count));
191 
192  /* sort them by thread i.e., all cores with thread 0 and then thread 1 */
193  int index = 0;
194  for (int id = 0; id < num_apics; ++id) {
195  int apic_id = apic_ids[id];
196  if (apic_id & 0x1) { /* 2nd thread */
197  apic_ids_by_thread[index + (num_apics/2) - 1] = apic_id;
198  } else { /* 1st thread */
199  apic_ids_by_thread[index++] = apic_id;
200  }
201  }
202 
203  /* update apic_id, node_id in sorted order */
204  num_apics = 0;
205  get_core_thread_bits(&core_bits, &thread_bits);
206  for (dev = all_devices; dev; dev = dev->next) {
207  uint8_t package;
208 
209  if ((dev->path.type != DEVICE_PATH_APIC) ||
210  (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
211  continue;
212  }
213  if (!dev->enabled)
214  continue;
215  if (num_apics >= ARRAY_SIZE(apic_ids))
216  break;
217  dev->path.apic.apic_id = apic_ids_by_thread[num_apics];
218  get_cpu_info_from_apicid(dev->path.apic.apic_id, core_bits, thread_bits,
219  &package, NULL, NULL);
220  dev->path.apic.node_id = package;
221  printk(BIOS_DEBUG, "CPU %d apic_id: 0x%x (%d), node_id: 0x%x\n",
222  num_apics, dev->path.apic.apic_id,
223  dev->path.apic.apic_id, dev->path.apic.node_id);
224 
225  ++num_apics;
226  }
227 }
228 
229 /* return true if command timed out else false */
230 static bool wait_for_bios_cmd_cpl(pci_devfn_t dev, uint32_t reg, uint32_t mask,
231  uint32_t target)
232 {
233  const uint32_t max_delay = 5000; /* 5 seconds max */
234  const uint32_t step_delay = 50; /* 50 us */
235  struct stopwatch sw;
236 
237  stopwatch_init_msecs_expire(&sw, max_delay);
238  while ((pci_s_read_config32(dev, reg) & mask) != target) {
239  udelay(step_delay);
240  if (stopwatch_expired(&sw)) {
241  printk(BIOS_ERR, "%s timed out for dev: %x, reg: 0x%x, "
242  "mask: 0x%x, target: 0x%x\n", __func__, dev, reg, mask, target);
243  return true; /* timedout */
244  }
245  }
246  return false; /* successful */
247 }
248 
249 /* return true if command timed out else false */
250 static bool write_bios_mailbox_cmd(pci_devfn_t dev, uint32_t command, uint32_t data)
251 {
252  /* verify bios is not in busy state */
253  if (wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_MB_INTERFACE_REG, BIOS_MB_RUN_BUSY_MASK, 0))
254  return true; /* timed out */
255 
256  /* write data to data register */
257  printk(BIOS_SPEW, "%s - pci_s_write_config32 reg: 0x%x, data: 0x%x\n", __func__,
260 
261  /* write the command */
262  printk(BIOS_SPEW, "%s - pci_s_write_config32 reg: 0x%x, data: 0x%lx\n", __func__,
265  command | BIOS_MB_RUN_BUSY_MASK);
266 
267  /* wait for completion or time out*/
268  return wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_MB_INTERFACE_REG,
270 }
271 
272 /* return true if command timed out else false */
273 static bool set_bios_reset_cpl_for_package(uint32_t socket, uint32_t rst_cpl_mask,
274  uint32_t pcode_init_mask, uint32_t val)
275 {
277  const pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN);
278 
280  reg &= (uint32_t) ~rst_cpl_mask;
281  reg |= val;
282 
283  /* update BIOS RESET completion bit */
285 
286  /* wait for PCU ack */
287  return wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_RESET_CPL_REG, pcode_init_mask,
288  pcode_init_mask);
289 }
290 
291 static void set_bios_init_completion_for_package(uint32_t socket)
292 {
293  uint32_t data;
294  bool timedout;
296  const pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN);
297 
298  /* read PCU config */
299  timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0);
300  if (timedout) {
301  /* 2nd try */
302  timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0);
303  if (timedout)
304  die("BIOS PCU Misc Config Read timed out.\n");
305 
306  /* Since the 1st try failed, we need to make sure PCU is in stable state */
308  printk(BIOS_SPEW, "%s - pci_s_read_config32 reg: 0x%x, data: 0x%x\n",
309  __func__, PCU_CR1_BIOS_MB_DATA_REG, data);
310  timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_WRITE_PCU_MISC_CFG, data);
311  if (timedout)
312  die("BIOS PCU Misc Config Write timed out.\n");
313  }
314 
315  /* update RST_CPL3, PCODE_INIT_DONE3 */
316  timedout = set_bios_reset_cpl_for_package(socket, RST_CPL3_MASK,
318  if (timedout)
319  die("BIOS RESET CPL3 timed out.\n");
320 
321  /* Set PMAX_LOCK - must be set before RESET CPL4 */
323 
324  /* update RST_CPL4, PCODE_INIT_DONE4 */
325  timedout = set_bios_reset_cpl_for_package(socket, RST_CPL4_MASK,
327  if (timedout)
328  die("BIOS RESET CPL4 timed out.\n");
329 
330  /* set CSR_DESIRED_CORES_CFG2 lock bit */
333  printk(BIOS_SPEW, "%s - pci_s_write_config32 PCU_CR1_DESIRED_CORES_CFG2_REG 0x%x, data: 0x%x\n",
334  __func__, PCU_CR1_DESIRED_CORES_CFG2_REG, data);
336 }
337 
338 void set_bios_init_completion(void)
339 {
340  /* FIXME: This may need to be changed for multi-socket platforms */
341  uint32_t sbsp_socket_id = 0;
342 
343  /*
344  * According to the BIOS Writer's Guide, the SBSP must be the last socket
345  * to receive the BIOS init completion message. So, we send it to all non-SBSP
346  * sockets first.
347  */
348  for (uint32_t socket = 0; socket < soc_get_num_cpus(); ++socket) {
349  if (socket == sbsp_socket_id)
350  continue;
351  set_bios_init_completion_for_package(socket);
352  }
353 
354  /* And finally, take care of the SBSP */
355  set_bios_init_completion_for_package(sbsp_socket_id);
356 }
357 #endif
static struct cpuid_result cpuid_ext(int op, unsigned int ecx)
Definition: cpu.h:59
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
#define assert(statement)
Definition: assert.h:74
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
int cpu_read_topology(unsigned int *num_phys, unsigned int *num_virt)
Definition: cpulib.c:267
DEVTREE_CONST struct device *DEVTREE_CONST all_devices
Linked list of ALL devices.
Definition: device_const.c:13
static struct smmstore_params_info info
Definition: ramstage.c:12
static size_t offset
Definition: flashconsole.c:16
#define MSR_PLATFORM_INFO
Definition: fsb.c:16
const void * fsp_find_extension_hob_by_guid(const uint8_t *guid, size_t *size)
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
static __always_inline void wrmsr(unsigned int index, msr_t msr)
Definition: msr.h:157
static __always_inline void pci_or_config32(const struct device *dev, u16 reg, u32 ormask)
Definition: pci_ops.h:191
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack)
Definition: soc_util.c:33
bool is_iio_stack_res(const STACK_RES *res)
Definition: soc_util.c:28
int x
Definition: edid.c:994
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
@ DEVICE_PATH_CPU_CLUSTER
Definition: path.h:14
@ DEVICE_PATH_APIC
Definition: path.h:12
static __always_inline uint32_t pci_s_read_config32(pci_devfn_t dev, uint16_t reg)
Definition: pci_io_cfg.h:92
static __always_inline uint32_t pci_io_read_config32(pci_devfn_t dev, uint16_t reg)
Definition: pci_io_cfg.h:41
static __always_inline void pci_io_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value)
Definition: pci_io_cfg.h:65
static __always_inline void pci_s_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value)
Definition: pci_io_cfg.h:110
#define PCI_DEV(SEGBUS, DEV, FN)
Definition: pci_type.h:14
u32 pci_devfn_t
Definition: pci_type.h:8
#define PCU_DEV
Definition: pci_devs.h:121
u32 cpuid
static const int mask[4]
Definition: gpio.c:308
#define PCODE_INIT_DONE3_MASK
Definition: pci_devs.h:57
#define SAD_ALL_FUNC
Definition: pci_devs.h:12
#define PCU_DEV_CR0(bus)
Definition: pci_devs.h:27
#define PCU_CR1_BIOS_MB_DATA_REG
Definition: pci_devs.h:41
#define UBOX_DECS_BUS
Definition: pci_devs.h:98
#define PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK
Definition: pci_devs.h:61
#define BIOS_CMD_READ_PCU_MISC_CFG
Definition: pci_devs.h:46
#define RST_CPL3_MASK
Definition: pci_devs.h:53
#define PCODE_INIT_DONE4_MASK
Definition: pci_devs.h:58
#define SAD_ALL_PAM0123_CSR
Definition: pci_devs.h:13
#define PCU_CR1_BIOS_MB_INTERFACE_REG
Definition: pci_devs.h:43
#define SAD_ALL_PAM456_CSR
Definition: pci_devs.h:15
#define PMAX_LOCK
Definition: pci_devs.h:37
#define UBOX_DECS_CPUBUSNO_CSR
Definition: pci_devs.h:101
#define UBOX_DECS_FUNC
Definition: pci_devs.h:100
#define SAD_ALL_DEV
Definition: pci_devs.h:11
#define UBOX_DECS_CPUBUSNO1_CSR
Definition: pci_devs.h:102
#define PCU_CR1_DESIRED_CORES_CFG2_REG
Definition: pci_devs.h:60
#define UBOX_DECS_DEV
Definition: pci_devs.h:99
#define PCU_CR0_PMAX
Definition: pci_devs.h:36
#define PCU_CR1_FUN
Definition: pci_devs.h:39
#define BIOS_CMD_WRITE_PCU_MISC_CFG
Definition: pci_devs.h:47
#define PCU_CR1_BIOS_RESET_CPL_REG
Definition: pci_devs.h:50
#define RST_CPL4_MASK
Definition: pci_devs.h:54
#define PCU_IIO_STACK
Definition: pci_devs.h:23
#define BIOS_MB_RUN_BUSY_MASK
Definition: pci_devs.h:44
#define MSR_PPIN
Definition: msr.h:98
#define MSR_PPIN_CTL_ENABLE
Definition: msr.h:97
#define MSR_PPIN_CTL
Definition: msr.h:94
#define MSR_PPIN_CTL_LOCK
Definition: msr.h:95
#define MSR_PPIN_CAP
Definition: msr.h:100
void xeonsp_init_cpu_config(void)
void set_bios_init_completion(void)
int get_platform_thread_count(void)
Definition: util.c:84
static unsigned int get_threads_per_package(void)
Definition: util.c:77
msr_t read_msr_ppin(void)
Definition: util.c:46
void unlock_pam_regions(void)
Definition: util.c:27
void get_iiostack_info(struct iiostack_resource *info)
Definition: util.c:103
const IIO_UDS * get_iio_uds(void)
Definition: util.c:89
uint8_t get_stack_busno(const uint8_t stack)
Definition: util.c:16
unsigned int soc_get_num_cpus(void)
Definition: util.c:120
void bubblesort(int *v, size_t num_entries, sort_order_t order)
Definition: sort.c:8
@ NUM_ASCENDING
Definition: sort.h:8
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
unsigned int node_id
Definition: path.h:74
unsigned int apic_id
Definition: path.h:72
Definition: device.h:76
DEVTREE_CONST struct device * dev
Definition: device.h:78
uint32_t ecx
Definition: cpu.h:32
struct apic_path apic
Definition: path.h:119
enum device_path_type type
Definition: path.h:114
Definition: device.h:107
struct device_path path
Definition: device.h:115
DEVTREE_CONST struct bus * bus
Definition: device.h:108
DEVTREE_CONST struct device * next
Definition: device.h:113
unsigned int enabled
Definition: device.h:122
unsigned int lo
Definition: msr.h:111
u8 val
Definition: sys.c:300
#define s(param, src_bits, pmcreg, dst_bits)
void udelay(uint32_t us)
Definition: udelay.c:15