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