blob: 304b81d311034d0c2f16dc32cd58cd436fd3e4c2 [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 *
Marc Jones1587dc82017-05-15 18:55:11 -06005 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#define __SIMPLE_DEVICE__
16
Marshall Dawsonb6172112017-09-13 17:47:31 -060017#include <assert.h>
Marc Jones1587dc82017-05-15 18:55:11 -060018#include <stdint.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010019#include <console/console.h>
Marshall Dawson94ee9372017-06-15 12:18:23 -060020#include <cpu/x86/msr.h>
Kyösti Mälkkib2a5f0b2019-08-04 19:54:32 +030021#include <cpu/x86/smm.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020022#include <cpu/amd/msr.h>
Marshall Dawson94ee9372017-06-15 12:18:23 -060023#include <cpu/amd/mtrr.h>
Marc Jones1587dc82017-05-15 18:55:11 -060024#include <cbmem.h>
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060025#include <arch/bert_storage.h>
Marshall Dawsonb6172112017-09-13 17:47:31 -060026#include <soc/northbridge.h>
Marshall Dawson69486ca2019-05-02 12:03:45 -060027#include <soc/iomap.h>
28#include <amdblocks/acpimmio.h>
Marc Jones1587dc82017-05-15 18:55:11 -060029
Julius Wernercd49cce2019-03-05 16:53:33 -080030#if CONFIG(ACPI_BERT)
Marshall Dawsonf0de2422018-09-10 13:28:49 -060031 #if CONFIG_SMM_TSEG_SIZE == 0x0
32 #define BERT_REGION_MAX_SIZE 0x100000
33 #else
34 /* SMM_TSEG_SIZE must stay on a boundary appropriate for its granularity */
35 #define BERT_REGION_MAX_SIZE CONFIG_SMM_TSEG_SIZE
36 #endif
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060037#else
Marshall Dawsonf0de2422018-09-10 13:28:49 -060038 #define BERT_REGION_MAX_SIZE 0
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060039#endif
40
41void bert_reserved_region(void **start, size_t *size)
42{
Julius Wernercd49cce2019-03-05 16:53:33 -080043 if (CONFIG(ACPI_BERT))
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060044 *start = cbmem_top();
45 else
46 start = NULL;
47 *size = BERT_REGION_MAX_SIZE;
48}
49
Arthur Heymans340e4b82019-10-23 17:25:58 +020050void *cbmem_top_chipset(void)
Marshall Dawson94ee9372017-06-15 12:18:23 -060051{
52 msr_t tom = rdmsr(TOP_MEM);
53
54 if (!tom.lo)
55 return 0;
Richard Spiegel8c614f22018-10-23 14:53:23 -070056
57 /* 8MB alignment to keep MTRR usage low */
58 return (void *)ALIGN_DOWN(restore_top_of_low_cacheable()
59 - CONFIG_SMM_TSEG_SIZE
60 - BERT_REGION_MAX_SIZE, 8*MiB);
Marshall Dawsonb6172112017-09-13 17:47:31 -060061}
62
63static uintptr_t smm_region_start(void)
64{
Marshall Dawson4b0f6fa2018-09-04 13:08:25 -060065 return (uintptr_t)cbmem_top() + BERT_REGION_MAX_SIZE;
Marshall Dawsonb6172112017-09-13 17:47:31 -060066}
67
68static size_t smm_region_size(void)
69{
70 return CONFIG_SMM_TSEG_SIZE;
71}
72
Marshall Dawsonf3c57a7c2018-01-29 18:08:16 -070073/*
74 * For data stored in TSEG, ensure TValid is clear so R/W access can reach
75 * the DRAM when not in SMM.
76 */
77static void clear_tvalid(void)
78{
79 msr_t hwcr = rdmsr(HWCR_MSR);
Elyes HAOUAS400ce552018-10-12 10:54:30 +020080 msr_t mask = rdmsr(SMM_MASK_MSR);
Marshall Dawsonf3c57a7c2018-01-29 18:08:16 -070081 int tvalid = !!(mask.lo & SMM_TSEG_VALID);
82
83 if (hwcr.lo & SMM_LOCK) {
84 if (!tvalid) /* not valid but locked means still accessible */
85 return;
86
87 printk(BIOS_ERR, "Error: can't clear TValid, already locked\n");
88 return;
89 }
90
91 mask.lo &= ~SMM_TSEG_VALID;
Elyes HAOUAS400ce552018-10-12 10:54:30 +020092 wrmsr(SMM_MASK_MSR, mask);
Marshall Dawsonf3c57a7c2018-01-29 18:08:16 -070093}
94
Kyösti Mälkki4913d8a2019-08-05 12:49:09 +030095void smm_region(uintptr_t *start, size_t *size)
Marshall Dawsonb6172112017-09-13 17:47:31 -060096{
Kyösti Mälkki544369e2019-08-06 22:14:34 +030097 static int once;
Marshall Dawsonb6172112017-09-13 17:47:31 -060098
Kyösti Mälkki4913d8a2019-08-05 12:49:09 +030099 *start = smm_region_start();
100 *size = smm_region_size();
Marshall Dawsonb6172112017-09-13 17:47:31 -0600101
Kyösti Mälkki544369e2019-08-06 22:14:34 +0300102 if (!once) {
103 clear_tvalid();
104 once = 1;
105 }
Marshall Dawson94ee9372017-06-15 12:18:23 -0600106}