~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/xen/enlighten_pvh.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php