2018-03-07 20:57:14 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 Intel Corporation. All rights reserved.
|
|
|
|
*
|
2018-05-26 01:49:13 +08:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2018-03-07 20:57:14 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <cpu.h>
|
|
|
|
#include <mmu.h>
|
|
|
|
#include <gdt.h>
|
|
|
|
#include <idt.h>
|
|
|
|
#include <msr.h>
|
|
|
|
|
2018-06-22 22:50:58 +08:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
2018-03-07 20:57:14 +08:00
|
|
|
/* MULTIBOOT HEADER */
|
|
|
|
#define MULTIBOOT_HEADER_MAGIC 0x1badb002
|
|
|
|
#define MULTIBOOT_HEADER_FLAGS 0x00000002 /*flags bit 1 : enable mem_*, mmap_**/
|
|
|
|
|
2018-07-28 13:50:58 +08:00
|
|
|
.extern cpu_primary_save32
|
|
|
|
.extern cpu_primary_save64
|
2018-03-07 20:57:14 +08:00
|
|
|
.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:
|
2018-07-28 13:50:58 +08:00
|
|
|
/* save the MULTBOOT magic number & MBI */
|
|
|
|
movl %eax, (boot_regs)
|
|
|
|
movl %ebx, (boot_regs+4)
|
|
|
|
|
|
|
|
/* Save boot context from 32bit mode */
|
|
|
|
call cpu_primary_save_32
|
|
|
|
|
2018-03-07 20:57:14 +08:00
|
|
|
/* Disable interrupts */
|
|
|
|
cli
|
|
|
|
|
|
|
|
/* Clear direction flag */
|
|
|
|
cld
|
|
|
|
|
2018-06-22 22:50:58 +08:00
|
|
|
/* detect whether it is in long mode
|
|
|
|
*
|
|
|
|
* 0xc0000080 = MSR_IA32_EFER
|
|
|
|
*/
|
|
|
|
movl $0xc0000080, %ecx
|
2018-03-07 20:57:14 +08:00
|
|
|
rdmsr
|
2018-06-22 22:50:58 +08:00
|
|
|
/* 0x400 = MSR_IA32_EFER_LMA_BIT */
|
|
|
|
test $0x400, %eax
|
2018-03-07 20:57:14 +08:00
|
|
|
|
|
|
|
/* jump to 64bit entry if it is already in long mode */
|
|
|
|
jne cpu_primary_start_64
|
|
|
|
|
|
|
|
/* Disable paging */
|
|
|
|
mov %cr0, %ebx
|
2018-06-22 22:50:58 +08:00
|
|
|
/* 0x7fffffff = ~CR0_PG */
|
|
|
|
andl $0x7fffffff, %ebx
|
2018-03-07 20:57:14 +08:00
|
|
|
mov %ebx, %cr0
|
|
|
|
|
2018-06-22 22:50:58 +08:00
|
|
|
/* Set DE, PAE, MCE and OS support bits in CR4
|
|
|
|
* 0x00000668 =
|
|
|
|
* (CR4_DE | CR4_PAE | CR4_MCE | CR4_OSFXSR | CR4_OSXMMEXCPT) */
|
|
|
|
movl $0x00000668, %eax
|
2018-03-07 20:57:14 +08:00
|
|
|
mov %eax, %cr4
|
|
|
|
|
|
|
|
/* Set CR3 to PML4 table address */
|
|
|
|
movl $cpu_boot32_page_tables_start, %edi
|
|
|
|
mov %edi, %cr3
|
|
|
|
|
|
|
|
/* Set LME bit in EFER */
|
2018-06-22 22:50:58 +08:00
|
|
|
|
|
|
|
/* 0xc0000080 = MSR_IA32_EFER */
|
|
|
|
movl $0xc0000080, %ecx
|
2018-03-07 20:57:14 +08:00
|
|
|
rdmsr
|
2018-06-22 22:50:58 +08:00
|
|
|
/* 0x00000100 = MSR_IA32_EFER_LME_BIT */
|
|
|
|
orl $0x00000100, %eax
|
2018-03-07 20:57:14 +08:00
|
|
|
wrmsr
|
|
|
|
|
|
|
|
/* Enable paging, protection, numeric error and co-processor
|
|
|
|
monitoring in CR0 to enter long mode */
|
|
|
|
mov %cr0, %ebx
|
2018-06-22 22:50:58 +08:00
|
|
|
/* 0x80000023 = (CR0_PG | CR0_PE | CR0_MP | CR0_NE) */
|
|
|
|
orl $0x80000023, %ebx
|
2018-03-07 20:57:14 +08:00
|
|
|
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 */
|
2018-07-13 16:27:30 +08:00
|
|
|
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
|
|
|
ljmp $0x0008, $primary_start_long_mode
|
2018-03-07 20:57:14 +08:00
|
|
|
|
|
|
|
.code64
|
|
|
|
.org 0x200
|
|
|
|
.global cpu_primary_start_64
|
|
|
|
cpu_primary_start_64:
|
|
|
|
/* save the MULTBOOT magic number & MBI */
|
2018-06-23 01:02:22 +08:00
|
|
|
lea boot_regs(%rip), %rax
|
|
|
|
movl %edi, (%rax)
|
|
|
|
movl %esi, 4(%rax)
|
2018-03-07 20:57:14 +08:00
|
|
|
|
2018-07-28 13:50:58 +08:00
|
|
|
/* Save boot context from 64bit mode */
|
|
|
|
call cpu_primary_save_64
|
|
|
|
|
2018-03-07 20:57:14 +08:00
|
|
|
primary_start_long_mode:
|
|
|
|
|
2018-06-23 01:02:22 +08:00
|
|
|
/* Initialize temporary stack pointer */
|
|
|
|
lea _ld_bss_end(%rip), %rsp
|
HV:treewide:Add 16-bit atomic operations and update vpid type
There are some integer type conversions reported by static
analysis tool for vcpu id, number of created vcpus, and
vpid, to reduce these type conversions, redesign vcpu id,
number of created vcpus, and vpid type as uint16_t as per
their usage, related 16-bit atomic operations shall be
added in HV.
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.
Add 16-bit atomic add/dec/store operations;
Update temporary variables type and parameters type of
related caller;
Update vpid type as uint16_t;
Replace Macro with constant value for CPU_PAGE_SIZE.
Note: According to SDM A.10, there are some bits defined
in the IA32_VMX_EPT_VPID_CAP MSR to support the INVVPID
instruction, these bits don't mean actual VPID, so
the vpid field in the data struct vmx_capability doesn't
be updated.
V1--V2:
update comments for assembly code as per coding style;
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
2018-07-11 11:09:10 +08:00
|
|
|
/*0x1000 = CPU_PAGE_SIZE*/
|
|
|
|
add $0x1000,%rsp
|
2018-06-23 01:02:22 +08:00
|
|
|
/* 16 = CPU_STACK_ALIGN */
|
|
|
|
and $(~(16 - 1)),%rsp
|
2018-03-07 20:57:14 +08:00
|
|
|
|
2018-06-23 01:02:22 +08:00
|
|
|
/*
|
|
|
|
* Fix up the .rela sections
|
|
|
|
* Notes: this includes the fixup to IDT tables and temporary
|
|
|
|
* page tables
|
|
|
|
*/
|
2018-06-23 01:25:24 +08:00
|
|
|
call _relocate
|
2018-03-07 20:57:14 +08:00
|
|
|
|
|
|
|
/* Load temportary GDT pointer value */
|
2018-06-23 01:02:22 +08:00
|
|
|
lea cpu_primary32_gdt_ptr(%rip), %rbx
|
2018-03-07 20:57:14 +08:00
|
|
|
lgdt (%ebx)
|
|
|
|
|
2018-06-23 01:02:22 +08:00
|
|
|
/* Set the correct long jump address */
|
|
|
|
lea jmpbuf(%rip), %rax
|
|
|
|
lea after(%rip), %rbx
|
|
|
|
mov %rbx, (%rax)
|
2018-03-07 20:57:14 +08:00
|
|
|
rex.w ljmp *(%rax)
|
|
|
|
.data
|
2018-06-23 01:02:22 +08:00
|
|
|
jmpbuf: .quad 0
|
2018-07-13 16:27:30 +08:00
|
|
|
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
|
|
|
.word 0x0008
|
2018-03-07 20:57:14 +08:00
|
|
|
.text
|
|
|
|
after:
|
|
|
|
// load all selector registers with appropriate values
|
|
|
|
xor %edx, %edx
|
|
|
|
lldt %dx
|
2018-07-13 16:27:30 +08:00
|
|
|
/* 0x10 = HOST_GDT_RING0_DATA_SEL*/
|
|
|
|
movl $0x10,%eax
|
2018-03-07 20:57:14 +08:00
|
|
|
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
|
|
|
|
|
2018-06-23 01:02:22 +08:00
|
|
|
/*
|
|
|
|
* Fix up the IDT desciptors
|
|
|
|
* The relocation delta in IDT tables has been fixed in _relocate()
|
|
|
|
*/
|
|
|
|
leal HOST_IDT(%rip), %edx
|
|
|
|
movl $HOST_IDT_ENTRIES, %ecx
|
|
|
|
|
|
|
|
.fixup_idt_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 .fixup_idt_entries
|
|
|
|
|
|
|
|
/* Load IDT */
|
|
|
|
lea HOST_IDTR(%rip), %rbx
|
|
|
|
lidtq (%rbx)
|
|
|
|
|
2018-03-07 20:57:14 +08:00
|
|
|
/* 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 */
|
HV:treewide:Add 16-bit atomic operations and update vpid type
There are some integer type conversions reported by static
analysis tool for vcpu id, number of created vcpus, and
vpid, to reduce these type conversions, redesign vcpu id,
number of created vcpus, and vpid type as uint16_t as per
their usage, related 16-bit atomic operations shall be
added in HV.
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.
Add 16-bit atomic add/dec/store operations;
Update temporary variables type and parameters type of
related caller;
Update vpid type as uint16_t;
Replace Macro with constant value for CPU_PAGE_SIZE.
Note: According to SDM A.10, there are some bits defined
in the IA32_VMX_EPT_VPID_CAP MSR to support the INVVPID
instruction, these bits don't mean actual VPID, so
the vpid field in the data struct vmx_capability doesn't
be updated.
V1--V2:
update comments for assembly code as per coding style;
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
2018-07-11 11:09:10 +08:00
|
|
|
/*0x1000 = CPU_PAGE_SIZE*/
|
|
|
|
.align 0x1000
|
2018-03-07 20:57:14 +08:00
|
|
|
.global cpu_boot32_page_tables_start
|
|
|
|
cpu_boot32_page_tables_start:
|
2018-08-23 16:11:17 +08:00
|
|
|
/* 0x3 = (PAGE_PRESENT | PAGE_RW) */
|
2018-06-22 22:50:58 +08:00
|
|
|
.quad cpu_primary32_pdpt_addr + 0x3
|
HV:treewide:Add 16-bit atomic operations and update vpid type
There are some integer type conversions reported by static
analysis tool for vcpu id, number of created vcpus, and
vpid, to reduce these type conversions, redesign vcpu id,
number of created vcpus, and vpid type as uint16_t as per
their usage, related 16-bit atomic operations shall be
added in HV.
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.
Add 16-bit atomic add/dec/store operations;
Update temporary variables type and parameters type of
related caller;
Update vpid type as uint16_t;
Replace Macro with constant value for CPU_PAGE_SIZE.
Note: According to SDM A.10, there are some bits defined
in the IA32_VMX_EPT_VPID_CAP MSR to support the INVVPID
instruction, these bits don't mean actual VPID, so
the vpid field in the data struct vmx_capability doesn't
be updated.
V1--V2:
update comments for assembly code as per coding style;
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
2018-07-11 11:09:10 +08:00
|
|
|
/*0x1000 = CPU_PAGE_SIZE*/
|
|
|
|
.align 0x1000
|
2018-03-07 20:57:14 +08:00
|
|
|
cpu_primary32_pdpt_addr:
|
|
|
|
address = 0
|
|
|
|
.rept 4
|
2018-08-23 16:11:17 +08:00
|
|
|
/* 0x3 = (PAGE_PRESENT | PAGE_RW) */
|
2018-06-22 22:50:58 +08:00
|
|
|
.quad cpu_primary32_pdt_addr + address + 0x3
|
HV:treewide:Add 16-bit atomic operations and update vpid type
There are some integer type conversions reported by static
analysis tool for vcpu id, number of created vcpus, and
vpid, to reduce these type conversions, redesign vcpu id,
number of created vcpus, and vpid type as uint16_t as per
their usage, related 16-bit atomic operations shall be
added in HV.
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.
Add 16-bit atomic add/dec/store operations;
Update temporary variables type and parameters type of
related caller;
Update vpid type as uint16_t;
Replace Macro with constant value for CPU_PAGE_SIZE.
Note: According to SDM A.10, there are some bits defined
in the IA32_VMX_EPT_VPID_CAP MSR to support the INVVPID
instruction, these bits don't mean actual VPID, so
the vpid field in the data struct vmx_capability doesn't
be updated.
V1--V2:
update comments for assembly code as per coding style;
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
2018-07-11 11:09:10 +08:00
|
|
|
/*0x1000 = CPU_PAGE_SIZE*/
|
|
|
|
address = address + 0x1000
|
2018-03-07 20:57:14 +08:00
|
|
|
.endr
|
HV:treewide:Add 16-bit atomic operations and update vpid type
There are some integer type conversions reported by static
analysis tool for vcpu id, number of created vcpus, and
vpid, to reduce these type conversions, redesign vcpu id,
number of created vcpus, and vpid type as uint16_t as per
their usage, related 16-bit atomic operations shall be
added in HV.
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.
Add 16-bit atomic add/dec/store operations;
Update temporary variables type and parameters type of
related caller;
Update vpid type as uint16_t;
Replace Macro with constant value for CPU_PAGE_SIZE.
Note: According to SDM A.10, there are some bits defined
in the IA32_VMX_EPT_VPID_CAP MSR to support the INVVPID
instruction, these bits don't mean actual VPID, so
the vpid field in the data struct vmx_capability doesn't
be updated.
V1--V2:
update comments for assembly code as per coding style;
Signed-off-by: Xiangyang Wu <xiangyang.wu@intel.com>
2018-07-11 11:09:10 +08:00
|
|
|
/*0x1000 = CPU_PAGE_SIZE*/
|
|
|
|
.align 0x1000
|
2018-03-07 20:57:14 +08:00
|
|
|
cpu_primary32_pdt_addr:
|
|
|
|
address = 0
|
|
|
|
.rept 2048
|
2018-08-23 16:11:17 +08:00
|
|
|
/* 0x83 = (PAGE_PSE | PAGE_PRESENT | PAGE_RW) */
|
2018-06-22 22:50:58 +08:00
|
|
|
.quad address + 0x83
|
2018-03-07 20:57:14 +08:00
|
|
|
address = address + 0x200000
|
|
|
|
.endr
|