Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / src / xen.c
1 // Xen HVM support
2 //
3 // Copyright (C) 2011 Citrix Systems.
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "config.h"
8 #include "xen.h"
9
10 #include "memmap.h" // add_e820
11 #include "types.h" // ASM32FLAT
12 #include "util.h" // copy_acpi_rsdp
13
14 #define INFO_PHYSICAL_ADDRESS 0x00001000
15
16 u32 xen_cpuid_base = 0;
17
18 struct xen_seabios_info {
19     char signature[14]; /* XenHVMSeaBIOS\0 */
20     u8 length;     /* Length of this struct */
21     u8 checksum;   /* Set such that the sum over bytes 0..length == 0 */
22     /*
23      * Physical address of an array of tables_nr elements.
24      *
25      * Each element is a 32 bit value contianing the physical address
26      * of a BIOS table.
27      */
28     u32 tables;
29     u32 tables_nr;
30     /*
31      * Physical address of the e820 table, contains e820_nr entries.
32      */
33     u32 e820;
34     u32 e820_nr;
35 } PACKED;
36
37 static void validate_info(struct xen_seabios_info *t)
38 {
39     if ( memcmp(t->signature, "XenHVMSeaBIOS", 14) )
40         panic("Bad Xen info signature\n");
41
42     if ( t->length < sizeof(struct xen_seabios_info) )
43         panic("Bad Xen info length\n");
44
45     if (checksum(t, t->length) != 0)
46         panic("Bad Xen info checksum\n");
47 }
48
49 void xen_probe(void)
50 {
51     u32 base, eax, ebx, ecx, edx;
52     char signature[13];
53
54     if (!CONFIG_XEN)
55         return;
56
57     for (base = 0x40000000; base < 0x40010000; base += 0x100) {
58         cpuid(base, &eax, &ebx, &ecx, &edx);
59         memcpy(signature + 0, &ebx, 4);
60         memcpy(signature + 4, &ecx, 4);
61         memcpy(signature + 8, &edx, 4);
62         signature[12] = 0;
63
64         dprintf(1, "Found hypervisor signature \"%s\" at %x\n",
65                 signature, base);
66         if (strcmp(signature, "XenVMMXenVMM") == 0) {
67             if ((eax - base) < 2)
68                 panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n",
69                       eax, base);
70             xen_cpuid_base = base;
71             break;
72         }
73     }
74 }
75
76 static int hypercall_xen_version( int cmd, void *arg)
77 {
78     return _hypercall2(int, xen_version, cmd, arg);
79 }
80
81 /* Fill in hypercall transfer pages. */
82 void xen_init_hypercalls(void)
83 {
84     u32 eax, ebx, ecx, edx;
85     xen_extraversion_t extraversion;
86     unsigned long i;
87
88     if (!usingXen())
89         return;
90
91     cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx);
92
93     xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE);
94     if (!xen_hypercall_page)
95         panic("unable to allocate Xen hypercall page\n");
96
97     dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page);
98     for ( i = 0; i < eax; i++ )
99         wrmsr(ebx, xen_hypercall_page + (i << 12) + i);
100
101     /* Print version information. */
102     cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
103     hypercall_xen_version(XENVER_extraversion, extraversion);
104     dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
105 }
106
107 void xen_copy_biostables(void)
108 {
109     struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
110     u32 *tables = (u32 *)info->tables;
111     int i;
112
113     dprintf(1, "xen: copy BIOS tables...\n");
114     for (i=0; i<info->tables_nr; i++) {
115         void *table = (void *)tables[i];
116         copy_acpi_rsdp(table);
117         copy_mptable(table);
118         copy_pir(table);
119         copy_smbios(table);
120     }
121 }
122
123 void xen_setup(void)
124 {
125     u64 maxram = 0, maxram_over4G = 0;
126     int i;
127     struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
128     struct e820entry *e820 = (struct e820entry *)info->e820;
129     validate_info(info);
130
131     dprintf(1, "xen: copy e820...\n");
132
133     for (i = 0; i < info->e820_nr; i++) {
134         struct e820entry *e = &e820[i];
135         if (e->type == E820_ACPI || e->type == E820_RAM) {
136             u64 end = e->start + e->size;
137             if (end > 0x100000000ull) {
138                 end -= 0x100000000ull;
139                 if (end > maxram_over4G)
140                     maxram_over4G = end;
141             } else if (end > maxram)
142                 maxram = end;
143         }
144         add_e820(e->start, e->size, e->type);
145     }
146
147     RamSize = maxram;
148     RamSizeOver4G = maxram_over4G;
149 }