Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 /*
0004  * Copyright C 2016, Oracle and/or its affiliates. All rights reserved.
0005  */
0006 
0007     .code32
0008     .text
0009 #define _pa(x)          ((x) - __START_KERNEL_map)
0010 
0011 #include <linux/elfnote.h>
0012 #include <linux/init.h>
0013 #include <linux/linkage.h>
0014 #include <asm/segment.h>
0015 #include <asm/asm.h>
0016 #include <asm/boot.h>
0017 #include <asm/processor-flags.h>
0018 #include <asm/msr.h>
0019 #include <asm/nospec-branch.h>
0020 #include <xen/interface/elfnote.h>
0021 
0022     __HEAD
0023 
0024 /*
0025  * Entry point for PVH guests.
0026  *
0027  * Xen ABI specifies the following register state when we come here:
0028  *
0029  * - `ebx`: contains the physical memory address where the loader has placed
0030  *          the boot start info structure.
0031  * - `cr0`: bit 0 (PE) must be set. All the other writeable bits are cleared.
0032  * - `cr4`: all bits are cleared.
0033  * - `cs `: must be a 32-bit read/execute code segment with a base of `0`
0034  *          and a limit of `0xFFFFFFFF`. The selector value is unspecified.
0035  * - `ds`, `es`: must be a 32-bit read/write data segment with a base of
0036  *               `0` and a limit of `0xFFFFFFFF`. The selector values are all
0037  *               unspecified.
0038  * - `tr`: must be a 32-bit TSS (active) with a base of '0' and a limit
0039  *         of '0x67'.
0040  * - `eflags`: bit 17 (VM) must be cleared. Bit 9 (IF) must be cleared.
0041  *             Bit 8 (TF) must be cleared. Other bits are all unspecified.
0042  *
0043  * All other processor registers and flag bits are unspecified. The OS is in
0044  * charge of setting up it's own stack, GDT and IDT.
0045  */
0046 
0047 #define PVH_GDT_ENTRY_CS    1
0048 #define PVH_GDT_ENTRY_DS    2
0049 #define PVH_CS_SEL      (PVH_GDT_ENTRY_CS * 8)
0050 #define PVH_DS_SEL      (PVH_GDT_ENTRY_DS * 8)
0051 
0052 SYM_CODE_START_LOCAL(pvh_start_xen)
0053     UNWIND_HINT_EMPTY
0054     cld
0055 
0056     lgdt (_pa(gdt))
0057 
0058     mov $PVH_DS_SEL,%eax
0059     mov %eax,%ds
0060     mov %eax,%es
0061     mov %eax,%ss
0062 
0063     /* Stash hvm_start_info. */
0064     mov $_pa(pvh_start_info), %edi
0065     mov %ebx, %esi
0066     mov _pa(pvh_start_info_sz), %ecx
0067     shr $2,%ecx
0068     rep
0069     movsl
0070 
0071     mov $_pa(early_stack_end), %esp
0072 
0073     /* Enable PAE mode. */
0074     mov %cr4, %eax
0075     orl $X86_CR4_PAE, %eax
0076     mov %eax, %cr4
0077 
0078 #ifdef CONFIG_X86_64
0079     /* Enable Long mode. */
0080     mov $MSR_EFER, %ecx
0081     rdmsr
0082     btsl $_EFER_LME, %eax
0083     wrmsr
0084 
0085     /* Enable pre-constructed page tables. */
0086     mov $_pa(init_top_pgt), %eax
0087     mov %eax, %cr3
0088     mov $(X86_CR0_PG | X86_CR0_PE), %eax
0089     mov %eax, %cr0
0090 
0091     /* Jump to 64-bit mode. */
0092     ljmp $PVH_CS_SEL, $_pa(1f)
0093 
0094     /* 64-bit entry point. */
0095     .code64
0096 1:
0097     /* Set base address in stack canary descriptor. */
0098     mov $MSR_GS_BASE,%ecx
0099     mov $_pa(canary), %eax
0100     xor %edx, %edx
0101     wrmsr
0102 
0103     call xen_prepare_pvh
0104 
0105     /* startup_64 expects boot_params in %rsi. */
0106     mov $_pa(pvh_bootparams), %rsi
0107     mov $_pa(startup_64), %rax
0108     ANNOTATE_RETPOLINE_SAFE
0109     jmp *%rax
0110 
0111 #else /* CONFIG_X86_64 */
0112 
0113     call mk_early_pgtbl_32
0114 
0115     mov $_pa(initial_page_table), %eax
0116     mov %eax, %cr3
0117 
0118     mov %cr0, %eax
0119     or $(X86_CR0_PG | X86_CR0_PE), %eax
0120     mov %eax, %cr0
0121 
0122     ljmp $PVH_CS_SEL, $1f
0123 1:
0124     call xen_prepare_pvh
0125     mov $_pa(pvh_bootparams), %esi
0126 
0127     /* startup_32 doesn't expect paging and PAE to be on. */
0128     ljmp $PVH_CS_SEL, $_pa(2f)
0129 2:
0130     mov %cr0, %eax
0131     and $~X86_CR0_PG, %eax
0132     mov %eax, %cr0
0133     mov %cr4, %eax
0134     and $~X86_CR4_PAE, %eax
0135     mov %eax, %cr4
0136 
0137     ljmp $PVH_CS_SEL, $_pa(startup_32)
0138 #endif
0139 SYM_CODE_END(pvh_start_xen)
0140 
0141     .section ".init.data","aw"
0142     .balign 8
0143 SYM_DATA_START_LOCAL(gdt)
0144     .word gdt_end - gdt_start
0145     .long _pa(gdt_start)
0146     .word 0
0147 SYM_DATA_END(gdt)
0148 SYM_DATA_START_LOCAL(gdt_start)
0149     .quad 0x0000000000000000            /* NULL descriptor */
0150 #ifdef CONFIG_X86_64
0151     .quad GDT_ENTRY(0xa09a, 0, 0xfffff) /* PVH_CS_SEL */
0152 #else
0153     .quad GDT_ENTRY(0xc09a, 0, 0xfffff) /* PVH_CS_SEL */
0154 #endif
0155     .quad GDT_ENTRY(0xc092, 0, 0xfffff) /* PVH_DS_SEL */
0156 SYM_DATA_END_LABEL(gdt_start, SYM_L_LOCAL, gdt_end)
0157 
0158     .balign 16
0159 SYM_DATA_LOCAL(canary, .fill 48, 1, 0)
0160 
0161 SYM_DATA_START_LOCAL(early_stack)
0162     .fill BOOT_STACK_SIZE, 1, 0
0163 SYM_DATA_END_LABEL(early_stack, SYM_L_LOCAL, early_stack_end)
0164 
0165     ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY,
0166                  _ASM_PTR (pvh_start_xen - __START_KERNEL_map))