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