blob: e2b0f7d6bc0e59d2c35dcecf9a76024b40b5a8b5 [file] [log] [blame]
Marc Jones1587dc82017-05-15 18:55:11 -06001/*
2 * This file is part of the coreboot project.
3 *
Marshall Dawsonb6172112017-09-13 17:47:31 -06004 * Copyright (C) 2015 Intel Corp.
5 *
Marc Jones1587dc82017-05-15 18:55:11 -06006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#define __SIMPLE_DEVICE__
17
Marshall Dawsonb6172112017-09-13 17:47:31 -060018#include <assert.h>
Marc Jones1587dc82017-05-15 18:55:11 -060019#include <stdint.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010020#include <console/console.h>
Marshall Dawson94ee9372017-06-15 12:18:23 -060021#include <cpu/x86/msr.h>
Kyösti Mälkkib2a5f0b2019-08-04 19:54:32 +030022#include <cpu/x86/smm.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020023#include <cpu/amd/msr.h>
Marshall Dawson94ee9372017-06-15 12:18:23 -060024#include <cpu/amd/mtrr.h>
Marc Jones1587dc82017-05-15 18:55:11 -060025#include <cbmem.h>
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060026#include <arch/bert_storage.h>
Marshall Dawsonb6172112017-09-13 17:47:31 -060027#include <soc/northbridge.h>
Marshall Dawson69486ca2019-05-02 12:03:45 -060028#include <soc/iomap.h>
29#include <amdblocks/acpimmio.h>
Marc Jones1587dc82017-05-15 18:55:11 -060030
31void backup_top_of_low_cacheable(uintptr_t ramtop)
32{
Marshall Dawson22f54c52017-11-29 09:30:23 -070033 biosram_write32(BIOSRAM_CBMEM_TOP, ramtop);
Marc Jones1587dc82017-05-15 18:55:11 -060034}
35
36uintptr_t restore_top_of_low_cacheable(void)
37{
Marshall Dawson22f54c52017-11-29 09:30:23 -070038 return biosram_read32(BIOSRAM_CBMEM_TOP);
Marc Jones1587dc82017-05-15 18:55:11 -060039}
Marshall Dawson94ee9372017-06-15 12:18:23 -060040
Julius Wernercd49cce2019-03-05 16:53:33 -080041#if CONFIG(ACPI_BERT)
Marshall Dawsonf0de2422018-09-10 13:28:49 -060042 #if CONFIG_SMM_TSEG_SIZE == 0x0
43 #define BERT_REGION_MAX_SIZE 0x100000
44 #else
45 /* SMM_TSEG_SIZE must stay on a boundary appropriate for its granularity */
46 #define BERT_REGION_MAX_SIZE CONFIG_SMM_TSEG_SIZE
47 #endif
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060048#else
Marshall Dawsonf0de2422018-09-10 13:28:49 -060049 #define BERT_REGION_MAX_SIZE 0
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060050#endif
51
52void bert_reserved_region(void **start, size_t *size)
53{
Julius Wernercd49cce2019-03-05 16:53:33 -080054 if (CONFIG(ACPI_BERT))
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060055 *start = cbmem_top();
56 else
57 start = NULL;
58 *size = BERT_REGION_MAX_SIZE;
59}
60
Marshall Dawson94ee9372017-06-15 12:18:23 -060061void *cbmem_top(void)
62{
63 msr_t tom = rdmsr(TOP_MEM);
64
65 if (!tom.lo)
66 return 0;
Richard Spiegel8c614f22018-10-23 14:53:23 -070067
68 /* 8MB alignment to keep MTRR usage low */
69 return (void *)ALIGN_DOWN(restore_top_of_low_cacheable()
70 - CONFIG_SMM_TSEG_SIZE
71 - BERT_REGION_MAX_SIZE, 8*MiB);
Marshall Dawsonb6172112017-09-13 17:47:31 -060072}
73
74static uintptr_t smm_region_start(void)
75{
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060076 return (uintptr_t)cbmem_top() + BERT_REGION_MAX_SIZE;
Marshall Dawsonb6172112017-09-13 17:47:31 -060077}
78
79static size_t smm_region_size(void)
80{
81 return CONFIG_SMM_TSEG_SIZE;
82}
83
Kyösti Mälkki14222d82019-08-05 15:10:18 +030084void smm_region(uintptr_t *start, size_t *size)
Marshall Dawsonb6172112017-09-13 17:47:31 -060085{
Kyösti Mälkki14222d82019-08-05 15:10:18 +030086 *start = smm_region_start();
Marshall Dawsonb6172112017-09-13 17:47:31 -060087 *size = smm_region_size();
88}
89
Marshall Dawsonf3c57a7c2018-01-29 18:08:16 -070090/*
91 * For data stored in TSEG, ensure TValid is clear so R/W access can reach
92 * the DRAM when not in SMM.
93 */
94static void clear_tvalid(void)
95{
96 msr_t hwcr = rdmsr(HWCR_MSR);
Elyes HAOUAS400ce552018-10-12 10:54:30 +020097 msr_t mask = rdmsr(SMM_MASK_MSR);
Marshall Dawsonf3c57a7c2018-01-29 18:08:16 -070098 int tvalid = !!(mask.lo & SMM_TSEG_VALID);
99
100 if (hwcr.lo & SMM_LOCK) {
101 if (!tvalid) /* not valid but locked means still accessible */
102 return;
103
104 printk(BIOS_ERR, "Error: can't clear TValid, already locked\n");
105 return;
106 }
107
108 mask.lo &= ~SMM_TSEG_VALID;
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200109 wrmsr(SMM_MASK_MSR, mask);
Marshall Dawsonf3c57a7c2018-01-29 18:08:16 -0700110}
111
Kyösti Mälkki14222d82019-08-05 15:10:18 +0300112int smm_subregion(int sub, uintptr_t *start, size_t *size)
Marshall Dawsonb6172112017-09-13 17:47:31 -0600113{
Kyösti Mälkki544369e2019-08-06 22:14:34 +0300114 static int once;
Marshall Dawsonb6172112017-09-13 17:47:31 -0600115 uintptr_t sub_base;
116 size_t sub_size;
117 const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
118
Kyösti Mälkki14222d82019-08-05 15:10:18 +0300119 smm_region(&sub_base, &sub_size);
Marshall Dawsonb6172112017-09-13 17:47:31 -0600120 assert(sub_size > CONFIG_SMM_RESERVED_SIZE);
121
Kyösti Mälkki544369e2019-08-06 22:14:34 +0300122 if (!once) {
123 clear_tvalid();
124 once = 1;
125 }
126
Marshall Dawsonb6172112017-09-13 17:47:31 -0600127 switch (sub) {
128 case SMM_SUBREGION_HANDLER:
129 /* Handler starts at the base of TSEG. */
130 sub_size -= cache_size;
131 break;
132 case SMM_SUBREGION_CACHE:
133 /* External cache is in the middle of TSEG. */
134 sub_base += sub_size - cache_size;
135 sub_size = cache_size;
136 break;
137 default:
Kyösti Mälkkid157b3e2019-08-05 15:13:53 +0300138 *start = 0;
139 *size = 0;
Marshall Dawsonb6172112017-09-13 17:47:31 -0600140 return -1;
141 }
142
Kyösti Mälkki14222d82019-08-05 15:10:18 +0300143 *start = sub_base;
Marshall Dawsonb6172112017-09-13 17:47:31 -0600144 *size = sub_size;
Marshall Dawsonb6172112017-09-13 17:47:31 -0600145 return 0;
Marshall Dawson94ee9372017-06-15 12:18:23 -0600146}