ia64/xen-unstable

annotate tools/firmware/hvmloader/hvmloader.c @ 11081:323eb29083e6

[HVM] Remove unused apic_enabled field from hvm_info_table.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Aug 10 15:45:47 2006 +0100 (2006-08-10)
parents 49dcd838b7df
children 4210049a5854
rev   line source
kaf24@8708 1 /*
kaf24@8708 2 * hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader.
kaf24@8708 3 *
kaf24@8708 4 * A quicky so that we can boot rom images as if they were a Linux kernel.
kaf24@8708 5 * This code will copy the rom images (ROMBIOS/VGABIOS/VM86) into their
kaf24@8708 6 * respective spaces and transfer control to VM86 to execute the BIOSes.
kaf24@8708 7 *
kaf24@8708 8 * Leendert van Doorn, leendert@watson.ibm.com
kaf24@8708 9 * Copyright (c) 2005, International Business Machines Corporation.
kaf24@8708 10 *
kaf24@8708 11 * This program is free software; you can redistribute it and/or modify it
kaf24@8708 12 * under the terms and conditions of the GNU General Public License,
kaf24@8708 13 * version 2, as published by the Free Software Foundation.
kaf24@8708 14 *
kaf24@8708 15 * This program is distributed in the hope it will be useful, but WITHOUT
kaf24@8708 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
kaf24@8708 17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kaf24@8708 18 * more details.
kaf24@8708 19 *
kaf24@8708 20 * You should have received a copy of the GNU General Public License along with
kaf24@8708 21 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
kaf24@8708 22 * Place - Suite 330, Boston, MA 02111-1307 USA.
kaf24@8708 23 */
kaf24@8708 24 #include "roms.h"
kaf24@8708 25 #include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
kfraser@10976 26 #include "hypercall.h"
kfraser@10976 27 #include "util.h"
kfraser@10976 28 #include <xen/version.h>
kfraser@11081 29 #include <xen/hvm/params.h>
kaf24@8708 30
kaf24@8708 31 /* memory map */
kfraser@10976 32 #define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
kaf24@8708 33 #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
kaf24@8708 34 #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
kaf24@8708 35 #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
kaf24@8708 36
kaf24@8708 37 /* invoke SVM's paged realmode support */
kfraser@10893 38 #define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001
kaf24@8708 39
kaf24@8708 40 /*
kaf24@8708 41 * C runtime start off
kaf24@8708 42 */
kaf24@8708 43 asm(
kaf24@8708 44 " .text \n"
kaf24@8708 45 " .globl _start \n"
kaf24@8708 46 "_start: \n"
kaf24@8708 47 " cld \n"
kaf24@8708 48 " cli \n"
kaf24@8708 49 " lgdt gdt_desr \n"
kaf24@8708 50 " movl $stack_top, %esp \n"
kaf24@8708 51 " movl %esp, %ebp \n"
kaf24@8708 52 " call main \n"
kaf24@8708 53 " jmp halt \n"
kaf24@8708 54 " \n"
kaf24@8708 55 "gdt_desr: \n"
kaf24@8708 56 " .word gdt_end - gdt - 1 \n"
kaf24@8708 57 " .long gdt \n"
kaf24@8708 58 " \n"
kaf24@8708 59 " .align 8 \n"
kaf24@8708 60 "gdt: \n"
kaf24@8708 61 " .quad 0x0000000000000000 \n"
kaf24@8708 62 " .quad 0x00CF92000000FFFF \n"
kaf24@8708 63 " .quad 0x00CF9A000000FFFF \n"
kaf24@8708 64 "gdt_end: \n"
kaf24@8708 65 " \n"
kaf24@8708 66 "halt: \n"
kaf24@8708 67 " sti \n"
kaf24@8708 68 " jmp . \n"
kaf24@8708 69 " \n"
kaf24@8708 70 " .bss \n"
kaf24@8708 71 " .align 8 \n"
kaf24@8708 72 "stack: \n"
kaf24@8708 73 " .skip 0x4000 \n"
kaf24@8708 74 "stack_top: \n"
kaf24@8708 75 );
kaf24@8708 76
kaf24@8708 77 extern int get_acpi_enabled(void);
kaf24@8708 78 extern int acpi_madt_update(unsigned char* acpi_start);
kaf24@10575 79 extern void create_mp_tables(void);
kaf24@10575 80 struct hvm_info_table *get_hvm_info_table(void);
kaf24@8708 81
kfraser@10976 82 static int
kaf24@8708 83 cirrus_check(void)
kaf24@8708 84 {
kaf24@8708 85 outw(0x3C4, 0x9206);
kaf24@8708 86 return inb(0x3C5) == 0x12;
kaf24@8708 87 }
kaf24@8708 88
kfraser@10976 89 static int
kfraser@10893 90 vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx)
kaf24@8708 91 {
kaf24@8708 92 int eax;
kaf24@8708 93
kaf24@8708 94 __asm__ __volatile__(
kaf24@8708 95 ".byte 0x0F,0x01,0xD9"
kaf24@8708 96 : "=a" (eax)
kfraser@10893 97 : "a"(function),
kaf24@8708 98 "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
kaf24@8708 99 );
kaf24@8708 100 return eax;
kaf24@8708 101 }
kaf24@8708 102
kfraser@10976 103 static int
kaf24@8708 104 check_amd(void)
kaf24@8708 105 {
kaf24@8708 106 char id[12];
kaf24@8708 107
kaf24@8708 108 __asm__ __volatile__(
kaf24@8708 109 "cpuid"
kaf24@8708 110 : "=b" (*(int *)(&id[0])),
kaf24@8708 111 "=c" (*(int *)(&id[8])),
kaf24@8708 112 "=d" (*(int *)(&id[4]))
kaf24@8708 113 : "a" (0)
kaf24@8708 114 );
kaf24@8708 115 return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
kaf24@8708 116 }
kaf24@8708 117
kfraser@10976 118 static void
kfraser@10976 119 cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
kfraser@10976 120 {
kfraser@10976 121 __asm__ __volatile__(
kfraser@10976 122 "cpuid"
kfraser@10976 123 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
kfraser@10976 124 : "0" (idx) );
kfraser@10976 125 }
kfraser@10976 126
kfraser@10976 127 static void
kfraser@10976 128 wrmsr(uint32_t idx, uint64_t v)
kfraser@10976 129 {
kfraser@10976 130 __asm__ __volatile__(
kfraser@10976 131 "wrmsr"
kfraser@10976 132 : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
kfraser@10976 133 }
kfraser@10976 134
kfraser@10976 135 static void
kfraser@10976 136 init_hypercalls(void)
kfraser@10976 137 {
kfraser@10976 138 uint32_t eax, ebx, ecx, edx;
kfraser@10976 139 unsigned long i;
kfraser@10976 140 char signature[13], number[13];
kfraser@10976 141 xen_extraversion_t extraversion;
kfraser@10976 142
kfraser@10976 143 cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
kfraser@10976 144
kfraser@10976 145 *(uint32_t *)(signature + 0) = ebx;
kfraser@10976 146 *(uint32_t *)(signature + 4) = ecx;
kfraser@10976 147 *(uint32_t *)(signature + 8) = edx;
kfraser@10976 148 signature[12] = '\0';
kfraser@10976 149
kfraser@10976 150 if (strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002)) {
kfraser@10976 151 puts("FATAL: Xen hypervisor not detected\n");
kfraser@10976 152 __asm__ __volatile__( "ud2" );
kfraser@10976 153 }
kfraser@10976 154
kfraser@10976 155 cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
kfraser@10976 156
kfraser@10976 157 puts("Detected Xen v");
kfraser@10976 158 puts(itoa(number, eax >> 16));
kfraser@10976 159 puts(".");
kfraser@10976 160 puts(itoa(number, eax & 0xffff));
kfraser@10976 161
kfraser@10976 162 cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
kfraser@10976 163
kfraser@10976 164 for (i = 0; i < eax; i++)
kfraser@10976 165 wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
kfraser@10976 166
kfraser@10976 167 hypercall_xen_version(XENVER_extraversion, extraversion);
kfraser@10976 168 puts(extraversion);
kfraser@10976 169 puts("\n");
kfraser@10976 170 }
kfraser@10976 171
kaf24@8708 172 int
kaf24@8708 173 main(void)
kaf24@8708 174 {
kfraser@11081 175 struct xen_hvm_param hvm_param;
kaf24@10575 176
kaf24@8708 177 puts("HVM Loader\n");
kaf24@8708 178
kfraser@10976 179 init_hypercalls();
kfraser@10976 180
kaf24@8708 181 puts("Loading ROMBIOS ...\n");
kaf24@8708 182 memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
kfraser@11081 183
kfraser@11081 184 hvm_param.domid = DOMID_SELF;
kfraser@11081 185 hvm_param.index = HVM_PARAM_APIC_ENABLED;
kfraser@11081 186 if (!hypercall_hvm_op(HVMOP_get_param, &hvm_param) && hvm_param.value)
kaf24@10575 187 create_mp_tables();
kaf24@10575 188
kaf24@8708 189 if (cirrus_check()) {
kaf24@8708 190 puts("Loading Cirrus VGABIOS ...\n");
kaf24@8708 191 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kaf24@8708 192 vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
kaf24@8708 193 } else {
kaf24@8708 194 puts("Loading Standard VGABIOS ...\n");
kaf24@8708 195 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kaf24@8708 196 vgabios_stdvga, sizeof(vgabios_stdvga));
kaf24@8708 197 }
kaf24@8708 198
kaf24@8708 199 if (get_acpi_enabled() != 0) {
kaf24@8708 200 puts("Loading ACPI ...\n");
kaf24@8708 201 acpi_madt_update((unsigned char *) acpi);
kaf24@8708 202 if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
kaf24@8708 203 /*
kaf24@8708 204 * Make sure acpi table does not overlap rombios
kaf24@8708 205 * currently acpi less than 8K will be OK.
kaf24@8708 206 */
kaf24@8708 207 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi,
kaf24@8708 208 sizeof(acpi));
kaf24@8708 209 }
kaf24@8708 210 }
kaf24@8708 211
kaf24@8708 212 if (check_amd()) {
kaf24@8708 213 /* AMD implies this is SVM */
kaf24@8708 214 puts("SVM go ...\n");
kfraser@10893 215 vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0);
kaf24@8708 216 } else {
kaf24@8708 217 puts("Loading VMXAssist ...\n");
kaf24@8708 218 memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
kaf24@8708 219 vmxassist, sizeof(vmxassist));
kaf24@8708 220
kaf24@8708 221 puts("VMX go ...\n");
kaf24@8708 222 __asm__ __volatile__(
kaf24@8708 223 "jmp *%%eax"
kaf24@8708 224 : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
kaf24@8708 225 );
kaf24@8708 226 }
kaf24@8708 227
kaf24@8708 228 puts("Failed to invoke ROMBIOS\n");
kaf24@8708 229 return 0;
kaf24@8708 230 }
kaf24@8708 231