Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 1 | #include <cpu/x86/cache.h> |
| 2 | #include <cpu/x86/mtrr.h> |
| 3 | #include <cpu/x86/msr.h> |
| 4 | |
Kyösti Mälkki | 88a67f0 | 2013-12-12 12:27:53 +0200 | [diff] [blame] | 5 | #ifdef __ROMCC__ |
| 6 | static |
| 7 | #endif |
| 8 | void set_var_mtrr( |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 9 | unsigned reg, unsigned base, unsigned size, unsigned type) |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 10 | { |
| 11 | /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ |
Yinghai Lu | 21332b8 | 2007-04-06 19:49:05 +0000 | [diff] [blame] | 12 | /* FIXME: It only support 4G less range */ |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 13 | msr_t basem, maskm; |
| 14 | basem.lo = base | type; |
| 15 | basem.hi = 0; |
Alexandru Gagniuc | 86091f9 | 2015-09-30 20:23:09 -0700 | [diff] [blame] | 16 | wrmsr(MTRR_PHYS_BASE(reg), basem); |
| 17 | maskm.lo = ~(size - 1) | MTRR_PHYS_MASK_VALID; |
Stefan Reinauer | 23f49a8 | 2011-04-14 20:39:49 +0000 | [diff] [blame] | 18 | maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; |
Alexandru Gagniuc | 86091f9 | 2015-09-30 20:23:09 -0700 | [diff] [blame] | 19 | wrmsr(MTRR_PHYS_MASK(reg), maskm); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 20 | } |
| 21 | |
Martin Roth | c4e49f6 | 2015-07-11 13:42:54 -0600 | [diff] [blame] | 22 | #if !IS_ENABLED(CONFIG_CACHE_AS_RAM) |
Stefan Reinauer | b91a0f2 | 2012-06-15 15:34:24 -0700 | [diff] [blame] | 23 | static void cache_ramstage(void) |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 24 | { |
Stefan Reinauer | b91a0f2 | 2012-06-15 15:34:24 -0700 | [diff] [blame] | 25 | /* Enable caching for lower 1MB and ram stage using variable mtrr */ |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 26 | disable_cache(); |
Stefan Reinauer | b91a0f2 | 2012-06-15 15:34:24 -0700 | [diff] [blame] | 27 | set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 28 | enable_cache(); |
| 29 | } |
| 30 | |
Patrick Georgi | 1da1046 | 2011-10-28 20:28:03 +0200 | [diff] [blame] | 31 | const int addr_det = 0; |
| 32 | |
Paul Menzel | 4fe9813 | 2014-01-25 15:55:28 +0100 | [diff] [blame] | 33 | /* the fixed and variable MTRRs are power-up with random values, |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 34 | * clear them to MTRR_TYPE_UNCACHEABLE for safety. |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 35 | */ |
| 36 | static void do_early_mtrr_init(const unsigned long *mtrr_msrs) |
| 37 | { |
| 38 | /* Precondition: |
Alexandru Gagniuc | 86091f9 | 2015-09-30 20:23:09 -0700 | [diff] [blame] | 39 | * The cache is not enabled in cr0 nor in MTRR_DEF_TYPE_MSR |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 40 | * entry32.inc ensures the cache is not enabled in cr0 |
| 41 | */ |
| 42 | msr_t msr; |
| 43 | const unsigned long *msr_addr; |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 44 | |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 45 | /* Initialize all of the relevant msrs to 0 */ |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 46 | msr.lo = 0; |
| 47 | msr.hi = 0; |
| 48 | unsigned long msr_nr; |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 49 | for(msr_addr = mtrr_msrs; (msr_nr = *msr_addr); msr_addr++) { |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 50 | wrmsr(msr_nr, msr); |
| 51 | } |
| 52 | |
Martin Roth | 46cf9f7 | 2015-07-11 13:56:58 -0600 | [diff] [blame] | 53 | #if defined(CONFIG_XIP_ROM_SIZE) && CONFIG_XIP_ROM_SIZE |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 54 | /* enable write through caching so we can do execute in place |
| 55 | * on the flash rom. |
Patrick Georgi | 1da1046 | 2011-10-28 20:28:03 +0200 | [diff] [blame] | 56 | * Determine address by calculating the XIP_ROM_SIZE sized area with |
| 57 | * XIP_ROM_SIZE alignment that contains the global variable defined above; |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 58 | */ |
Patrick Georgi | 1da1046 | 2011-10-28 20:28:03 +0200 | [diff] [blame] | 59 | unsigned long f = (unsigned long)&addr_det & ~(CONFIG_XIP_ROM_SIZE - 1); |
| 60 | set_var_mtrr(1, f, CONFIG_XIP_ROM_SIZE, MTRR_TYPE_WRBACK); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 61 | #endif |
| 62 | |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 63 | /* Set the default memory type and enable fixed and variable MTRRs |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 64 | */ |
| 65 | /* Enable Variable MTRRs */ |
| 66 | msr.hi = 0x00000000; |
| 67 | msr.lo = 0x00000800; |
Alexandru Gagniuc | 86091f9 | 2015-09-30 20:23:09 -0700 | [diff] [blame] | 68 | wrmsr(MTRR_DEF_TYPE_MSR, msr); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 69 | |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Stefan Reinauer | d4f5373 | 2010-04-09 14:46:51 +0000 | [diff] [blame] | 72 | static inline void early_mtrr_init(void) |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 73 | { |
| 74 | static const unsigned long mtrr_msrs[] = { |
| 75 | /* fixed mtrr */ |
| 76 | 0x250, 0x258, 0x259, |
| 77 | 0x268, 0x269, 0x26A, |
| 78 | 0x26B, 0x26C, 0x26D, |
| 79 | 0x26E, 0x26F, |
| 80 | /* var mtrr */ |
| 81 | 0x200, 0x201, 0x202, 0x203, |
| 82 | 0x204, 0x205, 0x206, 0x207, |
| 83 | 0x208, 0x209, 0x20A, 0x20B, |
| 84 | 0x20C, 0x20D, 0x20E, 0x20F, |
| 85 | /* NULL end of table */ |
| 86 | 0 |
| 87 | }; |
| 88 | disable_cache(); |
| 89 | do_early_mtrr_init(mtrr_msrs); |
| 90 | enable_cache(); |
| 91 | } |
| 92 | |
Stefan Reinauer | 8a926845 | 2010-04-07 03:40:37 +0000 | [diff] [blame] | 93 | static inline int early_mtrr_init_detected(void) |
Jason Schildt | 6a2c09a | 2005-10-25 21:07:34 +0000 | [diff] [blame] | 94 | { |
| 95 | msr_t msr; |
| 96 | /* See if MTRR's are enabled. |
| 97 | * a #RESET disables them while an #INIT |
| 98 | * preserves their state. This works |
| 99 | * on both Intel and AMD cpus, at least |
| 100 | * according to the documentation. |
| 101 | */ |
Alexandru Gagniuc | 86091f9 | 2015-09-30 20:23:09 -0700 | [diff] [blame] | 102 | msr = rdmsr(MTRR_DEF_TYPE_MSR); |
| 103 | return msr.lo & MTRR_DEF_TYPE_EN; |
Jason Schildt | 6a2c09a | 2005-10-25 21:07:34 +0000 | [diff] [blame] | 104 | } |
Stefan Reinauer | 23f49a8 | 2011-04-14 20:39:49 +0000 | [diff] [blame] | 105 | #endif |