xen: branch for v5.9-rc1

-----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQRTLbB6QfY48x44uB6AXGG7T9hjvgUCXyzfRgAKCRCAXGG7T9hj
 vtYfAQCiqT8MBvwTpqsiu2si0ceyBZ7y8cuEqOMvqPTH0N1bYQD+JD1mMN2WjR0d
 nKWwy/i8lXudBsDqY4N81WWBh+FMPA4=
 =Lb6P
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-5.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen updates from Juergen Gross:

 - two trivial comment fixes

 - a small series for the Xen balloon driver fixing some issues

 - a series of the Xen privcmd driver targeting elimination of using
   get_user_pages*() in this driver

 - a series for the Xen swiotlb driver cleaning it up and adding support
   for letting the kernel run as dom0 on Rpi4

* tag 'for-linus-5.9-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/arm: call dma_to_phys on the dma_addr_t parameter of dma_cache_maint
  xen/arm: introduce phys/dma translations in xen_dma_sync_for_*
  swiotlb-xen: introduce phys_to_dma/dma_to_phys translations
  swiotlb-xen: remove XEN_PFN_PHYS
  swiotlb-xen: add struct device * parameter to is_xen_swiotlb_buffer
  swiotlb-xen: add struct device * parameter to xen_dma_sync_for_device
  swiotlb-xen: add struct device * parameter to xen_dma_sync_for_cpu
  swiotlb-xen: add struct device * parameter to xen_bus_to_phys
  swiotlb-xen: add struct device * parameter to xen_phys_to_bus
  swiotlb-xen: remove start_dma_addr
  swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses
  Revert "xen/balloon: Fix crash when ballooning on x86 32 bit PAE"
  xen/balloon: make the balloon wait interruptible
  xen/balloon: fix accounting in alloc_xenballooned_pages error path
  xen: hypercall.h: fix duplicated word
  xen/gntdev: gntdev.h: drop a duplicated word
  xen/privcmd: Convert get_user_pages*() to pin_user_pages*()
  xen/privcmd: Mark pages as dirty
  xen/privcmd: Corrected error handling path
This commit is contained in:
Linus Torvalds 2020-08-07 10:53:02 -07:00
commit e51418191f
8 changed files with 120 additions and 106 deletions

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/cpu.h>
#include <linux/dma-direct.h>
#include <linux/dma-noncoherent.h>
#include <linux/gfp.h>
#include <linux/highmem.h>
@ -42,15 +43,18 @@ unsigned long xen_get_swiotlb_free_pages(unsigned int order)
static bool hypercall_cflush = false;
/* buffers in highmem or foreign pages cannot cross page boundaries */
static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op)
static void dma_cache_maint(struct device *dev, dma_addr_t handle,
size_t size, u32 op)
{
struct gnttab_cache_flush cflush;
cflush.a.dev_bus_addr = handle & XEN_PAGE_MASK;
cflush.offset = xen_offset_in_page(handle);
cflush.op = op;
handle &= XEN_PAGE_MASK;
do {
cflush.a.dev_bus_addr = dma_to_phys(dev, handle);
if (size + cflush.offset > XEN_PAGE_SIZE)
cflush.length = XEN_PAGE_SIZE - cflush.offset;
else
@ -59,7 +63,7 @@ static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op)
HYPERVISOR_grant_table_op(GNTTABOP_cache_flush, &cflush, 1);
cflush.offset = 0;
cflush.a.dev_bus_addr += cflush.length;
handle += cflush.length;
size -= cflush.length;
} while (size);
}
@ -71,24 +75,20 @@ static void dma_cache_maint(dma_addr_t handle, size_t size, u32 op)
* pfn_valid returns true the pages is local and we can use the native
* dma-direct functions, otherwise we call the Xen specific version.
*/
void xen_dma_sync_for_cpu(dma_addr_t handle, phys_addr_t paddr, size_t size,
enum dma_data_direction dir)
void xen_dma_sync_for_cpu(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
if (pfn_valid(PFN_DOWN(handle)))
arch_sync_dma_for_cpu(paddr, size, dir);
else if (dir != DMA_TO_DEVICE)
dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL);
if (dir != DMA_TO_DEVICE)
dma_cache_maint(dev, handle, size, GNTTAB_CACHE_INVAL);
}
void xen_dma_sync_for_device(dma_addr_t handle, phys_addr_t paddr, size_t size,
enum dma_data_direction dir)
void xen_dma_sync_for_device(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
if (pfn_valid(PFN_DOWN(handle)))
arch_sync_dma_for_device(paddr, size, dir);
else if (dir == DMA_FROM_DEVICE)
dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL);
if (dir == DMA_FROM_DEVICE)
dma_cache_maint(dev, handle, size, GNTTAB_CACHE_INVAL);
else
dma_cache_maint(handle, size, GNTTAB_CACHE_CLEAN);
dma_cache_maint(dev, handle, size, GNTTAB_CACHE_CLEAN);
}
bool xen_arch_need_swiotlb(struct device *dev,
@ -96,7 +96,7 @@ bool xen_arch_need_swiotlb(struct device *dev,
dma_addr_t dev_addr)
{
unsigned int xen_pfn = XEN_PFN_DOWN(phys);
unsigned int bfn = XEN_PFN_DOWN(dev_addr);
unsigned int bfn = XEN_PFN_DOWN(dma_to_phys(dev, dev_addr));
/*
* The swiotlb buffer should be used if

View File

@ -82,7 +82,7 @@ struct xen_dm_op_buf;
* - clobber the rest
*
* The result certainly isn't pretty, and it really shows up cpp's
* weakness as as macro language. Sorry. (But let's just give thanks
* weakness as a macro language. Sorry. (But let's just give thanks
* there aren't more than 5 arguments...)
*/

View File

@ -266,20 +266,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
return NULL;
}
#ifdef CONFIG_SPARSEMEM
{
unsigned long limit = 1UL << (MAX_PHYSMEM_BITS - PAGE_SHIFT);
unsigned long pfn = res->start >> PAGE_SHIFT;
if (pfn > limit) {
pr_err("New System RAM resource outside addressable RAM (%lu > %lu)\n",
pfn, limit);
release_memory_resource(res);
return NULL;
}
}
#endif
return res;
}
@ -568,11 +554,13 @@ static int add_ballooned_pages(int nr_pages)
if (xen_hotplug_unpopulated) {
st = reserve_additional_memory();
if (st != BP_ECANCELED) {
int rc;
mutex_unlock(&balloon_mutex);
wait_event(balloon_wq,
rc = wait_event_interruptible(balloon_wq,
!list_empty(&ballooned_pages));
mutex_lock(&balloon_mutex);
return 0;
return rc ? -ENOMEM : 0;
}
}
@ -630,6 +618,12 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages)
out_undo:
mutex_unlock(&balloon_mutex);
free_xenballooned_pages(pgno, pages);
/*
* NB: free_xenballooned_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(alloc_xenballooned_pages);

View File

@ -580,13 +580,13 @@ static long privcmd_ioctl_mmap_batch(
static int lock_pages(
struct privcmd_dm_op_buf kbufs[], unsigned int num,
struct page *pages[], unsigned int nr_pages)
struct page *pages[], unsigned int nr_pages, unsigned int *pinned)
{
unsigned int i;
for (i = 0; i < num; i++) {
unsigned int requested;
int pinned;
int page_count;
requested = DIV_ROUND_UP(
offset_in_page(kbufs[i].uptr) + kbufs[i].size,
@ -594,14 +594,15 @@ static int lock_pages(
if (requested > nr_pages)
return -ENOSPC;
pinned = get_user_pages_fast(
page_count = pin_user_pages_fast(
(unsigned long) kbufs[i].uptr,
requested, FOLL_WRITE, pages);
if (pinned < 0)
return pinned;
if (page_count < 0)
return page_count;
nr_pages -= pinned;
pages += pinned;
*pinned += page_count;
nr_pages -= page_count;
pages += page_count;
}
return 0;
@ -609,15 +610,7 @@ static int lock_pages(
static void unlock_pages(struct page *pages[], unsigned int nr_pages)
{
unsigned int i;
if (!pages)
return;
for (i = 0; i < nr_pages; i++) {
if (pages[i])
put_page(pages[i]);
}
unpin_user_pages_dirty_lock(pages, nr_pages, true);
}
static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
@ -630,6 +623,7 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
struct xen_dm_op_buf *xbufs = NULL;
unsigned int i;
long rc;
unsigned int pinned = 0;
if (copy_from_user(&kdata, udata, sizeof(kdata)))
return -EFAULT;
@ -683,9 +677,11 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
goto out;
}
rc = lock_pages(kbufs, kdata.num, pages, nr_pages);
if (rc)
rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &pinned);
if (rc < 0) {
nr_pages = pinned;
goto out;
}
for (i = 0; i < kdata.num; i++) {
set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);

View File

@ -52,37 +52,39 @@ static unsigned long xen_io_tlb_nslabs;
* Quick lookup value of the bus address of the IOTLB.
*/
static u64 start_dma_addr;
/*
* Both of these functions should avoid XEN_PFN_PHYS because phys_addr_t
* can be 32bit when dma_addr_t is 64bit leading to a loss in
* information if the shift is done before casting to 64bit.
*/
static inline dma_addr_t xen_phys_to_bus(phys_addr_t paddr)
static inline phys_addr_t xen_phys_to_bus(struct device *dev, phys_addr_t paddr)
{
unsigned long bfn = pfn_to_bfn(XEN_PFN_DOWN(paddr));
dma_addr_t dma = (dma_addr_t)bfn << XEN_PAGE_SHIFT;
phys_addr_t baddr = (phys_addr_t)bfn << XEN_PAGE_SHIFT;
dma |= paddr & ~XEN_PAGE_MASK;
return dma;
baddr |= paddr & ~XEN_PAGE_MASK;
return baddr;
}
static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr)
static inline dma_addr_t xen_phys_to_dma(struct device *dev, phys_addr_t paddr)
{
return phys_to_dma(dev, xen_phys_to_bus(dev, paddr));
}
static inline phys_addr_t xen_bus_to_phys(struct device *dev,
phys_addr_t baddr)
{
unsigned long xen_pfn = bfn_to_pfn(XEN_PFN_DOWN(baddr));
dma_addr_t dma = (dma_addr_t)xen_pfn << XEN_PAGE_SHIFT;
phys_addr_t paddr = dma;
paddr |= baddr & ~XEN_PAGE_MASK;
phys_addr_t paddr = (xen_pfn << XEN_PAGE_SHIFT) |
(baddr & ~XEN_PAGE_MASK);
return paddr;
}
static inline dma_addr_t xen_virt_to_bus(void *address)
static inline phys_addr_t xen_dma_to_phys(struct device *dev,
dma_addr_t dma_addr)
{
return xen_phys_to_bus(virt_to_phys(address));
return xen_bus_to_phys(dev, dma_to_phys(dev, dma_addr));
}
static inline dma_addr_t xen_virt_to_bus(struct device *dev, void *address)
{
return xen_phys_to_dma(dev, virt_to_phys(address));
}
static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
@ -99,11 +101,11 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
return 0;
}
static int is_xen_swiotlb_buffer(dma_addr_t dma_addr)
static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
{
unsigned long bfn = XEN_PFN_DOWN(dma_addr);
unsigned long bfn = XEN_PFN_DOWN(dma_to_phys(dev, dma_addr));
unsigned long xen_pfn = bfn_to_local_pfn(bfn);
phys_addr_t paddr = XEN_PFN_PHYS(xen_pfn);
phys_addr_t paddr = (phys_addr_t)xen_pfn << XEN_PAGE_SHIFT;
/* If the address is outside our domain, it CAN
* have the same virtual address as another address
@ -241,7 +243,6 @@ int __ref xen_swiotlb_init(int verbose, bool early)
m_ret = XEN_SWIOTLB_EFIXUP;
goto error;
}
start_dma_addr = xen_virt_to_bus(xen_io_tlb_start);
if (early) {
if (swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs,
verbose))
@ -307,12 +308,12 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
if (hwdev && hwdev->coherent_dma_mask)
dma_mask = hwdev->coherent_dma_mask;
/* At this point dma_handle is the physical address, next we are
/* At this point dma_handle is the dma address, next we are
* going to set it to the machine address.
* Do not use virt_to_phys(ret) because on ARM it doesn't correspond
* to *dma_handle. */
phys = *dma_handle;
dev_addr = xen_phys_to_bus(phys);
phys = dma_to_phys(hwdev, *dma_handle);
dev_addr = xen_phys_to_dma(hwdev, phys);
if (((dev_addr + size - 1 <= dma_mask)) &&
!range_straddles_page_boundary(phys, size))
*dma_handle = dev_addr;
@ -322,6 +323,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs);
return NULL;
}
*dma_handle = phys_to_dma(hwdev, *dma_handle);
SetPageXenRemapped(virt_to_page(ret));
}
memset(ret, 0, size);
@ -335,23 +337,30 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
int order = get_order(size);
phys_addr_t phys;
u64 dma_mask = DMA_BIT_MASK(32);
struct page *page;
if (hwdev && hwdev->coherent_dma_mask)
dma_mask = hwdev->coherent_dma_mask;
/* do not use virt_to_phys because on ARM it doesn't return you the
* physical address */
phys = xen_bus_to_phys(dev_addr);
phys = xen_dma_to_phys(hwdev, dev_addr);
/* Convert the size to actually allocated. */
size = 1UL << (order + XEN_PAGE_SHIFT);
if (is_vmalloc_addr(vaddr))
page = vmalloc_to_page(vaddr);
else
page = virt_to_page(vaddr);
if (!WARN_ON((dev_addr + size - 1 > dma_mask) ||
range_straddles_page_boundary(phys, size)) &&
TestClearPageXenRemapped(virt_to_page(vaddr)))
TestClearPageXenRemapped(page))
xen_destroy_contiguous_region(phys, order);
xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs);
xen_free_coherent_pages(hwdev, size, vaddr, phys_to_dma(hwdev, phys),
attrs);
}
/*
@ -367,7 +376,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
unsigned long attrs)
{
phys_addr_t map, phys = page_to_phys(page) + offset;
dma_addr_t dev_addr = xen_phys_to_bus(phys);
dma_addr_t dev_addr = xen_phys_to_dma(dev, phys);
BUG_ON(dir == DMA_NONE);
/*
@ -386,13 +395,13 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
*/
trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
map = swiotlb_tbl_map_single(dev, start_dma_addr, phys,
size, size, dir, attrs);
map = swiotlb_tbl_map_single(dev, virt_to_phys(xen_io_tlb_start),
phys, size, size, dir, attrs);
if (map == (phys_addr_t)DMA_MAPPING_ERROR)
return DMA_MAPPING_ERROR;
phys = map;
dev_addr = xen_phys_to_bus(map);
dev_addr = xen_phys_to_dma(dev, map);
/*
* Ensure that the address returned is DMA'ble
@ -404,8 +413,12 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
}
done:
if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
xen_dma_sync_for_device(dev_addr, phys, size, dir);
if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
if (pfn_valid(PFN_DOWN(dma_to_phys(dev, dev_addr))))
arch_sync_dma_for_device(phys, size, dir);
else
xen_dma_sync_for_device(dev, dev_addr, size, dir);
}
return dev_addr;
}
@ -420,15 +433,19 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
static void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
phys_addr_t paddr = xen_bus_to_phys(dev_addr);
phys_addr_t paddr = xen_dma_to_phys(hwdev, dev_addr);
BUG_ON(dir == DMA_NONE);
if (!dev_is_dma_coherent(hwdev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
xen_dma_sync_for_cpu(dev_addr, paddr, size, dir);
if (!dev_is_dma_coherent(hwdev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
if (pfn_valid(PFN_DOWN(dma_to_phys(hwdev, dev_addr))))
arch_sync_dma_for_cpu(paddr, size, dir);
else
xen_dma_sync_for_cpu(hwdev, dev_addr, size, dir);
}
/* NOTE: We use dev_addr here, not paddr! */
if (is_xen_swiotlb_buffer(dev_addr))
if (is_xen_swiotlb_buffer(hwdev, dev_addr))
swiotlb_tbl_unmap_single(hwdev, paddr, size, size, dir, attrs);
}
@ -436,12 +453,16 @@ static void
xen_swiotlb_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir)
{
phys_addr_t paddr = xen_bus_to_phys(dma_addr);
phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);
if (!dev_is_dma_coherent(dev))
xen_dma_sync_for_cpu(dma_addr, paddr, size, dir);
if (!dev_is_dma_coherent(dev)) {
if (pfn_valid(PFN_DOWN(dma_to_phys(dev, dma_addr))))
arch_sync_dma_for_cpu(paddr, size, dir);
else
xen_dma_sync_for_cpu(dev, dma_addr, size, dir);
}
if (is_xen_swiotlb_buffer(dma_addr))
if (is_xen_swiotlb_buffer(dev, dma_addr))
swiotlb_tbl_sync_single(dev, paddr, size, dir, SYNC_FOR_CPU);
}
@ -449,13 +470,17 @@ static void
xen_swiotlb_sync_single_for_device(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir)
{
phys_addr_t paddr = xen_bus_to_phys(dma_addr);
phys_addr_t paddr = xen_dma_to_phys(dev, dma_addr);
if (is_xen_swiotlb_buffer(dma_addr))
if (is_xen_swiotlb_buffer(dev, dma_addr))
swiotlb_tbl_sync_single(dev, paddr, size, dir, SYNC_FOR_DEVICE);
if (!dev_is_dma_coherent(dev))
xen_dma_sync_for_device(dma_addr, paddr, size, dir);
if (!dev_is_dma_coherent(dev)) {
if (pfn_valid(PFN_DOWN(dma_to_phys(dev, dma_addr))))
arch_sync_dma_for_device(paddr, size, dir);
else
xen_dma_sync_for_device(dev, dma_addr, size, dir);
}
}
/*
@ -536,7 +561,7 @@ xen_swiotlb_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
static int
xen_swiotlb_dma_supported(struct device *hwdev, u64 mask)
{
return xen_virt_to_bus(xen_io_tlb_end - 1) <= mask;
return xen_virt_to_bus(hwdev, xen_io_tlb_end - 1) <= mask;
}
const struct dma_map_ops xen_swiotlb_dma_ops = {

View File

@ -66,7 +66,7 @@ struct ioctl_gntdev_map_grant_ref {
/*
* Removes the grant references from the mapping table of an instance of
* of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
* gntdev. N.B. munmap() must be called on the relevant virtual address(es)
* before this ioctl is called, or an error will result.
*/
#define IOCTL_GNTDEV_UNMAP_GRANT_REF \

View File

@ -24,7 +24,6 @@
#define XEN_PFN_DOWN(x) ((x) >> XEN_PAGE_SHIFT)
#define XEN_PFN_UP(x) (((x) + XEN_PAGE_SIZE-1) >> XEN_PAGE_SHIFT)
#define XEN_PFN_PHYS(x) ((phys_addr_t)(x) << XEN_PAGE_SHIFT)
#include <asm/xen/page.h>

View File

@ -4,10 +4,10 @@
#include <linux/swiotlb.h>
void xen_dma_sync_for_cpu(dma_addr_t handle, phys_addr_t paddr, size_t size,
enum dma_data_direction dir);
void xen_dma_sync_for_device(dma_addr_t handle, phys_addr_t paddr, size_t size,
enum dma_data_direction dir);
void xen_dma_sync_for_cpu(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir);
void xen_dma_sync_for_device(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir);
extern int xen_swiotlb_init(int verbose, bool early);
extern const struct dma_map_ops xen_swiotlb_dma_ops;