/* SPDX-License-Identifier: GPL-2.0-only */ /* * I/O page allocation * * Copyright (c) 2021 IBM Corp * * Authors: * Pierre Morel * * Using this interface provide host access to the allocated pages in * case the guest is a protected guest. * This is needed for I/O buffers. * */ #include #include #include #include #include #include #include #include static int share_pages(void *p, int count) { int i = 0; for (i = 0; i < count; i++, p += PAGE_SIZE) if (uv_set_shared((unsigned long)p)) break; return i; } static void unshare_pages(void *p, int count) { int i; for (i = count; i > 0; i--, p += PAGE_SIZE) uv_remove_shared((unsigned long)p); } void *alloc_io_mem(int size, int flags) { int order = get_order(PAGE_ALIGN(size) >> PAGE_SHIFT); void *p; int n; assert(size); p = alloc_pages_flags(order, AREA_DMA31 | flags); if (!p || !uv_os_is_guest()) return p; n = share_pages(p, 1 << order); if (n == 1 << order) return p; unshare_pages(p, n); free_pages(p); return NULL; } void free_io_mem(void *p, int size) { int order = get_order(PAGE_ALIGN(size) >> PAGE_SHIFT); assert(IS_ALIGNED((uintptr_t)p, PAGE_SIZE)); if (uv_os_is_guest()) unshare_pages(p, 1 << order); free_pages(p); }