diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-01-13 03:42:00 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-01-13 03:42:00 +0300 |
commit | ce990f1de0bc6ff3de43d385e0985efa980fba24 (patch) | |
tree | 44e2c7054f9cf324a090bb0423d837a4f02d2196 /drivers | |
parent | 64ad9461521b1a357846ef6cedc4bccd48a046e0 (diff) | |
parent | 54bb4a91b281e1b21235a4bc175e1293e787c016 (diff) | |
download | linux-ce990f1de0bc6ff3de43d385e0985efa980fba24.tar.xz |
Merge tag 'for-linus-5.17-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from Juergen Gross:
- a fix for the Xen gntdev driver
- a fix for running as Xen dom0 booted via EFI and the EFI framebuffer
being located above 4GB
- a series for support of mapping other guest's memory by using zone
device when running as Xen guest on Arm
* tag 'for-linus-5.17-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
dt-bindings: xen: Clarify "reg" purpose
arm/xen: Read extended regions from DT and init Xen resource
xen/unpopulated-alloc: Add mechanism to use Xen resource
xen/balloon: Bring alloc(free)_xenballooned_pages helpers back
arm/xen: Switch to use gnttab_setup_auto_xlat_frames() for DT
xen/unpopulated-alloc: Drop check for virt_addr_valid() in fill_list()
xen/x86: obtain upper 32 bits of video frame buffer address for Dom0
xen/gntdev: fix unmap notification order
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/xen/Kconfig | 2 | ||||
-rw-r--r-- | drivers/xen/balloon.c | 20 | ||||
-rw-r--r-- | drivers/xen/gntdev.c | 6 | ||||
-rw-r--r-- | drivers/xen/unpopulated-alloc.c | 87 |
4 files changed, 95 insertions, 20 deletions
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 33e941e40082..120d32f164ac 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -327,7 +327,7 @@ config XEN_FRONT_PGDIR_SHBUF config XEN_UNPOPULATED_ALLOC bool "Use unpopulated memory ranges for guest mappings" - depends on X86 && ZONE_DEVICE + depends on ZONE_DEVICE default XEN_BACKEND || XEN_GNTDEV || XEN_DOM0 help Use unpopulated memory ranges in order to create mappings for guest diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index ba2ea11e0d3d..a2c4fc49c483 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -581,7 +581,6 @@ void balloon_set_new_target(unsigned long target) } EXPORT_SYMBOL_GPL(balloon_set_new_target); -#ifndef CONFIG_XEN_UNPOPULATED_ALLOC static int add_ballooned_pages(unsigned int nr_pages) { enum bp_state st; @@ -610,12 +609,12 @@ static int add_ballooned_pages(unsigned int nr_pages) } /** - * xen_alloc_unpopulated_pages - get pages that have been ballooned out + * xen_alloc_ballooned_pages - get pages that have been ballooned out * @nr_pages: Number of pages to get * @pages: pages returned * @return 0 on success, error otherwise */ -int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages) +int xen_alloc_ballooned_pages(unsigned int nr_pages, struct page **pages) { unsigned int pgno = 0; struct page *page; @@ -652,23 +651,23 @@ int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages) return 0; out_undo: mutex_unlock(&balloon_mutex); - xen_free_unpopulated_pages(pgno, pages); + xen_free_ballooned_pages(pgno, pages); /* - * NB: free_xenballooned_pages will only subtract pgno pages, but since + * NB: xen_free_ballooned_pages will only subtract pgno pages, but since * target_unpopulated is incremented with nr_pages at the start we need * to remove the remaining ones also, or accounting will be screwed. */ balloon_stats.target_unpopulated -= nr_pages - pgno; return ret; } -EXPORT_SYMBOL(xen_alloc_unpopulated_pages); +EXPORT_SYMBOL(xen_alloc_ballooned_pages); /** - * xen_free_unpopulated_pages - return pages retrieved with get_ballooned_pages + * xen_free_ballooned_pages - return pages retrieved with get_ballooned_pages * @nr_pages: Number of pages * @pages: pages to return */ -void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages) +void xen_free_ballooned_pages(unsigned int nr_pages, struct page **pages) { unsigned int i; @@ -687,9 +686,9 @@ void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages) mutex_unlock(&balloon_mutex); } -EXPORT_SYMBOL(xen_free_unpopulated_pages); +EXPORT_SYMBOL(xen_free_ballooned_pages); -#if defined(CONFIG_XEN_PV) +#if defined(CONFIG_XEN_PV) && !defined(CONFIG_XEN_UNPOPULATED_ALLOC) static void __init balloon_add_region(unsigned long start_pfn, unsigned long pages) { @@ -712,7 +711,6 @@ static void __init balloon_add_region(unsigned long start_pfn, balloon_stats.total_pages += extra_pfn_end - start_pfn; } #endif -#endif static int __init balloon_init(void) { diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index fec1b6537166..59ffea800079 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -250,13 +250,13 @@ void gntdev_put_map(struct gntdev_priv *priv, struct gntdev_grant_map *map) if (!refcount_dec_and_test(&map->users)) return; + if (map->pages && !use_ptemod) + unmap_grant_pages(map, 0, map->count); + if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) { notify_remote_via_evtchn(map->notify.event); evtchn_put(map->notify.event); } - - if (map->pages && !use_ptemod) - unmap_grant_pages(map, 0, map->count); gntdev_free_map(map); } diff --git a/drivers/xen/unpopulated-alloc.c b/drivers/xen/unpopulated-alloc.c index 87e6b7db892f..a8b41057c382 100644 --- a/drivers/xen/unpopulated-alloc.c +++ b/drivers/xen/unpopulated-alloc.c @@ -8,6 +8,7 @@ #include <asm/page.h> +#include <xen/balloon.h> #include <xen/page.h> #include <xen/xen.h> @@ -15,13 +16,29 @@ static DEFINE_MUTEX(list_lock); static struct page *page_list; static unsigned int list_count; +static struct resource *target_resource; + +/* + * If arch is not happy with system "iomem_resource" being used for + * the region allocation it can provide it's own view by creating specific + * Xen resource with unused regions of guest physical address space provided + * by the hypervisor. + */ +int __weak __init arch_xen_unpopulated_init(struct resource **res) +{ + *res = &iomem_resource; + + return 0; +} + static int fill_list(unsigned int nr_pages) { struct dev_pagemap *pgmap; - struct resource *res; + struct resource *res, *tmp_res = NULL; void *vaddr; unsigned int i, alloc_pages = round_up(nr_pages, PAGES_PER_SECTION); - int ret = -ENOMEM; + struct range mhp_range; + int ret; res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -30,14 +47,40 @@ static int fill_list(unsigned int nr_pages) res->name = "Xen scratch"; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - ret = allocate_resource(&iomem_resource, res, - alloc_pages * PAGE_SIZE, 0, -1, + mhp_range = mhp_get_pluggable_range(true); + + ret = allocate_resource(target_resource, res, + alloc_pages * PAGE_SIZE, mhp_range.start, mhp_range.end, PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL); if (ret < 0) { pr_err("Cannot allocate new IOMEM resource\n"); goto err_resource; } + /* + * Reserve the region previously allocated from Xen resource to avoid + * re-using it by someone else. + */ + if (target_resource != &iomem_resource) { + tmp_res = kzalloc(sizeof(*tmp_res), GFP_KERNEL); + if (!tmp_res) { + ret = -ENOMEM; + goto err_insert; + } + + tmp_res->name = res->name; + tmp_res->start = res->start; + tmp_res->end = res->end; + tmp_res->flags = res->flags; + + ret = request_resource(&iomem_resource, tmp_res); + if (ret < 0) { + pr_err("Cannot request resource %pR (%d)\n", tmp_res, ret); + kfree(tmp_res); + goto err_insert; + } + } + pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL); if (!pgmap) { ret = -ENOMEM; @@ -85,7 +128,6 @@ static int fill_list(unsigned int nr_pages) for (i = 0; i < alloc_pages; i++) { struct page *pg = virt_to_page(vaddr + PAGE_SIZE * i); - BUG_ON(!virt_addr_valid(vaddr + PAGE_SIZE * i)); pg->zone_device_data = page_list; page_list = pg; list_count++; @@ -96,6 +138,11 @@ static int fill_list(unsigned int nr_pages) err_memremap: kfree(pgmap); err_pgmap: + if (tmp_res) { + release_resource(tmp_res); + kfree(tmp_res); + } +err_insert: release_resource(res); err_resource: kfree(res); @@ -113,6 +160,14 @@ int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages) unsigned int i; int ret = 0; + /* + * Fallback to default behavior if we do not have any suitable resource + * to allocate required region from and as the result we won't be able to + * construct pages. + */ + if (!target_resource) + return xen_alloc_ballooned_pages(nr_pages, pages); + mutex_lock(&list_lock); if (list_count < nr_pages) { ret = fill_list(nr_pages - list_count); @@ -160,6 +215,11 @@ void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages) { unsigned int i; + if (!target_resource) { + xen_free_ballooned_pages(nr_pages, pages); + return; + } + mutex_lock(&list_lock); for (i = 0; i < nr_pages; i++) { pages[i]->zone_device_data = page_list; @@ -202,3 +262,20 @@ static int __init init(void) } subsys_initcall(init); #endif + +static int __init unpopulated_init(void) +{ + int ret; + + if (!xen_domain()) + return -ENODEV; + + ret = arch_xen_unpopulated_init(&target_resource); + if (ret) { + pr_err("xen:unpopulated: Cannot initialize target resource\n"); + target_resource = NULL; + } + + return ret; +} +early_initcall(unpopulated_init); |