mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
With the Xen side of this interface (soon to be) fixed to return real sizes, userspace needs to be able to make the query. Introduce xenforeignmemory_resource_size() for the purpose, bumping the library minor version. Update both all osdep_xenforeignmemory_map_resource() implementations to understand size requests, skip the mmap() operation, and copy back the nr_frames field. For NetBSD, also fix up the ioctl() error path to issue an unmap(), which was overlooked by c/s 4a64e2bb39 "libs/foreignmemory: Implement on NetBSD". Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Paul Durrant <paul@xen.org> Acked-by: Wei Liu <wl@xen.org>
218 lines
5.3 KiB
C
218 lines
5.3 KiB
C
/*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include "private.h"
|
|
|
|
static int all_restrict_cb(Xentoolcore__Active_Handle *ah, domid_t domid) {
|
|
xenforeignmemory_handle *fmem = CONTAINER_OF(ah, *fmem, tc_ah);
|
|
|
|
if (fmem->fd < 0)
|
|
/* just in case */
|
|
return 0;
|
|
|
|
return xenforeignmemory_restrict(fmem, domid);
|
|
}
|
|
|
|
xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger,
|
|
unsigned open_flags)
|
|
{
|
|
xenforeignmemory_handle *fmem = malloc(sizeof(*fmem));
|
|
int rc;
|
|
|
|
if (!fmem) return NULL;
|
|
|
|
fmem->fd = -1;
|
|
fmem->logger = logger;
|
|
fmem->logger_tofree = NULL;
|
|
|
|
fmem->tc_ah.restrict_callback = all_restrict_cb;
|
|
xentoolcore__register_active_handle(&fmem->tc_ah);
|
|
|
|
if (!fmem->logger) {
|
|
fmem->logger = fmem->logger_tofree =
|
|
(xentoollog_logger*)
|
|
xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
|
|
if (!fmem->logger) goto err;
|
|
}
|
|
|
|
rc = osdep_xenforeignmemory_open(fmem);
|
|
if ( rc < 0 ) goto err;
|
|
|
|
return fmem;
|
|
|
|
err:
|
|
xentoolcore__deregister_active_handle(&fmem->tc_ah);
|
|
osdep_xenforeignmemory_close(fmem);
|
|
xtl_logger_destroy(fmem->logger_tofree);
|
|
free(fmem);
|
|
return NULL;
|
|
}
|
|
|
|
int xenforeignmemory_close(xenforeignmemory_handle *fmem)
|
|
{
|
|
int rc;
|
|
|
|
if ( !fmem )
|
|
return 0;
|
|
|
|
xentoolcore__deregister_active_handle(&fmem->tc_ah);
|
|
rc = osdep_xenforeignmemory_close(fmem);
|
|
xtl_logger_destroy(fmem->logger_tofree);
|
|
free(fmem);
|
|
return rc;
|
|
}
|
|
|
|
void *xenforeignmemory_map2(xenforeignmemory_handle *fmem,
|
|
uint32_t dom, void *addr,
|
|
int prot, int flags, size_t num,
|
|
const xen_pfn_t arr[/*num*/], int err[/*num*/])
|
|
{
|
|
void *ret;
|
|
int *err_to_free = NULL;
|
|
|
|
if ( err == NULL )
|
|
err = err_to_free = malloc(num * sizeof(int));
|
|
|
|
if ( err == NULL )
|
|
return NULL;
|
|
|
|
ret = osdep_xenforeignmemory_map(fmem, dom, addr, prot, flags, num, arr, err);
|
|
|
|
if ( ret && err_to_free )
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0 ; i < num ; i++ )
|
|
{
|
|
if ( err[i] )
|
|
{
|
|
errno = -err[i];
|
|
(void)osdep_xenforeignmemory_unmap(fmem, ret, num);
|
|
ret = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
free(err_to_free);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void *xenforeignmemory_map(xenforeignmemory_handle *fmem,
|
|
uint32_t dom, int prot,
|
|
size_t num,
|
|
const xen_pfn_t arr[/*num*/], int err[/*num*/])
|
|
{
|
|
return xenforeignmemory_map2(fmem, dom, NULL, prot, 0, num, arr, err);
|
|
}
|
|
|
|
int xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
|
|
void *addr, size_t num)
|
|
{
|
|
return osdep_xenforeignmemory_unmap(fmem, addr, num);
|
|
}
|
|
|
|
int xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
|
|
domid_t domid)
|
|
{
|
|
return osdep_xenforeignmemory_restrict(fmem, domid);
|
|
}
|
|
|
|
xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
|
|
xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
|
|
unsigned int id, unsigned long frame, unsigned long nr_frames,
|
|
void **paddr, int prot, int flags)
|
|
{
|
|
xenforeignmemory_resource_handle *fres;
|
|
int rc;
|
|
|
|
/* Check flags only contains POSIX defined values */
|
|
if ( flags & ~(MAP_SHARED | MAP_PRIVATE) )
|
|
{
|
|
errno = EINVAL;
|
|
return NULL;
|
|
}
|
|
|
|
fres = calloc(1, sizeof(*fres));
|
|
if ( !fres )
|
|
{
|
|
errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
fres->domid = domid;
|
|
fres->type = type;
|
|
fres->id = id;
|
|
fres->frame = frame;
|
|
fres->nr_frames = nr_frames;
|
|
fres->addr = *paddr;
|
|
fres->prot = prot;
|
|
fres->flags = flags;
|
|
|
|
rc = osdep_xenforeignmemory_map_resource(fmem, fres);
|
|
if ( rc )
|
|
{
|
|
free(fres);
|
|
fres = NULL;
|
|
} else
|
|
*paddr = fres->addr;
|
|
|
|
return fres;
|
|
}
|
|
|
|
int xenforeignmemory_unmap_resource(
|
|
xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
|
|
{
|
|
int rc = osdep_xenforeignmemory_unmap_resource(fmem, fres);
|
|
|
|
free(fres);
|
|
return rc;
|
|
}
|
|
|
|
int xenforeignmemory_resource_size(
|
|
xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
|
|
unsigned int id, size_t *size)
|
|
{
|
|
xenforeignmemory_resource_handle fres = {
|
|
.domid = domid,
|
|
.type = type,
|
|
.id = id,
|
|
};
|
|
int rc = osdep_xenforeignmemory_map_resource(fmem, &fres);
|
|
|
|
if ( rc )
|
|
return rc;
|
|
|
|
*size = fres.nr_frames << PAGE_SHIFT;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-file-style: "BSD"
|
|
* c-basic-offset: 4
|
|
* tab-width: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|