ia64/xen-unstable

annotate tools/firmware/hvmloader/hvmloader.c @ 12548:40a61d01e9dc

[HVM] Set VIOAPIC ID to a value that does not conflict with LAPIC IDs.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Nov 22 11:52:46 2006 +0000 (2006-11-22)
parents f555a90bcc37
children a8d31d5ce258
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"
kfraser@12057 25 #include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
kfraser@10976 26 #include "hypercall.h"
kfraser@10976 27 #include "util.h"
kfraser@12057 28 #include "acpi_utils.h"
kfraser@11115 29 #include "smbios.h"
kfraser@12548 30 #include "config.h"
kfraser@10976 31 #include <xen/version.h>
kfraser@11081 32 #include <xen/hvm/params.h>
kaf24@8708 33
kaf24@8708 34 /* memory map */
kfraser@12548 35 #define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
kfraser@12548 36 #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
kfraser@12548 37 #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
kfraser@12548 38 #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
kaf24@8708 39
kaf24@8708 40 /* invoke SVM's paged realmode support */
kfraser@12548 41 #define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001
kaf24@8708 42
kaf24@8708 43 /*
kaf24@8708 44 * C runtime start off
kaf24@8708 45 */
kaf24@8708 46 asm(
kfraser@12548 47 " .text \n"
kfraser@12548 48 " .globl _start \n"
kfraser@12548 49 "_start: \n"
kfraser@12548 50 " cld \n"
kfraser@12548 51 " cli \n"
kfraser@12548 52 " lgdt gdt_desr \n"
kfraser@12548 53 " movl $stack_top, %esp \n"
kfraser@12548 54 " movl %esp, %ebp \n"
kfraser@12548 55 " call main \n"
kfraser@12548 56 " ud2 \n"
kfraser@12548 57 " \n"
kfraser@12548 58 "gdt_desr: \n"
kfraser@12548 59 " .word gdt_end - gdt - 1 \n"
kfraser@12548 60 " .long gdt \n"
kfraser@12548 61 " \n"
kfraser@12548 62 " .align 8 \n"
kfraser@12548 63 "gdt: \n"
kfraser@12548 64 " .quad 0x0000000000000000 \n"
kfraser@12548 65 " .quad 0x00CF92000000FFFF \n"
kfraser@12548 66 " .quad 0x00CF9A000000FFFF \n"
kfraser@12548 67 "gdt_end: \n"
kfraser@12548 68 " \n"
kfraser@12548 69 " .bss \n"
kfraser@12548 70 " .align 8 \n"
kfraser@12548 71 "stack: \n"
kfraser@12548 72 " .skip 0x4000 \n"
kfraser@12548 73 "stack_top: \n"
kfraser@12548 74 );
kaf24@8708 75
kaf24@8708 76 extern int get_acpi_enabled(void);
kaf24@8708 77 extern int acpi_madt_update(unsigned char* acpi_start);
kaf24@10575 78 extern void create_mp_tables(void);
kaf24@10575 79 struct hvm_info_table *get_hvm_info_table(void);
kaf24@8708 80
kfraser@10976 81 static int
kaf24@8708 82 cirrus_check(void)
kaf24@8708 83 {
kfraser@12548 84 outw(0x3C4, 0x9206);
kfraser@12548 85 return inb(0x3C5) == 0x12;
kaf24@8708 86 }
kaf24@8708 87
kfraser@10976 88 static int
kfraser@10893 89 vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx)
kaf24@8708 90 {
kfraser@12548 91 int eax;
kaf24@8708 92
kfraser@12548 93 __asm__ __volatile__ (
kfraser@12548 94 ".byte 0x0F,0x01,0xD9"
kfraser@12548 95 : "=a" (eax)
kfraser@12548 96 : "a"(function),
kfraser@12548 97 "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi) );
kfraser@12548 98 return eax;
kaf24@8708 99 }
kaf24@8708 100
kfraser@10976 101 static int
kaf24@8708 102 check_amd(void)
kaf24@8708 103 {
kfraser@12548 104 char id[12];
kaf24@8708 105
kfraser@12548 106 __asm__ __volatile__ (
kfraser@12548 107 "cpuid"
kfraser@12548 108 : "=b" (*(int *)(&id[0])),
kfraser@12548 109 "=c" (*(int *)(&id[8])),
kfraser@12548 110 "=d" (*(int *)(&id[4]))
kfraser@12548 111 : "a" (0) );
kfraser@12548 112 return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
kaf24@8708 113 }
kaf24@8708 114
kfraser@10976 115 static void
kfraser@10976 116 wrmsr(uint32_t idx, uint64_t v)
kfraser@10976 117 {
kfraser@12548 118 __asm__ __volatile__ (
kfraser@12548 119 "wrmsr"
kfraser@12548 120 : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
kfraser@10976 121 }
kfraser@10976 122
kfraser@10976 123 static void
kfraser@10976 124 init_hypercalls(void)
kfraser@10976 125 {
kfraser@12548 126 uint32_t eax, ebx, ecx, edx;
kfraser@12548 127 unsigned long i;
kfraser@12548 128 char signature[13], number[13];
kfraser@12548 129 xen_extraversion_t extraversion;
kfraser@10976 130
kfraser@12548 131 cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
kfraser@10976 132
kfraser@12548 133 *(uint32_t *)(signature + 0) = ebx;
kfraser@12548 134 *(uint32_t *)(signature + 4) = ecx;
kfraser@12548 135 *(uint32_t *)(signature + 8) = edx;
kfraser@12548 136 signature[12] = '\0';
kfraser@10976 137
kfraser@12548 138 if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) )
kfraser@12548 139 {
kfraser@12548 140 puts("FATAL: Xen hypervisor not detected\n");
kfraser@12548 141 __asm__ __volatile__( "ud2" );
kfraser@12548 142 }
kfraser@10976 143
kfraser@12548 144 cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
kfraser@10976 145
kfraser@12548 146 puts("Detected Xen v");
kfraser@12548 147 puts(itoa(number, eax >> 16));
kfraser@12548 148 puts(".");
kfraser@12548 149 puts(itoa(number, eax & 0xffff));
kfraser@12548 150
kfraser@12548 151 cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
kfraser@12548 152
kfraser@12548 153 for ( i = 0; i < eax; i++ )
kfraser@12548 154 wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
kfraser@12548 155
kfraser@12548 156 hypercall_xen_version(XENVER_extraversion, extraversion);
kfraser@12548 157 puts(extraversion);
kfraser@12548 158 puts("\n");
kfraser@10976 159 }
kfraser@10976 160
kfraser@12548 161 static void apic_setup(void)
kaf24@8708 162 {
kfraser@12548 163 volatile uint32_t *ioregsel;
kfraser@12548 164 volatile uint32_t *iowin;
kaf24@8708 165
kfraser@12548 166 /* IOAPIC memory-mapped access window registers. */
kfraser@12548 167 ioregsel = (volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00);
kfraser@12548 168 iowin = (volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
kaf24@8708 169
kfraser@12548 170 /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */
kfraser@12548 171 *ioregsel = 0;
kfraser@12548 172 *iowin = IOAPIC_ID;
kaf24@8708 173 }
kaf24@8708 174
kfraser@12548 175 int main(void)
kfraser@12548 176 {
kfraser@12548 177 puts("HVM Loader\n");
kfraser@12548 178
kfraser@12548 179 init_hypercalls();
kfraser@12548 180
kfraser@12548 181 puts("Writing SMBIOS tables ...\n");
kfraser@12548 182 hvm_write_smbios_tables();
kfraser@12548 183
kfraser@12548 184 puts("Loading ROMBIOS ...\n");
kfraser@12548 185 memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
kfraser@12548 186
kfraser@12548 187 apic_setup();
kfraser@12548 188
kfraser@12548 189 create_mp_tables();
kfraser@12548 190
kfraser@12548 191 if ( cirrus_check() )
kfraser@12548 192 {
kfraser@12548 193 puts("Loading Cirrus VGABIOS ...\n");
kfraser@12548 194 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kfraser@12548 195 vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
kfraser@12548 196 }
kfraser@12548 197 else
kfraser@12548 198 {
kfraser@12548 199 puts("Loading Standard VGABIOS ...\n");
kfraser@12548 200 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kfraser@12548 201 vgabios_stdvga, sizeof(vgabios_stdvga));
kfraser@12548 202 }
kfraser@12548 203
kfraser@12548 204 if ( get_acpi_enabled() != 0 )
kfraser@12548 205 {
kfraser@12548 206 puts("Loading ACPI ...\n");
kfraser@12548 207 acpi_madt_update((unsigned char *) acpi);
kfraser@12548 208 if ( (ACPI_PHYSICAL_ADDRESS + sizeof(acpi)) <= 0xF0000 )
kfraser@12548 209 {
kfraser@12548 210 unsigned char *freemem = (unsigned char *)
kfraser@12548 211 (ACPI_PHYSICAL_ADDRESS + sizeof(acpi));
kfraser@12548 212 /*
kfraser@12548 213 * Make sure acpi table does not overlap rombios
kfraser@12548 214 * currently acpi less than 8K will be OK.
kfraser@12548 215 */
kfraser@12548 216 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi,
kfraser@12548 217 sizeof(acpi));
kfraser@12548 218 acpi_update((unsigned char *)ACPI_PHYSICAL_ADDRESS,
kfraser@12548 219 sizeof(acpi),
kfraser@12548 220 (unsigned char *)0xF0000,
kfraser@12548 221 &freemem);
kfraser@12548 222 }
kfraser@12548 223 }
kfraser@12548 224
kfraser@12548 225 if ( check_amd() )
kfraser@12548 226 {
kfraser@12548 227 /* AMD implies this is SVM */
kfraser@12548 228 puts("SVM go ...\n");
kfraser@12548 229 vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0);
kfraser@12548 230 }
kfraser@12548 231 else
kfraser@12548 232 {
kfraser@12548 233 puts("Loading VMXAssist ...\n");
kfraser@12548 234 memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
kfraser@12548 235 vmxassist, sizeof(vmxassist));
kfraser@12548 236
kfraser@12548 237 puts("VMX go ...\n");
kfraser@12548 238 __asm__ __volatile__(
kfraser@12548 239 "jmp *%%eax"
kfraser@12548 240 : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
kfraser@12548 241 );
kfraser@12548 242 }
kfraser@12548 243
kfraser@12548 244 puts("Failed to invoke ROMBIOS\n");
kfraser@12548 245 return 0;
kfraser@12548 246 }
kfraser@12548 247
kfraser@12548 248 /*
kfraser@12548 249 * Local variables:
kfraser@12548 250 * mode: C
kfraser@12548 251 * c-set-style: "BSD"
kfraser@12548 252 * c-basic-offset: 4
kfraser@12548 253 * tab-width: 4
kfraser@12548 254 * indent-tabs-mode: nil
kfraser@12548 255 * End:
kfraser@12548 256 */