mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-02 13:44:00 +00:00
for bsp_boot_init/cpu_secondary_init, they are on temp stack. for bsp_boot_post/cpu_secondary_post, they are on runtime stack. define SWITCH_TO MACRO to switch runtime stack then jump to post functions. Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
226 lines
6.2 KiB
ArmAsm
226 lines
6.2 KiB
ArmAsm
/*
|
|
* Copyright (C) 2018 Intel Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <cpu.h>
|
|
#include <mmu.h>
|
|
#include <gdt.h>
|
|
#include <idt.h>
|
|
#include <msr.h>
|
|
|
|
/* NOTE:
|
|
*
|
|
* MISRA C requires that all unsigned constants should have the suffix 'U'
|
|
* (e.g. 0xffU), but the assembler may not accept such C-style constants. For
|
|
* example, binutils 2.26 fails to compile assembly in that case. To work this
|
|
* around, all unsigned constants must be explicitly spells out in assembly
|
|
* with a comment tracking the original expression from which the magic
|
|
* number is calculated. As an example:
|
|
*
|
|
* /* 0x00000668 =
|
|
* * (CR4_DE | CR4_PAE | CR4_MCE | CR4_OSFXSR | CR4_OSXMMEXCPT) *\/
|
|
* movl $0x00000668, %eax
|
|
*
|
|
* Make sure that these numbers are updated accordingly if the definition of
|
|
* the macros involved are changed.
|
|
*/
|
|
|
|
/* MULTIBOOT HEADER */
|
|
#define MULTIBOOT_HEADER_MAGIC 0x1badb002
|
|
#define MULTIBOOT_HEADER_FLAGS 0x00000002 /*flags bit 1 : enable mem_*, mmap_**/
|
|
|
|
.section multiboot_header, "a"
|
|
|
|
.align 4
|
|
|
|
/* header magic */
|
|
.long MULTIBOOT_HEADER_MAGIC
|
|
/* header flags - flags bit 6 : enable mmap_* */
|
|
.long MULTIBOOT_HEADER_FLAGS
|
|
/* header checksum = -(magic + flags) */
|
|
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
|
|
|
.section entry, "ax"
|
|
|
|
.align 8
|
|
.code32
|
|
|
|
.global cpu_primary_start_32
|
|
cpu_primary_start_32:
|
|
/* Disable interrupts */
|
|
cli
|
|
|
|
/* Clear direction flag */
|
|
cld
|
|
|
|
/* save eax and ebx */
|
|
movl %eax, %esp
|
|
movl %ebx, %ebp
|
|
|
|
/* detect whether it is in long mode
|
|
*
|
|
* 0xc0000080 = MSR_IA32_EFER
|
|
*/
|
|
movl $0xc0000080, %ecx
|
|
rdmsr
|
|
/* 0x400 = MSR_IA32_EFER_LMA_BIT */
|
|
test $0x400, %eax
|
|
|
|
/* jump to 64bit entry if it is already in long mode */
|
|
jne cpu_primary_start_64
|
|
|
|
/* save the MULTBOOT magic number & MBI */
|
|
movl %esp, (boot_regs)
|
|
movl %ebp, (boot_regs+4)
|
|
|
|
/* Disable paging */
|
|
mov %cr0, %ebx
|
|
/* 0x7fffffff = ~CR0_PG */
|
|
andl $0x7fffffff, %ebx
|
|
mov %ebx, %cr0
|
|
|
|
/* Set DE, PAE, MCE and OS support bits in CR4
|
|
* 0x00000668 =
|
|
* (CR4_DE | CR4_PAE | CR4_MCE | CR4_OSFXSR | CR4_OSXMMEXCPT) */
|
|
movl $0x00000668, %eax
|
|
mov %eax, %cr4
|
|
|
|
/* Set CR3 to PML4 table address */
|
|
movl $cpu_boot32_page_tables_start, %edi
|
|
mov %edi, %cr3
|
|
|
|
/* Set LME bit in EFER */
|
|
|
|
/* 0xc0000080 = MSR_IA32_EFER */
|
|
movl $0xc0000080, %ecx
|
|
rdmsr
|
|
/* 0x00000100 = MSR_IA32_EFER_LME_BIT */
|
|
orl $0x00000100, %eax
|
|
wrmsr
|
|
|
|
/* Enable paging, protection, numeric error and co-processor
|
|
monitoring in CR0 to enter long mode */
|
|
mov %cr0, %ebx
|
|
/* 0x80000023 = (CR0_PG | CR0_PE | CR0_MP | CR0_NE) */
|
|
orl $0x80000023, %ebx
|
|
mov %ebx, %cr0
|
|
|
|
/* Load temportary GDT pointer value */
|
|
mov $cpu_primary32_gdt_ptr, %ebx
|
|
lgdt (%ebx)
|
|
|
|
/* Perform a long jump based to start executing in 64-bit mode */
|
|
ljmp $HOST_GDT_RING0_CODE_SEL, $primary_start_long_mode
|
|
|
|
.code64
|
|
.org 0x200
|
|
.global cpu_primary_start_64
|
|
cpu_primary_start_64:
|
|
/* save the MULTBOOT magic number & MBI */
|
|
movl %edi, (boot_regs)
|
|
movl %esi, (boot_regs+4)
|
|
|
|
primary_start_long_mode:
|
|
|
|
/* Fix up the IDT desciptors */
|
|
movl $HOST_IDT, %edx
|
|
movl $HOST_IDT_ENTRIES, %ecx
|
|
.LFixUpIDT_Entries:
|
|
xorl %eax, %eax
|
|
xchgl %eax, 12(%edx) /* Set rsvd bits to 0; eax now has
|
|
high 32 of entry point */
|
|
xchgl %eax, 8(%edx) /* Set bits 63..32 of entry point;
|
|
eax now has low 32 of entry point */
|
|
movw %ax, (%edx) /* Set bits 0-15 of procedure entry
|
|
point */
|
|
shr $16, %eax
|
|
movw %ax, 6(%edx) /* Set bits 16-31 of entry point */
|
|
addl $X64_IDT_DESC_SIZE,%edx
|
|
loop .LFixUpIDT_Entries
|
|
|
|
/* Load IDT */
|
|
mov $HOST_IDTR, %rcx
|
|
lidtq (%rcx)
|
|
|
|
/* Load temportary GDT pointer value */
|
|
mov $cpu_primary32_gdt_ptr, %ebx
|
|
lgdt (%ebx)
|
|
|
|
/* Replace CS with the correct value should we need it */
|
|
mov $HOST_GDT_RING0_CODE_SEL, %bx
|
|
mov %bx, jcs
|
|
movabsq $jmpbuf, %rax
|
|
rex.w ljmp *(%rax)
|
|
.data
|
|
jmpbuf: .quad after
|
|
jcs: .word 0
|
|
.text
|
|
after:
|
|
|
|
/* Initialize temporary stack pointer */
|
|
movq $_ld_bss_end, %rsp
|
|
add $CPU_PAGE_SIZE,%rsp
|
|
/* 16 = CPU_STACK_ALIGN */
|
|
and $(~(16 - 1)),%rsp
|
|
|
|
// load all selector registers with appropriate values
|
|
xor %edx, %edx
|
|
lldt %dx
|
|
movl $HOST_GDT_RING0_DATA_SEL,%eax
|
|
mov %eax,%ss // Was 32bit POC Stack
|
|
mov %eax,%ds // Was 32bit POC Data
|
|
mov %eax,%es // Was 32bit POC Data
|
|
mov %edx,%fs // Was 32bit POC Data
|
|
mov %edx,%gs // Was 32bit POC CLS
|
|
|
|
/* continue with chipset level initialization */
|
|
call bsp_boot_init
|
|
|
|
loop:
|
|
jmp loop
|
|
|
|
.align 4
|
|
.global boot_regs
|
|
boot_regs:
|
|
.long 0x00000000
|
|
.long 0x00000000
|
|
|
|
/* GDT table */
|
|
.align 4
|
|
cpu_primary32_gdt:
|
|
.quad 0x0000000000000000
|
|
.quad 0x00af9b000000ffff
|
|
.quad 0x00cf93000000ffff
|
|
cpu_primary32_gdt_end:
|
|
|
|
/* GDT pointer */
|
|
.align 2
|
|
cpu_primary32_gdt_ptr:
|
|
.short (cpu_primary32_gdt_end - cpu_primary32_gdt) - 1
|
|
.quad cpu_primary32_gdt
|
|
|
|
/* PML4, PDPT, and PD tables initialized to map first 4 GBytes of memory */
|
|
.align CPU_PAGE_SIZE
|
|
.global cpu_boot32_page_tables_start
|
|
cpu_boot32_page_tables_start:
|
|
/* 0x3 = (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT) */
|
|
.quad cpu_primary32_pdpt_addr + 0x3
|
|
.align CPU_PAGE_SIZE
|
|
cpu_primary32_pdpt_addr:
|
|
address = 0
|
|
.rept 4
|
|
/* 0x3 = (IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT) */
|
|
.quad cpu_primary32_pdt_addr + address + 0x3
|
|
address = address + CPU_PAGE_SIZE
|
|
.endr
|
|
.align CPU_PAGE_SIZE
|
|
cpu_primary32_pdt_addr:
|
|
address = 0
|
|
.rept 2048
|
|
/* 0x83 = (IA32E_PDPTE_PS_BIT | IA32E_COMM_P_BIT | IA32E_COMM_RW_BIT) */
|
|
.quad address + 0x83
|
|
address = address + 0x200000
|
|
.endr
|