mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
libxc: add abitility to dynamically load osdep.
Add a dummy backend which always returns ENOSYS. Mainly as a compile time testbed rather than because it is a useful backend. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Ian Jackson <ian.jackson.citrix.com>
This commit is contained in:
1 parent
0ccceacd05
commit
c89c726db9
4 files changed
+291
-2
No files matched your search
@@ -92,6 +92,10 @@ ifneq ($(stubdom),y)
|
||||
LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
|
||||
endif
|
||||
|
||||
ifneq ($(stubdom),y)
|
||||
LIB += xenctrl_osdep_ENOSYS.so
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
@@ -148,7 +152,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
|
||||
ln -sf $< $@
|
||||
|
||||
libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) -ldl $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS)
|
||||
|
||||
# libxenguest
|
||||
|
||||
@@ -186,5 +190,8 @@ libxenguest.so.$(MAJOR).$(MINOR): COMPRESSION_LIBS = $(call zlib-options,l)
|
||||
libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(GUEST_PIC_OBJS) $(COMPRESSION_LIBS) -lz -lxenctrl $(PTHREAD_LIBS)
|
||||
|
||||
xenctrl_osdep_ENOSYS.so: xenctrl_osdep_ENOSYS.o libxenctrl.so
|
||||
$(CC) -g $(CFLAGS) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ xenctrl_osdep_ENOSYS.o -lxenctrl
|
||||
|
||||
-include $(DEPS)
|
||||
|
||||
@@ -27,10 +27,22 @@
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef __MINIOS__
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#define XENCTRL_OSDEP "XENCTRL_OSDEP"
|
||||
|
||||
/*
|
||||
* Returns a (shallow) copy of the xc_osdep_info_t for the
|
||||
* active OS interface.
|
||||
*
|
||||
* On success a handle to the relevant library is opened. The user
|
||||
* must subsequently call xc_osdep_put_info() when it is
|
||||
* finished with the library.
|
||||
*
|
||||
* Logs IFF xch != NULL.
|
||||
*
|
||||
* Returns:
|
||||
* 0 - on success
|
||||
* -1 - on error
|
||||
@@ -38,16 +50,65 @@
|
||||
static int xc_osdep_get_info(xc_interface *xch, xc_osdep_info_t *info)
|
||||
{
|
||||
int rc = -1;
|
||||
#ifndef __MINIOS__
|
||||
const char *lib = getenv(XENCTRL_OSDEP);
|
||||
xc_osdep_info_t *pinfo;
|
||||
void *dl_handle = NULL;
|
||||
|
||||
*info = xc_osdep_info;
|
||||
if ( lib != NULL )
|
||||
{
|
||||
if ( getuid() != geteuid() )
|
||||
{
|
||||
if ( xch ) ERROR("cannot use %s=%s with setuid application", XENCTRL_OSDEP, lib);
|
||||
abort();
|
||||
}
|
||||
if ( getgid() != getegid() )
|
||||
{
|
||||
if ( xch ) ERROR("cannot use %s=%s with setgid application", XENCTRL_OSDEP, lib);
|
||||
abort();
|
||||
}
|
||||
|
||||
dl_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL);
|
||||
if ( !dl_handle )
|
||||
{
|
||||
if ( xch ) ERROR("unable to open osdep library %s: %s", lib, dlerror());
|
||||
goto out;
|
||||
}
|
||||
|
||||
pinfo = dlsym(dl_handle, "xc_osdep_info");
|
||||
if ( !pinfo )
|
||||
{
|
||||
if ( xch ) ERROR("unable to find xc_osinteface_info in %s: %s", lib, dlerror());
|
||||
goto out;
|
||||
}
|
||||
|
||||
*info = *pinfo;
|
||||
info->dl_handle = dl_handle;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*info = xc_osdep_info;
|
||||
info->dl_handle = NULL;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
#ifndef __MINIOS__
|
||||
out:
|
||||
if ( dl_handle && rc == -1 )
|
||||
dlclose(dl_handle);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void xc_osdep_put(xc_osdep_info_t *info)
|
||||
{
|
||||
#ifndef __MINIOS__
|
||||
if ( info->dl_handle )
|
||||
dlclose(info->dl_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct xc_interface_core *xc_interface_open_common(xentoollog_logger *logger,
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/* Dummy backend which just logs and returns ENOSYS. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xenctrl.h"
|
||||
#include "xenctrlosdep.h"
|
||||
|
||||
#define IPRINTF(_x, _f, _a...) xc_osdep_log(_x,XTL_INFO,0, _f , ## _a)
|
||||
|
||||
#define ERROR(_x, _m, _a...) xc_osdep_log(_x,XTL_ERROR,XC_INTERNAL_ERROR,_m , ## _a )
|
||||
#define PERROR(_x, _m, _a...) xc_osdep_log(_x,XTL_ERROR,XC_INTERNAL_ERROR,_m \
|
||||
" (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
|
||||
|
||||
static xc_osdep_handle ENOSYS_privcmd_open(xc_interface *xch)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd: opening handle %p\n", (void *)1);
|
||||
return (xc_osdep_handle)1; /*dummy*/
|
||||
}
|
||||
|
||||
static int ENOSYS_privcmd_close(xc_interface *xch, xc_osdep_handle h)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd: closing handle %p\n", h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ENOSYS_privcmd_hypercall(xc_interface *xch, xc_osdep_handle h, privcmd_hypercall_t *hypercall)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd %p: hypercall: %02lld(%#llx,%#llx,%#llx,%#llx,%#llx,%#llx)\n",
|
||||
h, hypercall->op,
|
||||
hypercall->arg[0], hypercall->arg[1], hypercall->arg[2],
|
||||
hypercall->arg[3], hypercall->arg[4], hypercall->arg[5]);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static void *ENOSYS_privcmd_map_foreign_batch(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
|
||||
xen_pfn_t *arr, int num)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_batch: dom%d prot %#x arr %p num %d\n", h, dom, prot, arr, num);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
static void *ENOSYS_privcmd_map_foreign_bulk(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int prot,
|
||||
const xen_pfn_t *arr, int *err, unsigned int num)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_buld: dom%d prot %#x arr %p err %p num %d\n", h, dom, prot, arr, err, num);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
static void *ENOSYS_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle h, uint32_t dom, int size, int prot,
|
||||
unsigned long mfn)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_range: dom%d size %#x prot %#x mfn %ld\n", h, dom, size, prot, mfn);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
static void *ENOSYS_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle h, uint32_t dom, size_t size, int prot,
|
||||
size_t chunksize, privcmd_mmap_entry_t entries[],
|
||||
int nentries)
|
||||
{
|
||||
IPRINTF(xch, "ENOSYS_privcmd %p: map_foreign_ranges: dom%d size %zd prot %#x chunksize %zd entries %p num %d\n", h, dom, size, prot, chunksize, entries, nentries);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
static struct xc_osdep_ops ENOSYS_privcmd_ops =
|
||||
{
|
||||
.open = &ENOSYS_privcmd_open,
|
||||
.close = &ENOSYS_privcmd_close,
|
||||
.u.privcmd = {
|
||||
.hypercall = &ENOSYS_privcmd_hypercall,
|
||||
|
||||
.map_foreign_batch = &ENOSYS_privcmd_map_foreign_batch,
|
||||
.map_foreign_bulk = &ENOSYS_privcmd_map_foreign_bulk,
|
||||
.map_foreign_range = &ENOSYS_privcmd_map_foreign_range,
|
||||
.map_foreign_ranges = &ENOSYS_privcmd_map_foreign_ranges,
|
||||
}
|
||||
};
|
||||
|
||||
static xc_osdep_handle ENOSYS_evtchn_open(xc_interface *xce)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn: opening handle %p\n", (void *)1);
|
||||
return (xc_osdep_handle)2; /*dummy*/
|
||||
}
|
||||
|
||||
static int ENOSYS_evtchn_close(xc_interface *xce, xc_osdep_handle h)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn: closing handle %p\n", h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ENOSYS_evtchn_fd(xc_interface *xce, xc_osdep_handle h)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_fd %p: fd\n", h);
|
||||
return (int)h;
|
||||
}
|
||||
|
||||
static int ENOSYS_evtchn_notify(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: notify: %d\n", h, port);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int ENOSYS_evtchn_bind_unbound_port(xc_interface *xce, xc_osdep_handle h, int domid)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: bind_unbound_port: dom%d\n", h, domid);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
static int ENOSYS_evtchn_bind_interdomain(xc_interface *xce, xc_osdep_handle h, int domid, evtchn_port_t remote_port)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: bind_interdomain: dmo%d %d\n", h, domid, remote_port);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
static int ENOSYS_evtchn_bind_virq(xc_interface *xce, xc_osdep_handle h, unsigned int virq)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: bind_virq: %d\n", h, virq);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
static int ENOSYS_evtchn_unbind(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: unbind: %d\n", h, port);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
static evtchn_port_or_error_t ENOSYS_evtchn_pending(xc_interface *xce, xc_osdep_handle h)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: pending\n", h);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int ENOSYS_evtchn_unmask(xc_interface *xce, xc_osdep_handle h, evtchn_port_t port)
|
||||
{
|
||||
IPRINTF(xce, "ENOSYS_evtchn %p: unmask: %d\n", h, port);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static struct xc_osdep_ops ENOSYS_evtchn_ops = {
|
||||
.open = &ENOSYS_evtchn_open,
|
||||
.close = &ENOSYS_evtchn_close,
|
||||
|
||||
.u.evtchn = {
|
||||
.fd = &ENOSYS_evtchn_fd,
|
||||
|
||||
.notify = &ENOSYS_evtchn_notify,
|
||||
|
||||
.bind_unbound_port = &ENOSYS_evtchn_bind_unbound_port,
|
||||
.bind_interdomain = &ENOSYS_evtchn_bind_interdomain,
|
||||
.bind_virq = &ENOSYS_evtchn_bind_virq,
|
||||
|
||||
.unbind = &ENOSYS_evtchn_unbind,
|
||||
|
||||
.pending = &ENOSYS_evtchn_pending,
|
||||
.unmask = &ENOSYS_evtchn_unmask,
|
||||
},
|
||||
};
|
||||
|
||||
static struct xc_osdep_ops * ENOSYS_osdep_init(xc_interface *xch, enum xc_osdep_type type)
|
||||
{
|
||||
struct xc_osdep_ops *ops;
|
||||
|
||||
if (getenv("ENOSYS") == NULL)
|
||||
{
|
||||
PERROR(xch, "ENOSYS: not configured\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case XC_OSDEP_PRIVCMD:
|
||||
ops = &ENOSYS_privcmd_ops;
|
||||
break;
|
||||
case XC_OSDEP_EVTCHN:
|
||||
ops = &ENOSYS_evtchn_ops;
|
||||
break;
|
||||
default:
|
||||
ops = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
IPRINTF(xch, "ENOSYS_osdep_init: initialising handle ops at %p\n", ops);
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
xc_osdep_info_t xc_osdep_info = {
|
||||
.name = "Pessimistic ENOSYS OS interface",
|
||||
.init = &ENOSYS_osdep_init,
|
||||
.fake = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -23,6 +23,18 @@
|
||||
* This interface defines the interactions between the Xen control
|
||||
* libraries and the OS facilities used to communicate with the
|
||||
* hypervisor.
|
||||
*
|
||||
* It is possible to override the default (native) implementation by
|
||||
* setting the XENCTRL_OSDEP environment variable to point to a
|
||||
* plugin library. Userspace can use this facility to intercept
|
||||
* hypervisor operations. This can be used e.g. to implement a
|
||||
* userspace simulator for Xen hypercalls.
|
||||
*
|
||||
* The plugin must contain a data structure:
|
||||
* xc_osdep_info_t xc_osdep_info;
|
||||
*
|
||||
* xc_osdep_init:
|
||||
* Must return a suitable struct xc_osdep_ops pointer or NULL on failure.
|
||||
*/
|
||||
|
||||
#ifndef XC_OSDEP_H
|
||||
@@ -125,6 +137,9 @@ struct xc_osdep_info
|
||||
|
||||
/* True if this interface backs onto a fake Xen. */
|
||||
int fake;
|
||||
|
||||
/* For internal use by loader. */
|
||||
void *dl_handle;
|
||||
};
|
||||
typedef struct xc_osdep_info xc_osdep_info_t;
|
||||
|
||||
|
||||