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