Skip to content

Commit 9ad95bd

Browse files
committed
Merge tag 'for-linus-4.15-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen fixes from Juergen Gross: "This contains two fixes for running under Xen: - a fix avoiding resource conflicts between adding mmio areas and memory hotplug - a fix setting NX bits in page table entries copied from Xen when running a PV guest" * tag 'for-linus-4.15-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/balloon: Mark unallocated host memory as UNUSABLE x86-64/Xen: eliminate W+X mappings
2 parents fca0e39 + b3cf852 commit 9ad95bd

File tree

6 files changed

+159
-13
lines changed

6 files changed

+159
-13
lines changed

arch/x86/xen/enlighten.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
2+
#include <linux/bootmem.h>
3+
#endif
14
#include <linux/cpu.h>
25
#include <linux/kexec.h>
36

47
#include <xen/features.h>
58
#include <xen/page.h>
9+
#include <xen/interface/memory.h>
610

711
#include <asm/xen/hypercall.h>
812
#include <asm/xen/hypervisor.h>
@@ -331,3 +335,80 @@ void xen_arch_unregister_cpu(int num)
331335
}
332336
EXPORT_SYMBOL(xen_arch_unregister_cpu);
333337
#endif
338+
339+
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
340+
void __init arch_xen_balloon_init(struct resource *hostmem_resource)
341+
{
342+
struct xen_memory_map memmap;
343+
int rc;
344+
unsigned int i, last_guest_ram;
345+
phys_addr_t max_addr = PFN_PHYS(max_pfn);
346+
struct e820_table *xen_e820_table;
347+
const struct e820_entry *entry;
348+
struct resource *res;
349+
350+
if (!xen_initial_domain())
351+
return;
352+
353+
xen_e820_table = kmalloc(sizeof(*xen_e820_table), GFP_KERNEL);
354+
if (!xen_e820_table)
355+
return;
356+
357+
memmap.nr_entries = ARRAY_SIZE(xen_e820_table->entries);
358+
set_xen_guest_handle(memmap.buffer, xen_e820_table->entries);
359+
rc = HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap);
360+
if (rc) {
361+
pr_warn("%s: Can't read host e820 (%d)\n", __func__, rc);
362+
goto out;
363+
}
364+
365+
last_guest_ram = 0;
366+
for (i = 0; i < memmap.nr_entries; i++) {
367+
if (xen_e820_table->entries[i].addr >= max_addr)
368+
break;
369+
if (xen_e820_table->entries[i].type == E820_TYPE_RAM)
370+
last_guest_ram = i;
371+
}
372+
373+
entry = &xen_e820_table->entries[last_guest_ram];
374+
if (max_addr >= entry->addr + entry->size)
375+
goto out; /* No unallocated host RAM. */
376+
377+
hostmem_resource->start = max_addr;
378+
hostmem_resource->end = entry->addr + entry->size;
379+
380+
/*
381+
* Mark non-RAM regions between the end of dom0 RAM and end of host RAM
382+
* as unavailable. The rest of that region can be used for hotplug-based
383+
* ballooning.
384+
*/
385+
for (; i < memmap.nr_entries; i++) {
386+
entry = &xen_e820_table->entries[i];
387+
388+
if (entry->type == E820_TYPE_RAM)
389+
continue;
390+
391+
if (entry->addr >= hostmem_resource->end)
392+
break;
393+
394+
res = kzalloc(sizeof(*res), GFP_KERNEL);
395+
if (!res)
396+
goto out;
397+
398+
res->name = "Unavailable host RAM";
399+
res->start = entry->addr;
400+
res->end = (entry->addr + entry->size < hostmem_resource->end) ?
401+
entry->addr + entry->size : hostmem_resource->end;
402+
rc = insert_resource(hostmem_resource, res);
403+
if (rc) {
404+
pr_warn("%s: Can't insert [%llx - %llx) (%d)\n",
405+
__func__, res->start, res->end, rc);
406+
kfree(res);
407+
goto out;
408+
}
409+
}
410+
411+
out:
412+
kfree(xen_e820_table);
413+
}
414+
#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */

arch/x86/xen/enlighten_pv.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
#include "multicalls.h"
8989
#include "pmu.h"
9090

91+
#include "../kernel/cpu/cpu.h" /* get_cpu_cap() */
92+
9193
void *xen_initial_gdt;
9294

9395
static int xen_cpu_up_prepare_pv(unsigned int cpu);
@@ -1258,6 +1260,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
12581260
__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
12591261

12601262
/* Work out if we support NX */
1263+
get_cpu_cap(&boot_cpu_data);
12611264
x86_configure_nx();
12621265

12631266
/* Get mfn list */

arch/x86/xen/mmu_pv.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,18 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
19021902
/* Graft it onto L4[511][510] */
19031903
copy_page(level2_kernel_pgt, l2);
19041904

1905+
/*
1906+
* Zap execute permission from the ident map. Due to the sharing of
1907+
* L1 entries we need to do this in the L2.
1908+
*/
1909+
if (__supported_pte_mask & _PAGE_NX) {
1910+
for (i = 0; i < PTRS_PER_PMD; ++i) {
1911+
if (pmd_none(level2_ident_pgt[i]))
1912+
continue;
1913+
level2_ident_pgt[i] = pmd_set_flags(level2_ident_pgt[i], _PAGE_NX);
1914+
}
1915+
}
1916+
19051917
/* Copy the initial P->M table mappings if necessary. */
19061918
i = pgd_index(xen_start_info->mfn_list);
19071919
if (i && i < pgd_index(__START_KERNEL_map))

arch/x86/xen/setup.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,6 @@ char * __init xen_memory_setup(void)
808808
addr = xen_e820_table.entries[0].addr;
809809
size = xen_e820_table.entries[0].size;
810810
while (i < xen_e820_table.nr_entries) {
811-
bool discard = false;
812811

813812
chunk_size = size;
814813
type = xen_e820_table.entries[i].type;
@@ -824,11 +823,10 @@ char * __init xen_memory_setup(void)
824823
xen_add_extra_mem(pfn_s, n_pfns);
825824
xen_max_p2m_pfn = pfn_s + n_pfns;
826825
} else
827-
discard = true;
826+
type = E820_TYPE_UNUSABLE;
828827
}
829828

830-
if (!discard)
831-
xen_align_and_add_e820_region(addr, chunk_size, type);
829+
xen_align_and_add_e820_region(addr, chunk_size, type);
832830

833831
addr += chunk_size;
834832
size -= chunk_size;

drivers/xen/balloon.c

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,25 @@ static void release_memory_resource(struct resource *resource)
257257
kfree(resource);
258258
}
259259

260+
/*
261+
* Host memory not allocated to dom0. We can use this range for hotplug-based
262+
* ballooning.
263+
*
264+
* It's a type-less resource. Setting IORESOURCE_MEM will make resource
265+
* management algorithms (arch_remove_reservations()) look into guest e820,
266+
* which we don't want.
267+
*/
268+
static struct resource hostmem_resource = {
269+
.name = "Host RAM",
270+
};
271+
272+
void __attribute__((weak)) __init arch_xen_balloon_init(struct resource *res)
273+
{}
274+
260275
static struct resource *additional_memory_resource(phys_addr_t size)
261276
{
262-
struct resource *res;
263-
int ret;
277+
struct resource *res, *res_hostmem;
278+
int ret = -ENOMEM;
264279

265280
res = kzalloc(sizeof(*res), GFP_KERNEL);
266281
if (!res)
@@ -269,13 +284,42 @@ static struct resource *additional_memory_resource(phys_addr_t size)
269284
res->name = "System RAM";
270285
res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
271286

272-
ret = allocate_resource(&iomem_resource, res,
273-
size, 0, -1,
274-
PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
275-
if (ret < 0) {
276-
pr_err("Cannot allocate new System RAM resource\n");
277-
kfree(res);
278-
return NULL;
287+
res_hostmem = kzalloc(sizeof(*res), GFP_KERNEL);
288+
if (res_hostmem) {
289+
/* Try to grab a range from hostmem */
290+
res_hostmem->name = "Host memory";
291+
ret = allocate_resource(&hostmem_resource, res_hostmem,
292+
size, 0, -1,
293+
PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
294+
}
295+
296+
if (!ret) {
297+
/*
298+
* Insert this resource into iomem. Because hostmem_resource
299+
* tracks portion of guest e820 marked as UNUSABLE noone else
300+
* should try to use it.
301+
*/
302+
res->start = res_hostmem->start;
303+
res->end = res_hostmem->end;
304+
ret = insert_resource(&iomem_resource, res);
305+
if (ret < 0) {
306+
pr_err("Can't insert iomem_resource [%llx - %llx]\n",
307+
res->start, res->end);
308+
release_memory_resource(res_hostmem);
309+
res_hostmem = NULL;
310+
res->start = res->end = 0;
311+
}
312+
}
313+
314+
if (ret) {
315+
ret = allocate_resource(&iomem_resource, res,
316+
size, 0, -1,
317+
PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
318+
if (ret < 0) {
319+
pr_err("Cannot allocate new System RAM resource\n");
320+
kfree(res);
321+
return NULL;
322+
}
279323
}
280324

281325
#ifdef CONFIG_SPARSEMEM
@@ -287,6 +331,7 @@ static struct resource *additional_memory_resource(phys_addr_t size)
287331
pr_err("New System RAM resource outside addressable RAM (%lu > %lu)\n",
288332
pfn, limit);
289333
release_memory_resource(res);
334+
release_memory_resource(res_hostmem);
290335
return NULL;
291336
}
292337
}
@@ -765,6 +810,8 @@ static int __init balloon_init(void)
765810
set_online_page_callback(&xen_online_page);
766811
register_memory_notifier(&xen_memory_nb);
767812
register_sysctl_table(xen_root);
813+
814+
arch_xen_balloon_init(&hostmem_resource);
768815
#endif
769816

770817
#ifdef CONFIG_XEN_PV

include/xen/balloon.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,8 @@ static inline void xen_balloon_init(void)
4444
{
4545
}
4646
#endif
47+
48+
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
49+
struct resource;
50+
void arch_xen_balloon_init(struct resource *hostmem_resource);
51+
#endif

0 commit comments

Comments
 (0)