1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2008-2011 4 * Graeme Russ, <graeme.russ@gmail.com> 5 * 6 * (C) Copyright 2002 7 * Daniel Engstr��m, Omicron Ceti AB, <daniel@omicron.se> 8 * 9 * (C) Copyright 2002 10 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 11 * Marius Groeger <mgroeger@sysgo.de> 12 * 13 * (C) Copyright 2002 14 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 15 * Alex Zuepke <azu@sysgo.de> 16 * 17 * Part of this file is adapted from coreboot 18 * src/arch/x86/lib/cpu.c 19 */ 20 21#include <common.h> 22#include <cpu_func.h> 23#include <init.h> 24#include <log.h> 25#include <malloc.h> 26#include <spl.h> 27#include <asm/control_regs.h> 28#include <asm/coreboot_tables.h> 29#include <asm/cpu.h> 30#include <asm/global_data.h> 31#include <asm/mp.h> 32#include <asm/msr.h> 33#include <asm/mtrr.h> 34#include <asm/processor-flags.h> 35 36DECLARE_GLOBAL_DATA_PTR; 37 38#define CPUID_FEATURE_PAE BIT(6) 39#define CPUID_FEATURE_PSE36 BIT(17) 40#define CPUID_FEAURE_HTT BIT(28) 41 42/* 43 * Constructor for a conventional segment GDT (or LDT) entry 44 * This is a macro so it can be used in initialisers 45 */ 46#define GDT_ENTRY(flags, base, limit) \ 47 ((((base) & 0xff000000ULL) << (56-24)) | \ 48 (((flags) & 0x0000f0ffULL) << 40) | \ 49 (((limit) & 0x000f0000ULL) << (48-16)) | \ 50 (((base) & 0x00ffffffULL) << 16) | \ 51 (((limit) & 0x0000ffffULL))) 52 53struct gdt_ptr { 54 u16 len; 55 u32 ptr; 56} __packed; 57 58struct cpu_device_id { 59 unsigned vendor; 60 unsigned device; 61}; 62 63struct cpuinfo_x86 { 64 uint8_t x86; /* CPU family */ 65 uint8_t x86_vendor; /* CPU vendor */ 66 uint8_t x86_model; 67 uint8_t x86_mask; 68}; 69 70/* gcc 7.3 does not wwant to drop x86_vendors, so use #ifdef */ 71#ifndef CONFIG_TPL_BUILD 72/* 73 * List of cpu vendor strings along with their normalized 74 * id values. 75 */ 76static const struct { 77 int vendor; 78 const char *name; 79} x86_vendors[] = { 80 { X86_VENDOR_INTEL, "GenuineIntel", }, 81 { X86_VENDOR_CYRIX, "CyrixInstead", }, 82 { X86_VENDOR_AMD, "AuthenticAMD", }, 83 { X86_VENDOR_UMC, "UMC UMC UMC ", }, 84 { X86_VENDOR_NEXGEN, "NexGenDriven", }, 85 { X86_VENDOR_CENTAUR, "CentaurHauls", }, 86 { X86_VENDOR_RISE, "RiseRiseRise", }, 87 { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, 88 { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, 89 { X86_VENDOR_NSC, "Geode by NSC", }, 90 { X86_VENDOR_SIS, "SiS SiS SiS ", }, 91}; 92#endif 93 94static void load_ds(u32 segment) 95{ 96 asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE)); 97} 98 99static void load_es(u32 segment) 100{ 101 asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE)); 102} 103 104static void load_fs(u32 segment) 105{ 106 asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE)); 107} 108 109static void load_gs(u32 segment) 110{ 111 asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE)); 112} 113 114static void load_ss(u32 segment) 115{ 116 asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE)); 117} 118 119static void load_gdt(const u64 *boot_gdt, u16 num_entries) 120{ 121 struct gdt_ptr gdt; 122 123 gdt.len = (num_entries * X86_GDT_ENTRY_SIZE) - 1; 124 gdt.ptr = (ulong)boot_gdt; 125 126 asm volatile("lgdtl %0\n" : : "m" (gdt)); 127} 128 129void arch_setup_gd(gd_t *new_gd) 130{ 131 u64 *gdt_addr; 132 133 gdt_addr = new_gd->arch.gdt; 134 135 /* 136 * CS: code, read/execute, 4 GB, base 0 137 * 138 * Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS 139 */ 140 gdt_addr[X86_GDT_ENTRY_UNUSED] = GDT_ENTRY(0xc09b, 0, 0xfffff); 141 gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff); 142 143 /* DS: data, read/write, 4 GB, base 0 */ 144 gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff); 145 146 /* 147 * FS: data, read/write, sizeof (Global Data Pointer), 148 * base (Global Data Pointer) 149 */ 150 new_gd->arch.gd_addr = new_gd; 151 gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0x8093, 152 (ulong)&new_gd->arch.gd_addr, 153 sizeof(new_gd->arch.gd_addr) - 1); 154 155 /* 16-bit CS: code, read/execute, 64 kB, base 0 */ 156 gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff); 157 158 /* 16-bit DS: data, read/write, 64 kB, base 0 */ 159 gdt_addr[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x0093, 0, 0x0ffff); 160 161 gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff); 162 gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff); 163 164 load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES); 165 load_ds(X86_GDT_ENTRY_32BIT_DS); 166 load_es(X86_GDT_ENTRY_32BIT_DS); 167 load_gs(X86_GDT_ENTRY_32BIT_DS); 168 load_ss(X86_GDT_ENTRY_32BIT_DS); 169 load_fs(X86_GDT_ENTRY_32BIT_FS); 170} 171 172#ifdef CONFIG_HAVE_FSP 173/* 174 * Setup FSP execution environment GDT 175 * 176 * Per Intel FSP external architecture specification, before calling any FSP 177 * APIs, we need make sure the system is in flat 32-bit mode and both the code 178 * and data selectors should have full 4GB access range. Here we reuse the one 179 * we used in arch/x86/cpu/start16.S, and reload the segment registers. 180 */ 181void setup_fsp_gdt(void) 182{ 183 load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4); 184 load_ds(X86_GDT_ENTRY_32BIT_DS); 185 load_ss(X86_GDT_ENTRY_32BIT_DS); 186 load_es(X86_GDT_ENTRY_32BIT_DS); 187 load_fs(X86_GDT_ENTRY_32BIT_DS); 188 load_gs(X86_GDT_ENTRY_32BIT_DS); 189} 190#endif 191 192/* 193 * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected 194 * by the fact that they preserve the flags across the division of 5/2. 195 * PII and PPro exhibit this behavior too, but they have cpuid available. 196 */ 197 198/* 199 * Perform the Cyrix 5/2 test. A Cyrix won't change 200 * the flags, while other 486 chips will. 201 */ 202static inline int test_cyrix_52div(void) 203{ 204 unsigned int test; 205 206 __asm__ __volatile__( 207 "sahf\n\t" /* clear flags (%eax = 0x0005) */ 208 "div %b2\n\t" /* divide 5 by 2 */ 209 "lahf" /* store flags into %ah */ 210 : "=a" (test) 211 : "0" (5), "q" (2) 212 : "cc"); 213 214 /* AH is 0x02 on Cyrix after the divide.. */ 215 return (unsigned char) (test >> 8) == 0x02; 216} 217 218#ifndef CONFIG_TPL_BUILD 219/* 220 * Detect a NexGen CPU running without BIOS hypercode new enough 221 * to have CPUID. (Thanks to Herbert Oppmann) 222 */ 223static int deep_magic_nexgen_probe(void) 224{ 225 int ret; 226 227 __asm__ __volatile__ ( 228 " movw $0x5555, %%ax\n" 229 " xorw %%dx,%%dx\n" 230 " movw $2, %%cx\n" 231 " divw %%cx\n" 232 " movl $0, %%eax\n" 233 " jnz 1f\n" 234 " movl $1, %%eax\n" 235 "1:\n" 236 : "=a" (ret) : : "cx", "dx"); 237 return ret; 238} 239#endif 240 241static bool has_cpuid(void) 242{ 243 return flag_is_changeable_p(X86_EFLAGS_ID); 244} 245 246static bool has_mtrr(void) 247{ 248 return cpuid_edx(0x00000001) & (1 << 12) ? true : false; 249} 250 251#ifndef CONFIG_TPL_BUILD 252static int build_vendor_name(char *vendor_name) 253{ 254 struct cpuid_result result; 255 result = cpuid(0x00000000); 256 unsigned int *name_as_ints = (unsigned int *)vendor_name; 257 258 name_as_ints[0] = result.ebx; 259 name_as_ints[1] = result.edx; 260 name_as_ints[2] = result.ecx; 261 262 return result.eax; 263} 264#endif 265 266static void identify_cpu(struct cpu_device_id *cpu) 267{ 268 cpu->device = 0; /* fix gcc 4.4.4 warning */ 269 270 /* 271 * Do a quick and dirty check to save space - Intel and AMD only and 272 * just the vendor. This is enough for most TPL code. 273 */ 274 if (spl_phase() == PHASE_TPL) { 275 struct cpuid_result result; 276 277 result = cpuid(0x00000000); 278 switch (result.ecx >> 24) { 279 case 'l': /* GenuineIntel */ 280 cpu->vendor = X86_VENDOR_INTEL; 281 break; 282 case 'D': /* AuthenticAMD */ 283 cpu->vendor = X86_VENDOR_AMD; 284 break; 285 default: 286 cpu->vendor = X86_VENDOR_ANY; 287 break; 288 } 289 return; 290 } 291 292/* gcc 7.3 does not want to drop x86_vendors, so use #ifdef */ 293#ifndef CONFIG_TPL_BUILD 294 char vendor_name[16]; 295 int i; 296 297 vendor_name[0] = '\0'; /* Unset */ 298 299 /* Find the id and vendor_name */ 300 if (!has_cpuid()) { 301 /* Its a 486 if we can modify the AC flag */ 302 if (flag_is_changeable_p(X86_EFLAGS_AC)) 303 cpu->device = 0x00000400; /* 486 */ 304 else 305 cpu->device = 0x00000300; /* 386 */ 306 if ((cpu->device == 0x00000400) && test_cyrix_52div()) { 307 memcpy(vendor_name, "CyrixInstead", 13); 308 /* If we ever care we can enable cpuid here */ 309 } 310 /* Detect NexGen with old hypercode */ 311 else if (deep_magic_nexgen_probe()) 312 memcpy(vendor_name, "NexGenDriven", 13); 313 } else { 314 int cpuid_level; 315 316 cpuid_level = build_vendor_name(vendor_name); 317 vendor_name[12] = '\0'; 318 319 /* Intel-defined flags: level 0x00000001 */ 320 if (cpuid_level >= 0x00000001) { 321 cpu->device = cpuid_eax(0x00000001); 322 } else { 323 /* Have CPUID level 0 only unheard of */ 324 cpu->device = 0x00000400; 325 } 326 } 327 cpu->vendor = X86_VENDOR_UNKNOWN; 328 for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) { 329 if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) { 330 cpu->vendor = x86_vendors[i].vendor; 331 break; 332 } 333 } 334#endif 335} 336 337static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms) 338{ 339 c->x86 = (tfms >> 8) & 0xf; 340 c->x86_model = (tfms >> 4) & 0xf; 341 c->x86_mask = tfms & 0xf; 342 if (c->x86 == 0xf) 343 c->x86 += (tfms >> 20) & 0xff; 344 if (c->x86 >= 0x6) 345 c->x86_model += ((tfms >> 16) & 0xF) << 4; 346} 347 348u32 cpu_get_family_model(void) 349{ 350 return gd->arch.x86_device & 0x0fff0ff0; 351} 352 353u32 cpu_get_stepping(void) 354{ 355 return gd->arch.x86_mask; 356} 357 358/* initialise FPU, reset EM, set MP and NE */ 359static void setup_cpu_features(void) 360{ 361 const u32 em_rst = ~X86_CR0_EM; 362 const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE; 363 364 asm ("fninit\n" \ 365 "movl %%cr0, %%eax\n" \ 366 "andl %0, %%eax\n" \ 367 "orl %1, %%eax\n" \ 368 "movl %%eax, %%cr0\n" \ 369 : : "i" (em_rst), "i" (mp_ne_set) : "eax"); 370} 371 372void cpu_reinit_fpu(void) 373{ 374 asm ("fninit\n"); 375} 376 377static void setup_identity(void) 378{ 379 /* identify CPU via cpuid and store the decoded info into gd->arch */ 380 if (has_cpuid()) { 381 struct cpu_device_id cpu; 382 struct cpuinfo_x86 c; 383 384 identify_cpu(&cpu); 385 get_fms(&c, cpu.device); 386 gd->arch.x86 = c.x86; 387 gd->arch.x86_vendor = cpu.vendor; 388 gd->arch.x86_model = c.x86_model; 389 gd->arch.x86_mask = c.x86_mask; 390 gd->arch.x86_device = cpu.device; 391 392 gd->arch.has_mtrr = has_mtrr(); 393 } 394} 395 396static uint cpu_cpuid_extended_level(void) 397{ 398 return cpuid_eax(0x80000000); 399} 400 401int cpu_phys_address_size(void) 402{ 403 if (!has_cpuid()) 404 return 32; 405 406 if (cpu_cpuid_extended_level() >= 0x80000008) 407 return cpuid_eax(0x80000008) & 0xff; 408 409 if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36)) 410 return 36; 411 412 return 32; 413} 414 415/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ 416static void setup_pci_ram_top(void) 417{ 418 gd_set_pci_ram_top(0x80000000U); 419} 420 421static void setup_mtrr(void) 422{ 423 u64 mtrr_cap; 424 425 /* Configure fixed range MTRRs for some legacy regions */ 426 if (!gd->arch.has_mtrr || !ll_boot_init()) 427 return; 428 429 mtrr_cap = native_read_msr(MTRR_CAP_MSR); 430 if (mtrr_cap & MTRR_CAP_FIX) { 431 /* Mark the VGA RAM area as uncacheable */ 432 native_write_msr(MTRR_FIX_16K_A0000_MSR, 433 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), 434 MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); 435 436 /* 437 * Mark the PCI ROM area as cacheable to improve ROM 438 * execution performance. 439 */ 440 native_write_msr(MTRR_FIX_4K_C0000_MSR, 441 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), 442 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); 443 native_write_msr(MTRR_FIX_4K_C8000_MSR, 444 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), 445 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); 446 native_write_msr(MTRR_FIX_4K_D0000_MSR, 447 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), 448 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); 449 native_write_msr(MTRR_FIX_4K_D8000_MSR, 450 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), 451 MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); 452 453 /* Enable the fixed range MTRRs */ 454 msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); 455 } 456} 457 458int x86_cpu_init_tpl(void) 459{ 460 setup_cpu_features(); 461 setup_identity(); 462 463 return 0; 464} 465 466int x86_cpu_init_f(void) 467{ 468 if (ll_boot_init()) 469 setup_cpu_features(); 470 setup_identity(); 471 setup_mtrr(); 472 setup_pci_ram_top(); 473 474 /* Set up the i8254 timer if required */ 475 if (IS_ENABLED(CONFIG_I8254_TIMER)) 476 i8254_init(); 477 478 return 0; 479} 480 481int x86_cpu_reinit_f(void) 482{ 483 long addr; 484 485 setup_identity(); 486 setup_pci_ram_top(); 487 addr = locate_coreboot_table(); 488 if (addr >= 0) { 489 gd->arch.coreboot_table = addr; 490 gd->flags |= GD_FLG_SKIP_LL_INIT; 491 } 492 493 return 0; 494} 495 496void x86_enable_caches(void) 497{ 498 unsigned long cr0; 499 500 cr0 = read_cr0(); 501 cr0 &= ~(X86_CR0_NW | X86_CR0_CD); 502 write_cr0(cr0); 503 wbinvd(); 504} 505void enable_caches(void) __attribute__((weak, alias("x86_enable_caches"))); 506 507void x86_disable_caches(void) 508{ 509 unsigned long cr0; 510 511 cr0 = read_cr0(); 512 cr0 |= X86_CR0_NW | X86_CR0_CD; 513 wbinvd(); 514 write_cr0(cr0); 515 wbinvd(); 516} 517void disable_caches(void) __attribute__((weak, alias("x86_disable_caches"))); 518 519int dcache_status(void) 520{ 521 return !(read_cr0() & X86_CR0_CD); 522} 523 524void cpu_enable_paging_pae(ulong cr3) 525{ 526 __asm__ __volatile__( 527 /* Load the page table address */ 528 "movl %0, %%cr3\n" 529 /* Enable pae */ 530 "movl %%cr4, %%eax\n" 531 "orl $0x00000020, %%eax\n" 532 "movl %%eax, %%cr4\n" 533 /* Enable paging */ 534 "movl %%cr0, %%eax\n" 535 "orl $0x80000000, %%eax\n" 536 "movl %%eax, %%cr0\n" 537 : 538 : "r" (cr3) 539 : "eax"); 540} 541 542void cpu_disable_paging_pae(void) 543{ 544 /* Turn off paging */ 545 __asm__ __volatile__ ( 546 /* Disable paging */ 547 "movl %%cr0, %%eax\n" 548 "andl $0x7fffffff, %%eax\n" 549 "movl %%eax, %%cr0\n" 550 /* Disable pae */ 551 "movl %%cr4, %%eax\n" 552 "andl $0xffffffdf, %%eax\n" 553 "movl %%eax, %%cr4\n" 554 : 555 : 556 : "eax"); 557} 558 559static bool can_detect_long_mode(void) 560{ 561 return cpuid_eax(0x80000000) > 0x80000000UL; 562} 563 564static bool has_long_mode(void) 565{ 566 return cpuid_edx(0x80000001) & (1 << 29) ? true : false; 567} 568 569int cpu_has_64bit(void) 570{ 571 return has_cpuid() && can_detect_long_mode() && 572 has_long_mode(); 573} 574 575/* Base address for page tables used for 64-bit mode */ 576#define PAGETABLE_BASE 0x80000 577#define PAGETABLE_SIZE (6 * 4096) 578 579/** 580 * build_pagetable() - build a flat 4GiB page table structure for 64-bti mode 581 * 582 * @pgtable: Pointer to a 24iKB block of memory 583 */ 584static void build_pagetable(uint32_t *pgtable) 585{ 586 uint i; 587 588 memset(pgtable, '\0', PAGETABLE_SIZE); 589 590 /* Level 4 needs a single entry */ 591 pgtable[0] = (ulong)&pgtable[1024] + 7; 592 593 /* Level 3 has one 64-bit entry for each GiB of memory */ 594 for (i = 0; i < 4; i++) 595 pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + 7; 596 597 /* Level 2 has 2048 64-bit entries, each repesenting 2MiB */ 598 for (i = 0; i < 2048; i++) 599 pgtable[2048 + i * 2] = 0x183 + (i << 21UL); 600} 601 602int cpu_jump_to_64bit(ulong setup_base, ulong target) 603{ 604 uint32_t *pgtable; 605 606 pgtable = memalign(4096, PAGETABLE_SIZE); 607 if (!pgtable) 608 return -ENOMEM; 609 610 build_pagetable(pgtable); 611 cpu_call64((ulong)pgtable, setup_base, target); 612 free(pgtable); 613 614 return -EFAULT; 615} 616 617/* 618 * cpu_jump_to_64bit_uboot() - Jump from SPL to U-Boot 619 * 620 * It works by setting up page tables and calling the code to enter 64-bit long 621 * mode 622 */ 623int cpu_jump_to_64bit_uboot(ulong target) 624{ 625 uint32_t *pgtable; 626 627 pgtable = (uint32_t *)PAGETABLE_BASE; 628 build_pagetable(pgtable); 629 630 /* Jump to U-Boot */ 631 cpu_call64(PAGETABLE_BASE, 0, (ulong)target); 632 633 return -EFAULT; 634} 635 636int x86_mp_init(void) 637{ 638 int ret; 639 640 ret = mp_init(); 641 if (ret) { 642 printf("Warning: MP init failure\n"); 643 return log_ret(ret); 644 } 645 646 return 0; 647} 648