mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	Assembler is not happy:
arch/x86/cpu/sipi_vector.S: Assembler messages:
arch/x86/cpu/sipi_vector.S:134: Warning: no instruction mnemonic suffix given and no register operands; using default for `cmp'
arch/x86/cpu/sipi_vector.S:139: Warning: no instruction mnemonic suffix given and no register operands; using default for `bts'
arch/x86/cpu/sipi_vector.S:157: Warning: no instruction mnemonic suffix given and no register operands; using default for `cmp'
Fix this by adding appropriate suffixes to the assembler commands.
Fixes: 45b5a37836d5 ("x86: Add multi-processor init")
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
		
	
			
		
			
				
	
	
		
			217 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0 */
 | 
						|
/*
 | 
						|
 * Copyright (c) 2015 Google, Inc
 | 
						|
 *
 | 
						|
 * Taken from coreboot file of the same name
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * The SIPI vector is responsible for initializing the APs in the sytem. It
 | 
						|
 * loads microcode, sets up MSRs, and enables caching before calling into
 | 
						|
 * C code
 | 
						|
 */
 | 
						|
 | 
						|
#include <asm/global_data.h>
 | 
						|
#include <asm/msr-index.h>
 | 
						|
#include <asm/processor.h>
 | 
						|
#include <asm/processor-flags.h>
 | 
						|
#include <asm/sipi.h>
 | 
						|
 | 
						|
#define CODE_SEG	(X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE)
 | 
						|
#define DATA_SEG	(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE)
 | 
						|
 | 
						|
/*
 | 
						|
 * First we have the 16-bit section. Every AP process starts here.
 | 
						|
 * The simple task is to load U-Boot's Global Descriptor Table (GDT) to allow
 | 
						|
 * U-Boot's 32-bit code to become visible, then jump to ap_start.
 | 
						|
 *
 | 
						|
 * Note that this code is copied to RAM below 1MB in mp_init.c, and runs from
 | 
						|
 * there, but the 32-bit code (ap_start and onwards) is part of U-Boot and
 | 
						|
 * is therefore relocated to the top of RAM with other U-Boot code. This
 | 
						|
 * means that for the 16-bit code we must write relocatable code, but for the
 | 
						|
 * rest, we can do what we like.
 | 
						|
 */
 | 
						|
.text
 | 
						|
.code16
 | 
						|
.globl ap_start16
 | 
						|
ap_start16:
 | 
						|
	cli
 | 
						|
	xorl	%eax, %eax
 | 
						|
	movl	%eax, %cr3		/* Invalidate TLB */
 | 
						|
 | 
						|
	/* setup the data segment */
 | 
						|
	movw	%cs, %ax
 | 
						|
	movw	%ax, %ds
 | 
						|
 | 
						|
	/* Use an address relative to the data segment for the GDT */
 | 
						|
	movl	$gdtaddr, %ebx
 | 
						|
	subl	$ap_start16, %ebx
 | 
						|
 | 
						|
	data32 lgdt (%ebx)
 | 
						|
 | 
						|
	movl	%cr0, %eax
 | 
						|
	andl	$(~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_NE | \
 | 
						|
		    X86_CR0_TS | X86_CR0_EM | X86_CR0_MP)), %eax
 | 
						|
	orl	$(X86_CR0_NW | X86_CR0_CD | X86_CR0_PE), %eax
 | 
						|
	movl	%eax, %cr0
 | 
						|
 | 
						|
	movl	$ap_start_jmp, %eax
 | 
						|
	subl	$ap_start16, %eax
 | 
						|
	movw	%ax, %bp
 | 
						|
 | 
						|
	/* Jump to ap_start within U-Boot */
 | 
						|
data32 cs	ljmp	*(%bp)
 | 
						|
 | 
						|
	.align	4
 | 
						|
.globl sipi_params_16bit
 | 
						|
sipi_params_16bit:
 | 
						|
	/* 48-bit far pointer */
 | 
						|
ap_start_jmp:
 | 
						|
	.long	0		/* offset set to ap_start by U-Boot */
 | 
						|
	.word	CODE_SEG	/* segment */
 | 
						|
 | 
						|
	.word	0		/* padding */
 | 
						|
gdtaddr:
 | 
						|
	.word	0 /* limit */
 | 
						|
	.long	0 /* table */
 | 
						|
	.word	0 /* unused */
 | 
						|
 | 
						|
.globl ap_start16_code_end
 | 
						|
ap_start16_code_end:
 | 
						|
 | 
						|
/*
 | 
						|
 * Set up the special 'fs' segment for global_data. Then jump to ap_continue
 | 
						|
 * to set up the AP.
 | 
						|
 */
 | 
						|
.globl ap_start
 | 
						|
ap_start:
 | 
						|
	.code32
 | 
						|
	movw	$DATA_SEG, %ax
 | 
						|
	movw	%ax, %ds
 | 
						|
	movw	%ax, %es
 | 
						|
	movw	%ax, %ss
 | 
						|
	movw	%ax, %gs
 | 
						|
 | 
						|
	movw	$(X86_GDT_ENTRY_32BIT_FS * X86_GDT_ENTRY_SIZE), %ax
 | 
						|
	movw	%ax, %fs
 | 
						|
 | 
						|
	/* Load the Interrupt descriptor table */
 | 
						|
	mov	idt_ptr, %ebx
 | 
						|
	lidt	(%ebx)
 | 
						|
 | 
						|
	/* Obtain cpu number */
 | 
						|
	movl	ap_count, %eax
 | 
						|
1:
 | 
						|
	movl	%eax, %ecx
 | 
						|
	inc	%ecx
 | 
						|
	lock cmpxchg %ecx, ap_count
 | 
						|
	jnz	1b
 | 
						|
 | 
						|
	/* Setup stacks for each CPU */
 | 
						|
	movl	stack_size, %eax
 | 
						|
	mul	%ecx
 | 
						|
	movl	stack_top, %edx
 | 
						|
	subl	%eax, %edx
 | 
						|
	mov	%edx, %esp
 | 
						|
	/* Save cpu number */
 | 
						|
	mov	%ecx, %esi
 | 
						|
 | 
						|
	/* Determine if one should check microcode versions */
 | 
						|
	mov	microcode_ptr, %edi
 | 
						|
	test	%edi, %edi
 | 
						|
	jz	microcode_done /* Bypass if no microde exists */
 | 
						|
 | 
						|
	/* Get the Microcode version */
 | 
						|
	mov	$1, %eax
 | 
						|
	cpuid
 | 
						|
	mov	$MSR_IA32_UCODE_REV, %ecx
 | 
						|
	rdmsr
 | 
						|
	/* If something already loaded skip loading again */
 | 
						|
	test	%edx, %edx
 | 
						|
	jnz	microcode_done
 | 
						|
 | 
						|
	/* Determine if parallel microcode loading is allowed */
 | 
						|
	cmpl	$0xffffffff, microcode_lock
 | 
						|
	je	load_microcode
 | 
						|
 | 
						|
	/* Protect microcode loading */
 | 
						|
lock_microcode:
 | 
						|
	lock btsl $0, microcode_lock
 | 
						|
	jc	lock_microcode
 | 
						|
 | 
						|
load_microcode:
 | 
						|
	/* Load new microcode */
 | 
						|
	mov	$MSR_IA32_UCODE_WRITE, %ecx
 | 
						|
	xor	%edx, %edx
 | 
						|
	mov	%edi, %eax
 | 
						|
	/*
 | 
						|
	 * The microcode pointer is passed in pointing to the header. Adjust
 | 
						|
	 * pointer to reflect the payload (header size is 48 bytes)
 | 
						|
	 */
 | 
						|
	add	$UCODE_HEADER_LEN, %eax
 | 
						|
	pusha
 | 
						|
	wrmsr
 | 
						|
	popa
 | 
						|
 | 
						|
	/* Unconditionally unlock microcode loading */
 | 
						|
	cmpl	$0xffffffff, microcode_lock
 | 
						|
	je	microcode_done
 | 
						|
 | 
						|
	xor	%eax, %eax
 | 
						|
	mov	%eax, microcode_lock
 | 
						|
 | 
						|
microcode_done:
 | 
						|
	/*
 | 
						|
	 * Load MSRs. Each entry in the table consists of:
 | 
						|
	 * 0: index,
 | 
						|
	 * 4: value[31:0]
 | 
						|
	 * 8: value[63:32]
 | 
						|
	 * See struct saved_msr in mp_init.c.
 | 
						|
	 */
 | 
						|
	mov	msr_table_ptr, %edi
 | 
						|
	mov	msr_count, %ebx
 | 
						|
	test	%ebx, %ebx
 | 
						|
	jz	1f
 | 
						|
load_msr:
 | 
						|
	mov	(%edi), %ecx
 | 
						|
	mov	4(%edi), %eax
 | 
						|
	mov	8(%edi), %edx
 | 
						|
	wrmsr
 | 
						|
	add	$12, %edi
 | 
						|
	dec	%ebx
 | 
						|
	jnz	load_msr
 | 
						|
 | 
						|
1:
 | 
						|
	/* Enable caching */
 | 
						|
	mov	%cr0, %eax
 | 
						|
	andl	$(~(X86_CR0_CD | X86_CR0_NW)), %eax
 | 
						|
	mov	%eax, %cr0
 | 
						|
 | 
						|
	/* c_handler(cpu_num) */
 | 
						|
	movl	%esi, %eax	/* cpu_num */
 | 
						|
	mov	c_handler, %esi
 | 
						|
	call	*%esi
 | 
						|
 | 
						|
	/* This matches struct sipi_param */
 | 
						|
	.align	4
 | 
						|
.globl	sipi_params
 | 
						|
sipi_params:
 | 
						|
idt_ptr:
 | 
						|
	.long 0
 | 
						|
stack_top:
 | 
						|
	.long 0
 | 
						|
stack_size:
 | 
						|
	.long 0
 | 
						|
microcode_lock:
 | 
						|
	.long 0
 | 
						|
microcode_ptr:
 | 
						|
	.long 0
 | 
						|
msr_table_ptr:
 | 
						|
	.long 0
 | 
						|
msr_count:
 | 
						|
	.long 0
 | 
						|
c_handler:
 | 
						|
	.long 0
 | 
						|
ap_count:
 | 
						|
	.long 0
 |