1/*- 2 * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org> 3 * Copyright (c) 2011-2012 Spectra Logic Corporation 4 * Copyright (c) 2013 Roger Pau Monne <royger@FreeBSD.org> 5 * All rights reserved. 6 * 7 * This software was developed by Cherry G. Mathew <cherry@zyx.in> 8 * under sponsorship from Spectra Logic Corporation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34#include <machine/asmacros.h> 35#include <machine/psl.h> 36#include <machine/pmap.h> 37#include <machine/specialreg.h> 38 39#include <xen/xen-os.h> 40#define __ASSEMBLY__ 41#include <xen/interface/elfnote.h> 42 43#include "assym.inc" 44 45#define VTOP(x) ((x) - KERNBASE) 46#define ENTRY_SIZE 8 /* sizeof(uint64_t) */ 47 48#define GDT_CODE 0x08 49#define GDT_DATA 0x10 50 51.section __xen_guest 52 ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz, "FreeBSD") 53 ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz, __XSTRING(__FreeBSD_version)) 54 ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz, "xen-3.0") 55 ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, .quad, KERNBASE) 56 ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, .quad, 0) 57 ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .quad, xen_start) 58 ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad, hypercall_page) 59 ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, .quad, HYPERVISOR_VIRT_START) 60 ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_descriptor_tables|auto_translated_physmap|supervisor_mode_kernel|hvm_callback_vector") 61 ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "yes") 62 ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .long, PG_V, PG_V) 63 ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") 64 ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 0) 65 ELFNOTE(Xen, XEN_ELFNOTE_BSD_SYMTAB, .asciz, "yes") 66 /* For PVHv2 support. */ 67 ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long, VTOP(xen_start32)) 68 69 .text 70.p2align PAGE_SHIFT, 0x90 /* Hypercall_page needs to be PAGE aligned */ 71 72NON_GPROF_ENTRY(hypercall_page) 73 .skip 0x1000, 0x90 /* Fill with "nop"s */ 74 75/* Legacy PVH entry point, to be removed. */ 76NON_GPROF_ENTRY(xen_start) 77 /* Don't trust what the loader gives for rflags. */ 78 pushq $PSL_KERNEL 79 popfq 80 81 /* Parameters for the xen init function */ 82 movq %rsi, %rdi /* shared_info (arg 1) */ 83 movq %rsp, %rsi /* xenstack (arg 2) */ 84 85 /* Use our own stack */ 86 movq $bootstack,%rsp 87 xorl %ebp, %ebp 88 89 /* u_int64_t hammer_time_xen(start_info_t *si, u_int64_t xenstack); */ 90 call hammer_time_xen_legacy 91 movq %rax, %rsp /* set up kstack for mi_startup() */ 92 call mi_startup /* autoconfiguration, mountroot etc */ 93 94 /* NOTREACHED */ 950: hlt 96 jmp 0b 97 98/* PVH entry point. */ 99 .code32 100NON_GPROF_ENTRY(xen_start32) 101 102 /* Load flat GDT */ 103 movl $VTOP(gdtdesc32), %eax 104 lgdt (%eax) 105 jmp $GDT_CODE, $VTOP(reload_cs) 106 107reload_cs: 108 movw $GDT_DATA, %ax 109 movw %ax, %ds 110 movw %ax, %es 111 movw %ax, %ss 112 113 movl $VTOP(bootstack), %esp 114 115 /* Don't trust what the loader gives for eflags. */ 116 pushl $PSL_KERNEL 117 popfl 118 119 /* 120 * Create the page tables. 121 * The first 1GB is mapped using 2MB entries. 122 */ 123 movl $0, %eax 124pgbuild: 125 cmp $(PAGE_SIZE/ENTRY_SIZE), %eax 126 jae pgbuild_done 127 128 /* PT4[i] = VTOP(&PT3[0]) | PG_V | PG_RW | PG_U */ 129 movl $VTOP(PT4), %ecx 130 movl $VTOP(PT3), %edx 131 orl $(PG_V | PG_RW | PG_U), %edx 132 movl %edx, (%ecx,%eax,ENTRY_SIZE) 133 134 /* PT3[i] = VTOP(&PT2[0]) | PG_V | PG_RW | PG_U */ 135 movl $VTOP(PT3), %ecx 136 movl $VTOP(PT2), %edx 137 orl $(PG_V | PG_RW | PG_U), %edx 138 movl %edx, (%ecx,%eax,ENTRY_SIZE) 139 140 /* PT2[i] = i * 2MiB | PG_V | PG_RW | PG_PS | PG_U */ 141 movl $VTOP(PT2), %ecx 142 movl %eax, %edx 143 shll $PDRSHIFT, %edx 144 orl $(PG_V | PG_RW | PG_PS | PG_U), %edx 145 movl %edx, (%ecx,%eax,ENTRY_SIZE) 146 147 inc %eax 148 jmp pgbuild 149 150pgbuild_done: 151 /* Turn on EFER.LME */ 152 movl $MSR_EFER, %ecx 153 rdmsr 154 orl $EFER_LME, %eax 155 wrmsr 156 157 /* Turn on PAE */ 158 movl %cr4, %eax 159 orl $CR4_PAE, %eax 160 movl %eax, %cr4 161 162 /* Set %cr3 for PT4 */ 163 movl $VTOP(PT4), %eax 164 movl %eax, %cr3 165 166 /* Turn on paging (implicitly sets EFER.LMA) */ 167 movl %cr0, %eax 168 orl $CR0_PG, %eax 169 movl %eax, %cr0 170 171 /* Now we're in compatibility mode. Set %cs for long mode */ 172 movl $VTOP(gdtdesc), %eax 173 lgdt (%eax) 174 ljmp $GDT_CODE, $VTOP(longmode) 175 176 .code64 177longmode: 178 /* We're still running V=P, jump to entry point */ 179 movq $bootstack, %rsp 180 movq $start_kernel, %rax 181 pushq %rax 182 ret 183 184start_kernel: 185 /* 186 * Pass %ebx as the argument to hammer_time_xen, it contains 187 * the startup info. 188 */ 189 movq %rbx, %rdi 190 call hammer_time_xen 191 movq %rax, %rsp 192 call mi_startup 193 194 /* NOTREACHED */ 1950: hlt 196 jmp 0b 197 198/* Space for initial page tables */ 199 .data 200 .p2align 12,0x40 201PT4: 202 .space 0x1000 203PT3: 204 .space 0x1000 205PT2: 206 .space 0x1000 207 208/* 64bit GDT */ 209gdtdesc: 210 .word gdtend - gdt - 1 211 .long VTOP(gdt) # low 212 .long 0 # high 213gdt: 214 .long 0 # null descriptor 215 .long 0 216 .long 0x00000000 # %cs 217 .long 0x00209800 218 .long 0x00000000 # %ds 219 .long 0x00008000 220gdtend: 221 222/* 32bit GDT */ 223gdtdesc32: 224 .word gdt32end - gdt32 - 1 225 .long VTOP(gdt32) 226 .long 0 227gdt32: 228 .long 0 # null descriptor 229 .long 0 230 .long 0x0000ffff # %cs 231 .long 0x00cf9a00 232 .long 0x0000ffff # %ds, %es, %ss 233 .long 0x00cf9200 234gdt32end: 235