1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * Copyright (c) 2014 Google, Inc 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com> 7*4882a593Smuzhiyun * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan) 8*4882a593Smuzhiyun * Copyright (C) 2007-2008 coresystems GmbH 9*4882a593Smuzhiyun * Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com> 10*4882a593Smuzhiyun * 11*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0 12*4882a593Smuzhiyun */ 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun#include <common.h> 15*4882a593Smuzhiyun#include <asm/microcode.h> 16*4882a593Smuzhiyun#include <asm/msr-index.h> 17*4882a593Smuzhiyun#include <asm/mtrr.h> 18*4882a593Smuzhiyun#include <asm/post.h> 19*4882a593Smuzhiyun#include <asm/processor.h> 20*4882a593Smuzhiyun#include <asm/processor-flags.h> 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) 23*4882a593Smuzhiyun#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE 26*4882a593Smuzhiyun#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun/* Cache 4GB - MRC_SIZE_KB for MRC */ 29*4882a593Smuzhiyun#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1) 30*4882a593Smuzhiyun#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES) 31*4882a593Smuzhiyun#define CACHE_MRC_MASK (~CACHE_MRC_BYTES) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1) 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun#define NOEVICTMOD_MSR 0x2e0 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /* 38*4882a593Smuzhiyun * Note: ebp must not be touched in this code as it holds the BIST 39*4882a593Smuzhiyun * value (built-in self test). We preserve this value until it can 40*4882a593Smuzhiyun * be written to global_data when CAR is ready for use. 41*4882a593Smuzhiyun */ 42*4882a593Smuzhiyun.globl car_init 43*4882a593Smuzhiyuncar_init: 44*4882a593Smuzhiyun post_code(POST_CAR_START) 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun /* Send INIT IPI to all excluding ourself */ 47*4882a593Smuzhiyun movl $0x000C4500, %eax 48*4882a593Smuzhiyun movl $0xFEE00300, %esi 49*4882a593Smuzhiyun movl %eax, (%esi) 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun /* TODO: Load microcode later - the 'no eviction' mode breaks this */ 52*4882a593Smuzhiyun movl $MSR_IA32_UCODE_WRITE, %ecx 53*4882a593Smuzhiyun xorl %edx, %edx 54*4882a593Smuzhiyun movl $_dt_ucode_base_size, %eax 55*4882a593Smuzhiyun movl (%eax), %eax 56*4882a593Smuzhiyun addl $UCODE_HEADER_LEN, %eax 57*4882a593Smuzhiyun wrmsr 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun post_code(POST_CAR_SIPI) 60*4882a593Smuzhiyun /* Zero out all fixed range and variable range MTRRs */ 61*4882a593Smuzhiyun movl $mtrr_table, %esi 62*4882a593Smuzhiyun movl $((mtrr_table_end - mtrr_table) / 2), %edi 63*4882a593Smuzhiyun xorl %eax, %eax 64*4882a593Smuzhiyun xorl %edx, %edx 65*4882a593Smuzhiyunclear_mtrrs: 66*4882a593Smuzhiyun movw (%esi), %bx 67*4882a593Smuzhiyun movzx %bx, %ecx 68*4882a593Smuzhiyun wrmsr 69*4882a593Smuzhiyun add $2, %esi 70*4882a593Smuzhiyun dec %edi 71*4882a593Smuzhiyun jnz clear_mtrrs 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun post_code(POST_CAR_MTRR) 74*4882a593Smuzhiyun /* Configure the default memory type to uncacheable */ 75*4882a593Smuzhiyun movl $MTRR_DEF_TYPE_MSR, %ecx 76*4882a593Smuzhiyun rdmsr 77*4882a593Smuzhiyun andl $(~0x00000cff), %eax 78*4882a593Smuzhiyun wrmsr 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun post_code(POST_CAR_UNCACHEABLE) 81*4882a593Smuzhiyun /* Set Cache-as-RAM base address */ 82*4882a593Smuzhiyun movl $(MTRR_PHYS_BASE_MSR(0)), %ecx 83*4882a593Smuzhiyun movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax 84*4882a593Smuzhiyun xorl %edx, %edx 85*4882a593Smuzhiyun wrmsr 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun post_code(POST_CAR_BASE_ADDRESS) 88*4882a593Smuzhiyun /* Set Cache-as-RAM mask */ 89*4882a593Smuzhiyun movl $(MTRR_PHYS_MASK_MSR(0)), %ecx 90*4882a593Smuzhiyun movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax 91*4882a593Smuzhiyun movl $CPU_PHYSMASK_HI, %edx 92*4882a593Smuzhiyun wrmsr 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun post_code(POST_CAR_MASK) 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun /* Enable MTRR */ 97*4882a593Smuzhiyun movl $MTRR_DEF_TYPE_MSR, %ecx 98*4882a593Smuzhiyun rdmsr 99*4882a593Smuzhiyun orl $MTRR_DEF_TYPE_EN, %eax 100*4882a593Smuzhiyun wrmsr 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun /* Enable cache (CR0.CD = 0, CR0.NW = 0) */ 103*4882a593Smuzhiyun movl %cr0, %eax 104*4882a593Smuzhiyun andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax 105*4882a593Smuzhiyun invd 106*4882a593Smuzhiyun movl %eax, %cr0 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun /* enable the 'no eviction' mode */ 109*4882a593Smuzhiyun movl $NOEVICTMOD_MSR, %ecx 110*4882a593Smuzhiyun rdmsr 111*4882a593Smuzhiyun orl $1, %eax 112*4882a593Smuzhiyun andl $~2, %eax 113*4882a593Smuzhiyun wrmsr 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun /* Clear the cache memory region. This will also fill up the cache */ 116*4882a593Smuzhiyun movl $CACHE_AS_RAM_BASE, %esi 117*4882a593Smuzhiyun movl %esi, %edi 118*4882a593Smuzhiyun movl $(CACHE_AS_RAM_SIZE / 4), %ecx 119*4882a593Smuzhiyun xorl %eax, %eax 120*4882a593Smuzhiyun rep stosl 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun /* enable the 'no eviction run' state */ 123*4882a593Smuzhiyun movl $NOEVICTMOD_MSR, %ecx 124*4882a593Smuzhiyun rdmsr 125*4882a593Smuzhiyun orl $3, %eax 126*4882a593Smuzhiyun wrmsr 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun post_code(POST_CAR_FILL) 129*4882a593Smuzhiyun /* Enable Cache-as-RAM mode by disabling cache */ 130*4882a593Smuzhiyun movl %cr0, %eax 131*4882a593Smuzhiyun orl $X86_CR0_CD, %eax 132*4882a593Smuzhiyun movl %eax, %cr0 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun /* Enable cache for our code in Flash because we do XIP here */ 135*4882a593Smuzhiyun movl $MTRR_PHYS_BASE_MSR(1), %ecx 136*4882a593Smuzhiyun xorl %edx, %edx 137*4882a593Smuzhiyun movl $car_init_ret, %eax 138*4882a593Smuzhiyun andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax 139*4882a593Smuzhiyun orl $MTRR_TYPE_WRPROT, %eax 140*4882a593Smuzhiyun wrmsr 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun movl $MTRR_PHYS_MASK_MSR(1), %ecx 143*4882a593Smuzhiyun movl $CPU_PHYSMASK_HI, %edx 144*4882a593Smuzhiyun movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax 145*4882a593Smuzhiyun wrmsr 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun post_code(POST_CAR_ROM_CACHE) 148*4882a593Smuzhiyun#ifdef CONFIG_CACHE_MRC_BIN 149*4882a593Smuzhiyun /* Enable caching for ram init code to run faster */ 150*4882a593Smuzhiyun movl $MTRR_PHYS_BASE_MSR(2), %ecx 151*4882a593Smuzhiyun movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax 152*4882a593Smuzhiyun xorl %edx, %edx 153*4882a593Smuzhiyun wrmsr 154*4882a593Smuzhiyun movl $MTRR_PHYS_MASK_MSR(2), %ecx 155*4882a593Smuzhiyun movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax 156*4882a593Smuzhiyun movl $CPU_PHYSMASK_HI, %edx 157*4882a593Smuzhiyun wrmsr 158*4882a593Smuzhiyun#endif 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun post_code(POST_CAR_MRC_CACHE) 161*4882a593Smuzhiyun /* Enable cache */ 162*4882a593Smuzhiyun movl %cr0, %eax 163*4882a593Smuzhiyun andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax 164*4882a593Smuzhiyun movl %eax, %cr0 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun post_code(POST_CAR_CPU_CACHE) 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun /* All CPUs need to be in Wait for SIPI state */ 169*4882a593Smuzhiyunwait_for_sipi: 170*4882a593Smuzhiyun movl (%esi), %eax 171*4882a593Smuzhiyun bt $12, %eax 172*4882a593Smuzhiyun jc wait_for_sipi 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun /* return */ 175*4882a593Smuzhiyun jmp car_init_ret 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun.globl car_uninit 178*4882a593Smuzhiyuncar_uninit: 179*4882a593Smuzhiyun /* Disable cache */ 180*4882a593Smuzhiyun movl %cr0, %eax 181*4882a593Smuzhiyun orl $X86_CR0_CD, %eax 182*4882a593Smuzhiyun movl %eax, %cr0 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun /* Disable MTRRs */ 185*4882a593Smuzhiyun movl $MTRR_DEF_TYPE_MSR, %ecx 186*4882a593Smuzhiyun rdmsr 187*4882a593Smuzhiyun andl $(~MTRR_DEF_TYPE_EN), %eax 188*4882a593Smuzhiyun wrmsr 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun /* Disable the no-eviction run state */ 191*4882a593Smuzhiyun movl $NOEVICTMOD_MSR, %ecx 192*4882a593Smuzhiyun rdmsr 193*4882a593Smuzhiyun andl $~2, %eax 194*4882a593Smuzhiyun wrmsr 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun invd 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun /* Disable the no-eviction mode */ 199*4882a593Smuzhiyun rdmsr 200*4882a593Smuzhiyun andl $~1, %eax 201*4882a593Smuzhiyun wrmsr 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun#ifdef CONFIG_CACHE_MRC_BIN 204*4882a593Smuzhiyun /* Clear the MTRR that was used to cache MRC */ 205*4882a593Smuzhiyun xorl %eax, %eax 206*4882a593Smuzhiyun xorl %edx, %edx 207*4882a593Smuzhiyun movl $MTRR_PHYS_BASE_MSR(2), %ecx 208*4882a593Smuzhiyun wrmsr 209*4882a593Smuzhiyun movl $MTRR_PHYS_MASK_MSR(2), %ecx 210*4882a593Smuzhiyun wrmsr 211*4882a593Smuzhiyun#endif 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun /* Enable MTRRs */ 214*4882a593Smuzhiyun movl $MTRR_DEF_TYPE_MSR, %ecx 215*4882a593Smuzhiyun rdmsr 216*4882a593Smuzhiyun orl $MTRR_DEF_TYPE_EN, %eax 217*4882a593Smuzhiyun wrmsr 218*4882a593Smuzhiyun 219*4882a593Smuzhiyun invd 220*4882a593Smuzhiyun 221*4882a593Smuzhiyun ret 222*4882a593Smuzhiyun 223*4882a593Smuzhiyunmtrr_table: 224*4882a593Smuzhiyun /* Fixed MTRRs */ 225*4882a593Smuzhiyun .word 0x250, 0x258, 0x259 226*4882a593Smuzhiyun .word 0x268, 0x269, 0x26A 227*4882a593Smuzhiyun .word 0x26B, 0x26C, 0x26D 228*4882a593Smuzhiyun .word 0x26E, 0x26F 229*4882a593Smuzhiyun /* Variable MTRRs */ 230*4882a593Smuzhiyun .word 0x200, 0x201, 0x202, 0x203 231*4882a593Smuzhiyun .word 0x204, 0x205, 0x206, 0x207 232*4882a593Smuzhiyun .word 0x208, 0x209, 0x20A, 0x20B 233*4882a593Smuzhiyun .word 0x20C, 0x20D, 0x20E, 0x20F 234*4882a593Smuzhiyun .word 0x210, 0x211, 0x212, 0x213 235*4882a593Smuzhiyunmtrr_table_end: 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun .align 4 238*4882a593Smuzhiyun_dt_ucode_base_size: 239*4882a593Smuzhiyun /* These next two fields are filled in by ifdtool */ 240*4882a593Smuzhiyun.globl ucode_base 241*4882a593Smuzhiyunucode_base: /* Declared in microcode.h */ 242*4882a593Smuzhiyun .long 0 /* microcode base */ 243*4882a593Smuzhiyun .long 0 /* microcode size */ 244