root/arch/x86/platform/pvh/head.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 
   3 /*
   4  * Copyright C 2016, Oracle and/or its affiliates. All rights reserved.
   5  */
   6 
   7         .code32
   8         .text
   9 #define _pa(x)          ((x) - __START_KERNEL_map)
  10 
  11 #include <linux/elfnote.h>
  12 #include <linux/init.h>
  13 #include <linux/linkage.h>
  14 #include <asm/segment.h>
  15 #include <asm/asm.h>
  16 #include <asm/boot.h>
  17 #include <asm/processor-flags.h>
  18 #include <asm/msr.h>
  19 #include <xen/interface/elfnote.h>
  20 
  21         __HEAD
  22 
  23 /*
  24  * Entry point for PVH guests.
  25  *
  26  * Xen ABI specifies the following register state when we come here:
  27  *
  28  * - `ebx`: contains the physical memory address where the loader has placed
  29  *          the boot start info structure.
  30  * - `cr0`: bit 0 (PE) must be set. All the other writeable bits are cleared.
  31  * - `cr4`: all bits are cleared.
  32  * - `cs `: must be a 32-bit read/execute code segment with a base of ‘0’
  33  *          and a limit of ‘0xFFFFFFFF’. The selector value is unspecified.
  34  * - `ds`, `es`: must be a 32-bit read/write data segment with a base of
  35  *               ‘0’ and a limit of ‘0xFFFFFFFF’. The selector values are all
  36  *               unspecified.
  37  * - `tr`: must be a 32-bit TSS (active) with a base of '0' and a limit
  38  *         of '0x67'.
  39  * - `eflags`: bit 17 (VM) must be cleared. Bit 9 (IF) must be cleared.
  40  *             Bit 8 (TF) must be cleared. Other bits are all unspecified.
  41  *
  42  * All other processor registers and flag bits are unspecified. The OS is in
  43  * charge of setting up it's own stack, GDT and IDT.
  44  */
  45 
  46 #define PVH_GDT_ENTRY_CS        1
  47 #define PVH_GDT_ENTRY_DS        2
  48 #define PVH_GDT_ENTRY_CANARY    3
  49 #define PVH_CS_SEL              (PVH_GDT_ENTRY_CS * 8)
  50 #define PVH_DS_SEL              (PVH_GDT_ENTRY_DS * 8)
  51 #define PVH_CANARY_SEL          (PVH_GDT_ENTRY_CANARY * 8)
  52 
  53 ENTRY(pvh_start_xen)
  54         cld
  55 
  56         lgdt (_pa(gdt))
  57 
  58         mov $PVH_DS_SEL,%eax
  59         mov %eax,%ds
  60         mov %eax,%es
  61         mov %eax,%ss
  62 
  63         /* Stash hvm_start_info. */
  64         mov $_pa(pvh_start_info), %edi
  65         mov %ebx, %esi
  66         mov _pa(pvh_start_info_sz), %ecx
  67         shr $2,%ecx
  68         rep
  69         movsl
  70 
  71         mov $_pa(early_stack_end), %esp
  72 
  73         /* Enable PAE mode. */
  74         mov %cr4, %eax
  75         orl $X86_CR4_PAE, %eax
  76         mov %eax, %cr4
  77 
  78 #ifdef CONFIG_X86_64
  79         /* Enable Long mode. */
  80         mov $MSR_EFER, %ecx
  81         rdmsr
  82         btsl $_EFER_LME, %eax
  83         wrmsr
  84 
  85         /* Enable pre-constructed page tables. */
  86         mov $_pa(init_top_pgt), %eax
  87         mov %eax, %cr3
  88         mov $(X86_CR0_PG | X86_CR0_PE), %eax
  89         mov %eax, %cr0
  90 
  91         /* Jump to 64-bit mode. */
  92         ljmp $PVH_CS_SEL, $_pa(1f)
  93 
  94         /* 64-bit entry point. */
  95         .code64
  96 1:
  97         /* Set base address in stack canary descriptor. */
  98         mov $MSR_GS_BASE,%ecx
  99         mov $_pa(canary), %eax
 100         xor %edx, %edx
 101         wrmsr
 102 
 103         call xen_prepare_pvh
 104 
 105         /* startup_64 expects boot_params in %rsi. */
 106         mov $_pa(pvh_bootparams), %rsi
 107         mov $_pa(startup_64), %rax
 108         jmp *%rax
 109 
 110 #else /* CONFIG_X86_64 */
 111 
 112         /* Set base address in stack canary descriptor. */
 113         movl $_pa(gdt_start),%eax
 114         movl $_pa(canary),%ecx
 115         movw %cx, (PVH_GDT_ENTRY_CANARY * 8) + 2(%eax)
 116         shrl $16, %ecx
 117         movb %cl, (PVH_GDT_ENTRY_CANARY * 8) + 4(%eax)
 118         movb %ch, (PVH_GDT_ENTRY_CANARY * 8) + 7(%eax)
 119 
 120         mov $PVH_CANARY_SEL,%eax
 121         mov %eax,%gs
 122 
 123         call mk_early_pgtbl_32
 124 
 125         mov $_pa(initial_page_table), %eax
 126         mov %eax, %cr3
 127 
 128         mov %cr0, %eax
 129         or $(X86_CR0_PG | X86_CR0_PE), %eax
 130         mov %eax, %cr0
 131 
 132         ljmp $PVH_CS_SEL, $1f
 133 1:
 134         call xen_prepare_pvh
 135         mov $_pa(pvh_bootparams), %esi
 136 
 137         /* startup_32 doesn't expect paging and PAE to be on. */
 138         ljmp $PVH_CS_SEL, $_pa(2f)
 139 2:
 140         mov %cr0, %eax
 141         and $~X86_CR0_PG, %eax
 142         mov %eax, %cr0
 143         mov %cr4, %eax
 144         and $~X86_CR4_PAE, %eax
 145         mov %eax, %cr4
 146 
 147         ljmp $PVH_CS_SEL, $_pa(startup_32)
 148 #endif
 149 END(pvh_start_xen)
 150 
 151         .section ".init.data","aw"
 152         .balign 8
 153 gdt:
 154         .word gdt_end - gdt_start
 155         .long _pa(gdt_start)
 156         .word 0
 157 gdt_start:
 158         .quad 0x0000000000000000            /* NULL descriptor */
 159 #ifdef CONFIG_X86_64
 160         .quad GDT_ENTRY(0xa09a, 0, 0xfffff) /* PVH_CS_SEL */
 161 #else
 162         .quad GDT_ENTRY(0xc09a, 0, 0xfffff) /* PVH_CS_SEL */
 163 #endif
 164         .quad GDT_ENTRY(0xc092, 0, 0xfffff) /* PVH_DS_SEL */
 165         .quad GDT_ENTRY(0x4090, 0, 0x18)    /* PVH_CANARY_SEL */
 166 gdt_end:
 167 
 168         .balign 16
 169 canary:
 170         .fill 48, 1, 0
 171 
 172 early_stack:
 173         .fill BOOT_STACK_SIZE, 1, 0
 174 early_stack_end:
 175 
 176         ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY,
 177                      _ASM_PTR (pvh_start_xen - __START_KERNEL_map))

/* [<][>][^][v][top][bottom][index][help] */