vmmapi_freebsd.c revision 245678
1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/lib/libvmmapi/vmmapi_freebsd.c 245678 2013-01-20 03:42:49Z neel $ 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/lib/libvmmapi/vmmapi_freebsd.c 245678 2013-01-20 03:42:49Z neel $"); 31 32#include <sys/types.h> 33 34#include <machine/specialreg.h> 35#include <machine/segments.h> 36#include <machine/vmm.h> 37 38#include "vmmapi.h" 39 40#define DESC_UNUSABLE 0x00010000 41 42#define GUEST_NULL_SEL 0 43#define GUEST_CODE_SEL 1 44#define GUEST_DATA_SEL 2 45#define GUEST_GDTR_LIMIT (3 * 8 - 1) 46 47void 48vm_setup_freebsd_gdt(uint64_t *gdtr) 49{ 50 gdtr[GUEST_NULL_SEL] = 0; 51 gdtr[GUEST_CODE_SEL] = 0x0020980000000000; 52 gdtr[GUEST_DATA_SEL] = 0x0000900000000000; 53} 54 55/* 56 * Setup the 'vcpu' register set such that it will begin execution at 57 * 'rip' in long mode. 58 */ 59int 60vm_setup_freebsd_registers(struct vmctx *vmctx, int vcpu, 61 uint64_t rip, uint64_t cr3, uint64_t gdtbase, 62 uint64_t rsp) 63{ 64 int error; 65 uint64_t cr0, cr4, efer, rflags, desc_base; 66 uint32_t desc_access, desc_limit; 67 uint16_t gsel; 68 69 cr0 = CR0_PE | CR0_PG | CR0_NE; 70 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0) 71 goto done; 72 73 cr4 = CR4_PAE; 74 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0) 75 goto done; 76 77 efer = EFER_LME | EFER_LMA; 78 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_EFER, efer))) 79 goto done; 80 81 rflags = 0x2; 82 error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags); 83 if (error) 84 goto done; 85 86 desc_base = 0; 87 desc_limit = 0; 88 desc_access = 0x0000209B; 89 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS, 90 desc_base, desc_limit, desc_access); 91 if (error) 92 goto done; 93 94 desc_access = 0x00000093; 95 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS, 96 desc_base, desc_limit, desc_access); 97 if (error) 98 goto done; 99 100 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES, 101 desc_base, desc_limit, desc_access); 102 if (error) 103 goto done; 104 105 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS, 106 desc_base, desc_limit, desc_access); 107 if (error) 108 goto done; 109 110 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS, 111 desc_base, desc_limit, desc_access); 112 if (error) 113 goto done; 114 115 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS, 116 desc_base, desc_limit, desc_access); 117 if (error) 118 goto done; 119 120 /* 121 * XXX TR is pointing to null selector even though we set the 122 * TSS segment to be usable with a base address and limit of 0. 123 */ 124 desc_access = 0x0000008b; 125 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access); 126 if (error) 127 goto done; 128 129 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, 0, 0, 130 DESC_UNUSABLE); 131 if (error) 132 goto done; 133 134 gsel = GSEL(GUEST_CODE_SEL, SEL_KPL); 135 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, gsel)) != 0) 136 goto done; 137 138 gsel = GSEL(GUEST_DATA_SEL, SEL_KPL); 139 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, gsel)) != 0) 140 goto done; 141 142 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, gsel)) != 0) 143 goto done; 144 145 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, gsel)) != 0) 146 goto done; 147 148 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, gsel)) != 0) 149 goto done; 150 151 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, gsel)) != 0) 152 goto done; 153 154 /* XXX TR is pointing to the null selector */ 155 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, 0)) != 0) 156 goto done; 157 158 /* LDTR is pointing to the null selector */ 159 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0) 160 goto done; 161 162 /* entry point */ 163 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0) 164 goto done; 165 166 /* page table base */ 167 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, cr3)) != 0) 168 goto done; 169 170 desc_base = gdtbase; 171 desc_limit = GUEST_GDTR_LIMIT; 172 error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR, 173 desc_base, desc_limit, 0); 174 if (error != 0) 175 goto done; 176 177 if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, rsp)) != 0) 178 goto done; 179 180 error = 0; 181done: 182 return (error); 183} 184