1 /******************************************************************************
2 * arch/x86/guest/pvh-boot.c
3 *
4 * PVH boot time support
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Copyright (c) 2017 Citrix Systems Ltd.
20 */
21 #include <xen/init.h>
22 #include <xen/lib.h>
23 #include <xen/mm.h>
24
25 #include <asm/e820.h>
26 #include <asm/guest.h>
27
28 #include <public/arch-x86/hvm/start_info.h>
29
30 /* Initialised in head.S, before .bss is zeroed. */
31 bool __initdata pvh_boot;
32 uint32_t __initdata pvh_start_info_pa;
33
34 static multiboot_info_t __initdata pvh_mbi;
35 static module_t __initdata pvh_mbi_mods[8];
36 static const char *__initdata pvh_loader = "PVH Directboot";
37
convert_pvh_info(void)38 static void __init convert_pvh_info(void)
39 {
40 const struct hvm_start_info *pvh_info = __va(pvh_start_info_pa);
41 const struct hvm_modlist_entry *entry;
42 module_t *mod;
43 unsigned int i;
44
45 ASSERT(pvh_info->magic == XEN_HVM_START_MAGIC_VALUE);
46
47 /*
48 * Turn hvm_start_info into mbi. Luckily all modules are placed under 4GB
49 * boundary on x86.
50 */
51 pvh_mbi.flags = MBI_CMDLINE | MBI_MODULES | MBI_LOADERNAME;
52
53 BUG_ON(pvh_info->cmdline_paddr >> 32);
54 pvh_mbi.cmdline = pvh_info->cmdline_paddr;
55 pvh_mbi.boot_loader_name = __pa(pvh_loader);
56
57 BUG_ON(pvh_info->nr_modules >= ARRAY_SIZE(pvh_mbi_mods));
58 pvh_mbi.mods_count = pvh_info->nr_modules;
59 pvh_mbi.mods_addr = __pa(pvh_mbi_mods);
60
61 mod = pvh_mbi_mods;
62 entry = __va(pvh_info->modlist_paddr);
63 for ( i = 0; i < pvh_info->nr_modules; i++ )
64 {
65 BUG_ON(entry[i].paddr >> 32);
66 BUG_ON(entry[i].cmdline_paddr >> 32);
67
68 mod[i].mod_start = entry[i].paddr;
69 mod[i].mod_end = entry[i].paddr + entry[i].size;
70 mod[i].string = entry[i].cmdline_paddr;
71 }
72 }
73
get_memory_map(void)74 static void __init get_memory_map(void)
75 {
76 struct xen_memory_map memmap = {
77 .nr_entries = E820MAX,
78 };
79
80 set_xen_guest_handle(memmap.buffer, e820_raw.map);
81 BUG_ON(xen_hypercall_memory_op(XENMEM_memory_map, &memmap));
82 e820_raw.nr_map = memmap.nr_entries;
83
84 /* :( Various toolstacks don't sort the memory map. */
85 sanitize_e820_map(e820_raw.map, &e820_raw.nr_map);
86 }
87
pvh_init(void)88 multiboot_info_t *__init pvh_init(void)
89 {
90 convert_pvh_info();
91
92 probe_hypervisor();
93 ASSERT(xen_guest);
94
95 get_memory_map();
96
97 return &pvh_mbi;
98 }
99
pvh_print_info(void)100 void __init pvh_print_info(void)
101 {
102 const struct hvm_start_info *pvh_info = __va(pvh_start_info_pa);
103 const struct hvm_modlist_entry *entry;
104 unsigned int i;
105
106 ASSERT(pvh_info->magic == XEN_HVM_START_MAGIC_VALUE);
107
108 printk("PVH start info: (pa %08x)\n", pvh_start_info_pa);
109 printk(" version: %u\n", pvh_info->version);
110 printk(" flags: %#"PRIx32"\n", pvh_info->flags);
111 printk(" nr_modules: %u\n", pvh_info->nr_modules);
112 printk(" modlist_pa: %016"PRIx64"\n", pvh_info->modlist_paddr);
113 printk(" cmdline_pa: %016"PRIx64"\n", pvh_info->cmdline_paddr);
114 if ( pvh_info->cmdline_paddr )
115 printk(" cmdline: '%s'\n", (char *)__va(pvh_info->cmdline_paddr));
116 printk(" rsdp_pa: %016"PRIx64"\n", pvh_info->rsdp_paddr);
117
118 entry = __va(pvh_info->modlist_paddr);
119 for ( i = 0; i < pvh_info->nr_modules; i++ )
120 {
121 printk(" mod[%u].pa: %016"PRIx64"\n", i, entry[i].paddr);
122 printk(" mod[%u].size: %016"PRIu64"\n", i, entry[i].size);
123 printk(" mod[%u].cmdline_pa: %016"PRIx64"\n",
124 i, entry[i].cmdline_paddr);
125 if ( entry[i].cmdline_paddr )
126 printk(" mod[%1u].cmdline: '%s'\n", i,
127 (char *)__va(entry[i].cmdline_paddr));
128 }
129 }
130
131 /*
132 * Local variables:
133 * mode: C
134 * c-file-style: "BSD"
135 * c-basic-offset: 4
136 * tab-width: 4
137 * indent-tabs-mode: nil
138 * End:
139 */
140