coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
xip_cache.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/cpu.h>
4 #include <program_loading.h>
5 #include <commonlib/region.h>
6 #include <console/console.h>
7 #include <cpu/x86/mtrr.h>
8 
9 /* For now this is a good lowest common denominator for the total CPU cache.
10  TODO: fetch the total amount of cache from CPUID leaf2. */
11 #define MAX_CPU_CACHE (256 * KiB)
12 
13 /* This makes the 'worst' case assumption that all cachelines covered by
14  the MTRR, no matter the caching type, are filled and not overlapping. */
16 {
18  uint32_t total_cache = 0;
19 
20  for (i = 0; i < total_mtrrs; i++) {
21  msr_t mtrr = rdmsr(MTRR_PHYS_MASK(i));
22  if (!(mtrr.lo & MTRR_PHYS_MASK_VALID))
23  continue;
24  total_cache += ~(mtrr.lo & 0xfffff000) + 1;
25  }
26  return total_cache;
27 }
28 
30 {
32  const uint32_t size = prog_size(prog);
33  const uint32_t end = base + size;
34  const uint32_t cache_used = max_cache_used();
35  /* This will accumulate MTRR's as XIP stages are run.
36  For now this includes bootblock which sets ups its own
37  caching elsewhere, verstage and romstage */
38  int mtrr_num = get_free_var_mtrr();
39  uint32_t mtrr_base;
40  uint32_t mtrr_size = 4 * KiB;
41  struct cpuinfo_x86 cpu_info;
42 
44  /*
45  * An unidentified combination of speculative reads and branch
46  * predictions inside WRPROT-cacheable memory can cause invalidation
47  * of cachelines and loss of stack on models based on NetBurst
48  * microarchitecture. Therefore disable WRPROT region entirely for
49  * all family F models.
50  */
51  if (cpu_info.x86 == 0xf) {
53  "PROG_RUN: CPU does not support caching ROM\n"
54  "The next stage will run slowly!\n");
55  return;
56  }
57 
58  if (mtrr_num == -1) {
60  "PROG_RUN: No MTRR available to cache ROM!\n"
61  "The next stage will run slowly!\n");
62  return;
63  }
64 
65  if (cache_used + mtrr_size > MAX_CPU_CACHE) {
67  "PROG_RUN: No more cache available for the next stage\n"
68  "The next stage will run slowly!\n");
69  return;
70  }
71 
72  while (1) {
73  if (ALIGN_DOWN(base, mtrr_size) + mtrr_size >= end)
74  break;
75  if (cache_used + mtrr_size * 2 > MAX_CPU_CACHE)
76  break;
77  mtrr_size *= 2;
78  }
79 
80  mtrr_base = ALIGN_DOWN(base, mtrr_size);
81  if (mtrr_base + mtrr_size < end) {
82  printk(BIOS_NOTICE, "PROG_RUN: Limiting XIP cache to %uKiB!\n",
83  mtrr_size / KiB);
84  /* Check if we can cover a bigger range by aligning up. */
85  const uint32_t alt_base = ALIGN_UP(base, mtrr_size);
86  const uint32_t lower_coverage = mtrr_base + mtrr_size - base;
87  const uint32_t upper_coverage = MIN(alt_base + mtrr_size, end) - alt_base;
88  if (upper_coverage > lower_coverage)
89  mtrr_base = alt_base;
90  }
91 
93  "PROG_RUN: Setting MTRR to cache XIP stage. base: 0x%08x, size: 0x%08x\n",
94  mtrr_base, mtrr_size);
95 
96  set_var_mtrr(mtrr_num, mtrr_base, mtrr_size, MTRR_TYPE_WRPROT);
97 }
static unsigned int cpuid_eax(unsigned int op)
Definition: cpu.h:79
static void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
Definition: cpu.h:278
#define MIN(a, b)
Definition: helpers.h:37
#define ALIGN_DOWN(x, a)
Definition: helpers.h:18
#define KiB
Definition: helpers.h:75
#define ALIGN_UP(x, a)
Definition: helpers.h:17
#define printk(level,...)
Definition: stdlib.h:16
static int total_mtrrs
Definition: mtrr.c:40
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_NOTICE
BIOS_NOTICE - Unexpected but relatively insignificant.
Definition: loglevel.h:100
int get_free_var_mtrr(void)
Definition: mtrrlib.c:11
void set_var_mtrr(unsigned int reg, unsigned int base, unsigned int size, unsigned int type)
Definition: mtrrlib.c:30
static void * prog_start(const struct prog *prog)
static size_t prog_size(const struct prog *prog)
uintptr_t base
Definition: uart.c:17
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
Definition: cpu.h:230
unsigned int lo
Definition: msr.h:111
#define MTRR_PHYS_MASK(reg)
Definition: mtrr.h:40
static int get_var_mtrr_count(void)
Definition: mtrr.h:105
#define MTRR_TYPE_WRPROT
Definition: mtrr.h:13
#define MTRR_PHYS_MASK_VALID
Definition: mtrr.h:41
#define MAX_CPU_CACHE
Definition: xip_cache.c:11
static uint32_t max_cache_used(void)
Definition: xip_cache.c:15
void platform_prog_run(struct prog *prog)
Definition: xip_cache.c:29