blob: a215b9ea99e67a833b2577f514f398fc348291e1 [file] [log] [blame]
Ian Campbell74c78782011-06-01 11:00:29 +01001// 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
Kevin O'Connorc167e542015-09-29 09:40:46 -04007#include "config.h" // CONFIG_XEN
8#include "e820map.h" // e820_add
Kevin O'Connor4cd522e2013-11-29 12:14:34 -05009#include "hw/serialio.h" // DebugOutputPort
Kevin O'Connor9dea5902013-09-14 20:23:54 -040010#include "malloc.h" // memalign_high
Kevin O'Connorc167e542015-09-29 09:40:46 -040011#include "memmap.h" // PAGE_SIZE
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040012#include "output.h" // dprintf
13#include "paravirt.h" // PlatformRunningOn
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040014#include "string.h" // memcpy
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040015#include "util.h" // copy_acpi_rsdp
Kevin O'Connorb9c6a962013-09-14 13:01:30 -040016#include "x86.h" // cpuid
Kevin O'Connorc167e542015-09-29 09:40:46 -040017#include "xen.h" // xen_extraversion_t
Ian Campbell74c78782011-06-01 11:00:29 +010018
19#define INFO_PHYSICAL_ADDRESS 0x00001000
20
21u32 xen_cpuid_base = 0;
Ian Campbell9166c4a2012-06-27 12:08:49 +010022unsigned long xen_hypercall_page = 0;
Ian Campbell74c78782011-06-01 11:00:29 +010023
24struct xen_seabios_info {
25 char signature[14]; /* XenHVMSeaBIOS\0 */
26 u8 length; /* Length of this struct */
27 u8 checksum; /* Set such that the sum over bytes 0..length == 0 */
28 /*
29 * Physical address of an array of tables_nr elements.
30 *
31 * Each element is a 32 bit value contianing the physical address
32 * of a BIOS table.
33 */
34 u32 tables;
35 u32 tables_nr;
36 /*
37 * Physical address of the e820 table, contains e820_nr entries.
38 */
39 u32 e820;
40 u32 e820_nr;
41} PACKED;
42
43static void validate_info(struct xen_seabios_info *t)
44{
45 if ( memcmp(t->signature, "XenHVMSeaBIOS", 14) )
46 panic("Bad Xen info signature\n");
47
48 if ( t->length < sizeof(struct xen_seabios_info) )
49 panic("Bad Xen info length\n");
50
51 if (checksum(t, t->length) != 0)
52 panic("Bad Xen info checksum\n");
53}
54
Kevin O'Connord83c87b2013-01-21 01:14:12 -050055void xen_preinit(void)
Ian Campbell74c78782011-06-01 11:00:29 +010056{
57 u32 base, eax, ebx, ecx, edx;
58 char signature[13];
59
60 if (!CONFIG_XEN)
61 return;
62
63 for (base = 0x40000000; base < 0x40010000; base += 0x100) {
64 cpuid(base, &eax, &ebx, &ecx, &edx);
65 memcpy(signature + 0, &ebx, 4);
66 memcpy(signature + 4, &ecx, 4);
67 memcpy(signature + 8, &edx, 4);
68 signature[12] = 0;
69
Kevin O'Connor36289332012-07-21 13:41:16 -040070 dprintf(9, "Found hypervisor signature \"%s\" at %x\n",
Ian Campbell74c78782011-06-01 11:00:29 +010071 signature, base);
72 if (strcmp(signature, "XenVMMXenVMM") == 0) {
Ian Campbell54f3b252012-06-28 11:08:32 +010073 /* Set debug_io_port first, so the following messages work. */
Kevin O'Connora48f6022016-01-12 14:22:33 -050074 code_mutable_preinit();
Ian Campbell54f3b252012-06-28 11:08:32 +010075 DebugOutputPort = 0xe9;
Kevin O'Connorbb1fcb42014-01-15 13:52:14 -050076 debug_banner();
77 dprintf(1, "\nFound Xen hypervisor signature at %x\n", base);
Ian Campbell74c78782011-06-01 11:00:29 +010078 if ((eax - base) < 2)
79 panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n",
80 eax, base);
81 xen_cpuid_base = base;
82 break;
83 }
84 }
Kevin O'Connor02313b22013-02-07 22:42:25 -050085 if (!xen_cpuid_base) {
Ian Campbell54f3b252012-06-28 11:08:32 +010086 dprintf(1, "No Xen hypervisor found.\n");
Kevin O'Connor02313b22013-02-07 22:42:25 -050087 return;
88 }
89 PlatformRunningOn = PF_QEMU|PF_XEN;
Ian Campbell74c78782011-06-01 11:00:29 +010090}
91
92static int hypercall_xen_version( int cmd, void *arg)
93{
94 return _hypercall2(int, xen_version, cmd, arg);
95}
96
97/* Fill in hypercall transfer pages. */
Kevin O'Connord83c87b2013-01-21 01:14:12 -050098void xen_hypercall_setup(void)
Ian Campbell74c78782011-06-01 11:00:29 +010099{
100 u32 eax, ebx, ecx, edx;
101 xen_extraversion_t extraversion;
102 unsigned long i;
103
Kevin O'Connor897fb112013-02-07 23:32:48 -0500104 if (!runningOnXen())
Ian Campbell74c78782011-06-01 11:00:29 +0100105 return;
106
107 cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx);
108
109 xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE);
110 if (!xen_hypercall_page)
111 panic("unable to allocate Xen hypercall page\n");
112
113 dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page);
114 for ( i = 0; i < eax; i++ )
115 wrmsr(ebx, xen_hypercall_page + (i << 12) + i);
116
117 /* Print version information. */
118 cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
119 hypercall_xen_version(XENVER_extraversion, extraversion);
120 dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
121}
122
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500123void xen_biostable_setup(void)
Ian Campbell74c78782011-06-01 11:00:29 +0100124{
125 struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
Kevin O'Connor4d053eb2012-06-09 13:08:02 -0400126 void **tables = (void*)info->tables;
Ian Campbell74c78782011-06-01 11:00:29 +0100127 int i;
128
129 dprintf(1, "xen: copy BIOS tables...\n");
Kevin O'Connor4d053eb2012-06-09 13:08:02 -0400130 for (i=0; i<info->tables_nr; i++)
131 copy_table(tables[i]);
David Woodhousef34f0692013-02-05 16:14:06 +0000132
David Woodhoused304fe42013-02-23 00:24:48 +0000133 find_acpi_features();
Ian Campbell74c78782011-06-01 11:00:29 +0100134}
135
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500136void xen_ramsize_preinit(void)
Ian Campbell74c78782011-06-01 11:00:29 +0100137{
Ian Campbell74c78782011-06-01 11:00:29 +0100138 int i;
139 struct xen_seabios_info *info = (void *)INFO_PHYSICAL_ADDRESS;
140 struct e820entry *e820 = (struct e820entry *)info->e820;
141 validate_info(info);
142
143 dprintf(1, "xen: copy e820...\n");
144
145 for (i = 0; i < info->e820_nr; i++) {
146 struct e820entry *e = &e820[i];
Kevin O'Connorc167e542015-09-29 09:40:46 -0400147 e820_add(e->start, e->size, e->type);
Ian Campbell74c78782011-06-01 11:00:29 +0100148 }
Ian Campbell74c78782011-06-01 11:00:29 +0100149}