1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/acpi.h> 3 #include <linux/export.h> 4 #include <linux/mm.h> 5 6 #include <xen/hvc-console.h> 7 8 #include <asm/bootparam.h> 9 #include <asm/io_apic.h> 10 #include <asm/hypervisor.h> 11 #include <asm/e820/api.h> 12 #include <asm/setup.h> 13 14 #include <xen/xen.h> 15 #include <asm/xen/interface.h> 16 #include <asm/xen/hypercall.h> 17 18 #include <xen/interface/memory.h> 19 20 #include "xen-ops.h" 21 22 /* 23 * PVH variables. 24 * 25 * The variable xen_pvh needs to live in a data segment since it is used 26 * after startup_{32|64} is invoked, which will clear the .bss segment. 27 */ 28 bool __ro_after_init xen_pvh; 29 EXPORT_SYMBOL_GPL(xen_pvh); 30 31 /* 32 * Reserve e820 UNUSABLE regions to inflate the memory balloon. 33 * 34 * On PVH dom0 the host memory map is used, RAM regions available to dom0 are 35 * located as the same place as in the native memory map, but since dom0 gets 36 * less memory than the total amount of host RAM the ranges that can't be 37 * populated are converted from RAM -> UNUSABLE. Use such regions (up to the 38 * ratio signaled in EXTRA_MEM_RATIO) in order to inflate the balloon driver at 39 * boot. Doing so prevents the guest (even if just temporary) from using holes 40 * in the memory map in order to map grants or foreign addresses, and 41 * hopefully limits the risk of a clash with a device MMIO region. Ideally the 42 * hypervisor should notify us which memory ranges are suitable for creating 43 * foreign mappings, but that's not yet implemented. 44 */ 45 static void __init pvh_reserve_extra_memory(void) 46 { 47 struct boot_params *bootp = &boot_params; 48 unsigned int i, ram_pages = 0, extra_pages; 49 50 for (i = 0; i < bootp->e820_entries; i++) { 51 struct boot_e820_entry *e = &bootp->e820_table[i]; 52 53 if (e->type != E820_TYPE_RAM) 54 continue; 55 ram_pages += PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr); 56 } 57 58 /* Max amount of extra memory. */ 59 extra_pages = EXTRA_MEM_RATIO * ram_pages; 60 61 /* 62 * Convert UNUSABLE ranges to RAM and reserve them for foreign mapping 63 * purposes. 64 */ 65 for (i = 0; i < bootp->e820_entries && extra_pages; i++) { 66 struct boot_e820_entry *e = &bootp->e820_table[i]; 67 unsigned long pages; 68 69 if (e->type != E820_TYPE_UNUSABLE) 70 continue; 71 72 pages = min(extra_pages, 73 PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr)); 74 75 if (pages != (PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr))) { 76 struct boot_e820_entry *next; 77 78 if (bootp->e820_entries == 79 ARRAY_SIZE(bootp->e820_table)) 80 /* No space left to split - skip region. */ 81 continue; 82 83 /* Split entry. */ 84 next = e + 1; 85 memmove(next, e, 86 (bootp->e820_entries - i) * sizeof(*e)); 87 bootp->e820_entries++; 88 next->addr = PAGE_ALIGN(e->addr) + PFN_PHYS(pages); 89 e->size = next->addr - e->addr; 90 next->size -= e->size; 91 } 92 e->type = E820_TYPE_RAM; 93 extra_pages -= pages; 94 95 xen_add_extra_mem(PFN_UP(e->addr), pages); 96 } 97 } 98 99 static void __init pvh_arch_setup(void) 100 { 101 pvh_reserve_extra_memory(); 102 103 if (xen_initial_domain()) 104 xen_add_preferred_consoles(); 105 } 106 107 void __init xen_pvh_init(struct boot_params *boot_params) 108 { 109 u32 msr; 110 u64 pfn; 111 112 xen_pvh = 1; 113 xen_domain_type = XEN_HVM_DOMAIN; 114 xen_start_flags = pvh_start_info.flags; 115 116 msr = cpuid_ebx(xen_cpuid_base() + 2); 117 pfn = __pa(hypercall_page); 118 wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32)); 119 120 x86_init.oem.arch_setup = pvh_arch_setup; 121 x86_init.oem.banner = xen_banner; 122 123 xen_efi_init(boot_params); 124 125 if (xen_initial_domain()) { 126 struct xen_platform_op op = { 127 .cmd = XENPF_get_dom0_console, 128 }; 129 int ret = HYPERVISOR_platform_op(&op); 130 131 if (ret > 0) 132 xen_init_vga(&op.u.dom0_console, 133 min(ret * sizeof(char), 134 sizeof(op.u.dom0_console)), 135 &boot_params->screen_info); 136 } 137 } 138 139 void __init mem_map_via_hcall(struct boot_params *boot_params_p) 140 { 141 struct xen_memory_map memmap; 142 int rc; 143 144 memmap.nr_entries = ARRAY_SIZE(boot_params_p->e820_table); 145 set_xen_guest_handle(memmap.buffer, boot_params_p->e820_table); 146 rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); 147 if (rc) { 148 xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc); 149 BUG(); 150 } 151 boot_params_p->e820_entries = memmap.nr_entries; 152 } 153