ia64/xen-unstable

annotate tools/firmware/hvmloader/hvmloader.c @ 10575:ae245d35457b

[HVM][Firmware] Make the creation of MP tables more dynamic

Currently the ROMBIOS includes static MP tables for only four
configurations: 1-way, 2-way, 4-way, and 8-way.

This patch makes the creation of MP tables more dynamic by creating them
from within HVMLOADER based upon the VCPU number provided by the HVM
information table.

Note: Some of the information included used to create the MP tables is
still hard coded and based upon values used in the original ROMBIOS MP
tables. Data such as the CPU family/model/stepping information should
probably be made to match the information provided to the guest when
executing a CPUID.

Signed-off-by: Travis Betak <travis.betak@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jun 28 13:59:29 2006 +0100 (2006-06-28)
parents f1b361b05bf3
children 2e3b121662dc
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 */
kaf24@10575 26 #include <xen/hvm/hvm_info_table.h>
kaf24@8708 27
kaf24@8708 28 /* memory map */
kaf24@8708 29 #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
kaf24@8708 30 #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
kaf24@8708 31 #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
kaf24@8708 32
kaf24@8708 33 /* invoke SVM's paged realmode support */
kaf24@8708 34 #define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001
kaf24@8708 35
kaf24@8708 36 /*
kaf24@8708 37 * C runtime start off
kaf24@8708 38 */
kaf24@8708 39 asm(
kaf24@8708 40 " .text \n"
kaf24@8708 41 " .globl _start \n"
kaf24@8708 42 "_start: \n"
kaf24@8708 43 " cld \n"
kaf24@8708 44 " cli \n"
kaf24@8708 45 " lgdt gdt_desr \n"
kaf24@8708 46 " movl $stack_top, %esp \n"
kaf24@8708 47 " movl %esp, %ebp \n"
kaf24@8708 48 " call main \n"
kaf24@8708 49 " jmp halt \n"
kaf24@8708 50 " \n"
kaf24@8708 51 "gdt_desr: \n"
kaf24@8708 52 " .word gdt_end - gdt - 1 \n"
kaf24@8708 53 " .long gdt \n"
kaf24@8708 54 " \n"
kaf24@8708 55 " .align 8 \n"
kaf24@8708 56 "gdt: \n"
kaf24@8708 57 " .quad 0x0000000000000000 \n"
kaf24@8708 58 " .quad 0x00CF92000000FFFF \n"
kaf24@8708 59 " .quad 0x00CF9A000000FFFF \n"
kaf24@8708 60 "gdt_end: \n"
kaf24@8708 61 " \n"
kaf24@8708 62 "halt: \n"
kaf24@8708 63 " sti \n"
kaf24@8708 64 " jmp . \n"
kaf24@8708 65 " \n"
kaf24@8708 66 " .bss \n"
kaf24@8708 67 " .align 8 \n"
kaf24@8708 68 "stack: \n"
kaf24@8708 69 " .skip 0x4000 \n"
kaf24@8708 70 "stack_top: \n"
kaf24@8708 71 );
kaf24@8708 72
kaf24@8708 73 extern int get_acpi_enabled(void);
kaf24@8708 74 extern int acpi_madt_update(unsigned char* acpi_start);
kaf24@10575 75 extern void create_mp_tables(void);
kaf24@10575 76 struct hvm_info_table *get_hvm_info_table(void);
kaf24@8708 77
kaf24@8708 78 static inline void
kaf24@8708 79 outw(unsigned short addr, unsigned short val)
kaf24@8708 80 {
kaf24@8708 81 __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
kaf24@8708 82 }
kaf24@8708 83
kaf24@8708 84 static inline void
kaf24@8708 85 outb(unsigned short addr, unsigned char val)
kaf24@8708 86 {
kaf24@8708 87 __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
kaf24@8708 88 }
kaf24@8708 89
kaf24@8708 90 static inline unsigned char
kaf24@8708 91 inb(unsigned short addr)
kaf24@8708 92 {
kaf24@8708 93 unsigned char val;
kaf24@8708 94
kaf24@8708 95 __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
kaf24@8708 96 return val;
kaf24@8708 97 }
kaf24@8708 98
kaf24@8708 99 void *
kaf24@8708 100 memcpy(void *dest, const void *src, unsigned n)
kaf24@8708 101 {
kaf24@8708 102 int t0, t1, t2;
kaf24@8708 103
kaf24@8708 104 __asm__ __volatile__(
kaf24@8708 105 "cld\n"
kaf24@8708 106 "rep; movsl\n"
kaf24@8708 107 "testb $2,%b4\n"
kaf24@8708 108 "je 1f\n"
kaf24@8708 109 "movsw\n"
kaf24@8708 110 "1: testb $1,%b4\n"
kaf24@8708 111 "je 2f\n"
kaf24@8708 112 "movsb\n"
kaf24@8708 113 "2:"
kaf24@8708 114 : "=&c" (t0), "=&D" (t1), "=&S" (t2)
kaf24@8708 115 : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
kaf24@8708 116 : "memory"
kaf24@8708 117 );
kaf24@8708 118 return dest;
kaf24@8708 119 }
kaf24@8708 120
kaf24@8708 121 int
kaf24@8708 122 puts(const char *s)
kaf24@8708 123 {
kaf24@8708 124 while (*s)
kaf24@8708 125 outb(0xE9, *s++);
kaf24@8708 126 return 0;
kaf24@8708 127 }
kaf24@8708 128
kaf24@8708 129 int
kaf24@8708 130 cirrus_check(void)
kaf24@8708 131 {
kaf24@8708 132 outw(0x3C4, 0x9206);
kaf24@8708 133 return inb(0x3C5) == 0x12;
kaf24@8708 134 }
kaf24@8708 135
kaf24@8708 136 int
kaf24@8708 137 vmmcall(int edi, int esi, int edx, int ecx, int ebx)
kaf24@8708 138 {
kaf24@8708 139 int eax;
kaf24@8708 140
kaf24@8708 141 __asm__ __volatile__(
kaf24@8708 142 ".byte 0x0F,0x01,0xD9"
kaf24@8708 143 : "=a" (eax)
kaf24@8708 144 : "a"(0x58454E00), /* XEN\0 key */
kaf24@8708 145 "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
kaf24@8708 146 );
kaf24@8708 147 return eax;
kaf24@8708 148 }
kaf24@8708 149
kaf24@8708 150 int
kaf24@8708 151 check_amd(void)
kaf24@8708 152 {
kaf24@8708 153 char id[12];
kaf24@8708 154
kaf24@8708 155 __asm__ __volatile__(
kaf24@8708 156 "cpuid"
kaf24@8708 157 : "=b" (*(int *)(&id[0])),
kaf24@8708 158 "=c" (*(int *)(&id[8])),
kaf24@8708 159 "=d" (*(int *)(&id[4]))
kaf24@8708 160 : "a" (0)
kaf24@8708 161 );
kaf24@8708 162 return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
kaf24@8708 163 }
kaf24@8708 164
kaf24@8708 165 int
kaf24@8708 166 main(void)
kaf24@8708 167 {
kaf24@10575 168 struct hvm_info_table *t = get_hvm_info_table();
kaf24@10575 169
kaf24@8708 170 puts("HVM Loader\n");
kaf24@8708 171
kaf24@8708 172 puts("Loading ROMBIOS ...\n");
kaf24@8708 173 memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
kaf24@10575 174 if (t->apic_enabled)
kaf24@10575 175 create_mp_tables();
kaf24@10575 176
kaf24@8708 177 if (cirrus_check()) {
kaf24@8708 178 puts("Loading Cirrus VGABIOS ...\n");
kaf24@8708 179 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kaf24@8708 180 vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
kaf24@8708 181 } else {
kaf24@8708 182 puts("Loading Standard VGABIOS ...\n");
kaf24@8708 183 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
kaf24@8708 184 vgabios_stdvga, sizeof(vgabios_stdvga));
kaf24@8708 185 }
kaf24@8708 186
kaf24@8708 187 if (get_acpi_enabled() != 0) {
kaf24@8708 188 puts("Loading ACPI ...\n");
kaf24@8708 189 acpi_madt_update((unsigned char *) acpi);
kaf24@8708 190 if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
kaf24@8708 191 /*
kaf24@8708 192 * Make sure acpi table does not overlap rombios
kaf24@8708 193 * currently acpi less than 8K will be OK.
kaf24@8708 194 */
kaf24@8708 195 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi,
kaf24@8708 196 sizeof(acpi));
kaf24@8708 197 }
kaf24@8708 198 }
kaf24@8708 199
kaf24@8708 200 if (check_amd()) {
kaf24@8708 201 /* AMD implies this is SVM */
kaf24@8708 202 puts("SVM go ...\n");
kaf24@8708 203 vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
kaf24@8708 204 } else {
kaf24@8708 205 puts("Loading VMXAssist ...\n");
kaf24@8708 206 memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
kaf24@8708 207 vmxassist, sizeof(vmxassist));
kaf24@8708 208
kaf24@8708 209 puts("VMX go ...\n");
kaf24@8708 210 __asm__ __volatile__(
kaf24@8708 211 "jmp *%%eax"
kaf24@8708 212 : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
kaf24@8708 213 );
kaf24@8708 214 }
kaf24@8708 215
kaf24@8708 216 puts("Failed to invoke ROMBIOS\n");
kaf24@8708 217 return 0;
kaf24@8708 218 }
kaf24@8708 219