mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Merge branch 'staging' of git://xenbits.xen.org/people/konradwilk/xen into staging
* 'staging' of git://xenbits.xen.org/people/konradwilk/xen: Introduce the pvcalls header Introduce the Xen 9pfs transport header xen: introduce a C99 headers check ring.h: introduce macros to handle monodirectional rings with multiple req sizes tmem: Parse UUIDs correctly. tmem: Fix tmem-shared-auth 'auth' values tmem: By default to join an shared pool it must be authorized. xen/libxc: Move TMEM_AUTH to XEN_SYSCTL_TMEM_OP_SET_AUTH xen/libcx/tmem: Replace TMEM_RESTORE_NEW with XEN_SYSCTL_TMEM_OP_SET_POOLS displif: add ABI for para-virtual display
This commit is contained in:
commit
d641c24e7c
18 files changed
+1420
-111
No files matched your search
+1
-2
@@ -285,8 +285,7 @@ xen/arch/*/efi/boot.c
|
||||
xen/arch/*/efi/compat.c
|
||||
xen/arch/*/efi/efi.h
|
||||
xen/arch/*/efi/runtime.c
|
||||
xen/include/headers.chk
|
||||
xen/include/headers++.chk
|
||||
xen/include/headers*.chk
|
||||
xen/include/asm
|
||||
xen/include/asm-*/asm-offsets.h
|
||||
xen/include/asm-x86/cpuid-autogen.h
|
||||
|
||||
@@ -715,11 +715,9 @@ Ocfs2 has only very limited security; it is assumed that anyone who can
|
||||
access the filesystem bits on the shared disk can mount the filesystem and use
|
||||
it. But in a virtualized data center,
|
||||
higher isolation requirements may apply.
|
||||
As a result, a Xen boot option -- "tmem_shared_auth" -- was
|
||||
added. The option defaults to disabled,
|
||||
but when it is enabled, management tools must explicitly authenticate (or may
|
||||
As a result, management tools must explicitly authenticate (or may
|
||||
explicitly deny) shared pool access to any client.
|
||||
On Xen, this is done with the "xm
|
||||
On Xen, this is done with the "xl
|
||||
tmem-shared-auth" command.
|
||||
<P>
|
||||
<b><i>32-bit implementation</i>.</b>
|
||||
|
||||
@@ -1539,9 +1539,6 @@ pages) must also be specified via the tbuf\_size parameter.
|
||||
### tmem\_compress
|
||||
> `= <boolean>`
|
||||
|
||||
### tmem\_shared\_auth
|
||||
> `= <boolean>`
|
||||
|
||||
### tsc
|
||||
> `= unstable | skewed | stable:socket`
|
||||
|
||||
|
||||
@@ -1901,7 +1901,7 @@ int xc_tmem_control_oid(xc_interface *xch, int32_t pool_id, uint32_t subop,
|
||||
int xc_tmem_control(xc_interface *xch,
|
||||
int32_t pool_id, uint32_t subop, uint32_t cli_id,
|
||||
uint32_t len, uint32_t arg, void *buf);
|
||||
int xc_tmem_auth(xc_interface *xch, int cli_id, char *uuid_str, int arg1);
|
||||
int xc_tmem_auth(xc_interface *xch, int cli_id, char *uuid_str, int enable);
|
||||
int xc_tmem_save(xc_interface *xch, int dom, int live, int fd, int field_marker);
|
||||
int xc_tmem_save_extra(xc_interface *xch, int dom, int fd, int field_marker);
|
||||
void xc_tmem_save_done(xc_interface *xch, int dom);
|
||||
|
||||
+29
-47
@@ -22,30 +22,6 @@
|
||||
#include <assert.h>
|
||||
#include <xen/tmem.h>
|
||||
|
||||
static int do_tmem_op(xc_interface *xch, tmem_op_t *op)
|
||||
{
|
||||
int ret;
|
||||
DECLARE_HYPERCALL_BOUNCE(op, sizeof(*op), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
|
||||
|
||||
if ( xc_hypercall_bounce_pre(xch, op) )
|
||||
{
|
||||
PERROR("Could not bounce buffer for tmem op hypercall");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = xencall1(xch->xcall, __HYPERVISOR_tmem_op,
|
||||
HYPERCALL_BUFFER_AS_ARG(op));
|
||||
if ( ret < 0 )
|
||||
{
|
||||
if ( errno == EACCES )
|
||||
DPRINTF("tmem operation failed -- need to"
|
||||
" rebuild the user-space tool set?\n");
|
||||
}
|
||||
xc_hypercall_bounce_post(xch, op);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xc_tmem_control(xc_interface *xch,
|
||||
int32_t pool_id,
|
||||
uint32_t cmd,
|
||||
@@ -69,7 +45,8 @@ int xc_tmem_control(xc_interface *xch,
|
||||
sysctl.u.tmem_op.oid.oid[1] = 0;
|
||||
sysctl.u.tmem_op.oid.oid[2] = 0;
|
||||
|
||||
if ( cmd == XEN_SYSCTL_TMEM_OP_SET_CLIENT_INFO )
|
||||
if ( cmd == XEN_SYSCTL_TMEM_OP_SET_CLIENT_INFO ||
|
||||
cmd == XEN_SYSCTL_TMEM_OP_SET_AUTH )
|
||||
HYPERCALL_BOUNCE_SET_DIR(buf, XC_HYPERCALL_BUFFER_BOUNCE_IN);
|
||||
if ( len )
|
||||
{
|
||||
@@ -161,9 +138,9 @@ static int xc_tmem_uuid_parse(char *uuid_str, uint64_t *uuid_lo, uint64_t *uuid_
|
||||
else if ( *p >= '0' && *p <= '9' )
|
||||
digit = *p - '0';
|
||||
else if ( *p >= 'A' && *p <= 'F' )
|
||||
digit = *p - 'A';
|
||||
digit = *p - 'A' + 10;
|
||||
else if ( *p >= 'a' && *p <= 'f' )
|
||||
digit = *p - 'a';
|
||||
digit = *p - 'a' + 10;
|
||||
else
|
||||
return -1;
|
||||
*x = (*x << 4) | digit;
|
||||
@@ -176,22 +153,25 @@ static int xc_tmem_uuid_parse(char *uuid_str, uint64_t *uuid_lo, uint64_t *uuid_
|
||||
int xc_tmem_auth(xc_interface *xch,
|
||||
int cli_id,
|
||||
char *uuid_str,
|
||||
int arg1)
|
||||
int enable)
|
||||
{
|
||||
tmem_op_t op;
|
||||
|
||||
op.cmd = TMEM_AUTH;
|
||||
op.pool_id = 0;
|
||||
op.u.creat.arg1 = cli_id;
|
||||
op.u.creat.flags = arg1;
|
||||
if ( xc_tmem_uuid_parse(uuid_str, &op.u.creat.uuid[0],
|
||||
&op.u.creat.uuid[1]) < 0 )
|
||||
xen_tmem_pool_info_t pool = {
|
||||
.flags.u.auth = enable,
|
||||
.id = 0,
|
||||
.n_pages = 0,
|
||||
.uuid[0] = 0,
|
||||
.uuid[1] = 0,
|
||||
};
|
||||
if ( xc_tmem_uuid_parse(uuid_str, &pool.uuid[0],
|
||||
&pool.uuid[1]) < 0 )
|
||||
{
|
||||
PERROR("Can't parse uuid, use xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return do_tmem_op(xch, &op);
|
||||
return xc_tmem_control(xch, 0 /* pool_id */,
|
||||
XEN_SYSCTL_TMEM_OP_SET_AUTH,
|
||||
cli_id, sizeof(pool),
|
||||
0 /* arg */, &pool);
|
||||
}
|
||||
|
||||
/* Save/restore/live migrate */
|
||||
@@ -385,16 +365,18 @@ static int xc_tmem_restore_new_pool(
|
||||
uint64_t uuid_lo,
|
||||
uint64_t uuid_hi)
|
||||
{
|
||||
tmem_op_t op;
|
||||
xen_tmem_pool_info_t pool = {
|
||||
.flags.raw = flags,
|
||||
.id = pool_id,
|
||||
.n_pages = 0,
|
||||
.uuid[0] = uuid_lo,
|
||||
.uuid[1] = uuid_hi,
|
||||
};
|
||||
|
||||
op.cmd = TMEM_RESTORE_NEW;
|
||||
op.pool_id = pool_id;
|
||||
op.u.creat.arg1 = cli_id;
|
||||
op.u.creat.flags = flags;
|
||||
op.u.creat.uuid[0] = uuid_lo;
|
||||
op.u.creat.uuid[1] = uuid_hi;
|
||||
|
||||
return do_tmem_op(xch, &op);
|
||||
return xc_tmem_control(xch, pool_id,
|
||||
XEN_SYSCTL_TMEM_OP_SET_POOLS,
|
||||
cli_id, sizeof(pool),
|
||||
0 /* arg */, &pool);
|
||||
}
|
||||
|
||||
int xc_tmem_restore(xc_interface *xch, int dom, int io_fd)
|
||||
|
||||
@@ -416,7 +416,7 @@ struct cmd_spec cmd_table[] = {
|
||||
" -a Authenticate for all tmem pools\n"
|
||||
" -u UUID Specify uuid\n"
|
||||
" (abcdef01-2345-6789-1234-567890abcdef)\n"
|
||||
" -A AUTH 0=auth,1=deauth",
|
||||
" -A AUTH 0=deauth,1=auth",
|
||||
},
|
||||
{ "tmem-freeable",
|
||||
&main_tmem_freeable, 0, 0,
|
||||
|
||||
+16
-21
@@ -804,7 +804,7 @@ static void pool_flush(struct tmem_pool *pool, domid_t cli_id)
|
||||
|
||||
/************ CLIENT MANIPULATION OPERATIONS **************************/
|
||||
|
||||
static struct client *client_create(domid_t cli_id)
|
||||
struct client *client_create(domid_t cli_id)
|
||||
{
|
||||
struct client *client = xzalloc(struct client);
|
||||
int i, shift;
|
||||
@@ -846,7 +846,6 @@ static struct client *client_create(domid_t cli_id)
|
||||
client->info.version = TMEM_SPEC_VERSION;
|
||||
client->info.maxpools = MAX_POOLS_PER_DOMAIN;
|
||||
client->info.flags.u.compress = tmem_compression_enabled();
|
||||
client->shared_auth_required = tmem_shared_auth();
|
||||
for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++)
|
||||
client->shared_auth_uuid[i][0] =
|
||||
client->shared_auth_uuid[i][1] = -1L;
|
||||
@@ -1435,9 +1434,9 @@ static int do_tmem_destroy_pool(uint32_t pool_id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_tmem_new_pool(domid_t this_cli_id,
|
||||
uint32_t d_poolid, uint32_t flags,
|
||||
uint64_t uuid_lo, uint64_t uuid_hi)
|
||||
int do_tmem_new_pool(domid_t this_cli_id,
|
||||
uint32_t d_poolid, uint32_t flags,
|
||||
uint64_t uuid_lo, uint64_t uuid_hi)
|
||||
{
|
||||
struct client *client;
|
||||
domid_t cli_id;
|
||||
@@ -1530,7 +1529,7 @@ static int do_tmem_new_pool(domid_t this_cli_id,
|
||||
pool->shared = 0;
|
||||
goto out;
|
||||
}
|
||||
if ( client->shared_auth_required && !tmem_global.shared_auth )
|
||||
if ( !tmem_global.shared_auth )
|
||||
{
|
||||
for ( i = 0; i < MAX_GLOBAL_SHARED_POOLS; i++)
|
||||
if ( (client->shared_auth_uuid[i][0] == uuid_lo) &&
|
||||
@@ -1604,8 +1603,8 @@ fail:
|
||||
|
||||
/************ TMEM CONTROL OPERATIONS ************************************/
|
||||
|
||||
static int tmemc_shared_pool_auth(domid_t cli_id, uint64_t uuid_lo,
|
||||
uint64_t uuid_hi, bool_t auth)
|
||||
int tmemc_shared_pool_auth(domid_t cli_id, uint64_t uuid_lo,
|
||||
uint64_t uuid_hi, bool auth)
|
||||
{
|
||||
struct client *client;
|
||||
int i, free = -1;
|
||||
@@ -1908,21 +1907,15 @@ long do_tmem_op(tmem_cli_op_t uops)
|
||||
/* Acquire write lock for all commands at first. */
|
||||
write_lock(&tmem_rwlock);
|
||||
|
||||
if ( op.cmd == TMEM_CONTROL )
|
||||
switch ( op.cmd )
|
||||
{
|
||||
case TMEM_CONTROL:
|
||||
case TMEM_RESTORE_NEW:
|
||||
case TMEM_AUTH:
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
else if ( op.cmd == TMEM_AUTH )
|
||||
{
|
||||
rc = tmemc_shared_pool_auth(op.u.creat.arg1,op.u.creat.uuid[0],
|
||||
op.u.creat.uuid[1],op.u.creat.flags);
|
||||
}
|
||||
else if ( op.cmd == TMEM_RESTORE_NEW )
|
||||
{
|
||||
rc = do_tmem_new_pool(op.u.creat.arg1, op.pool_id, op.u.creat.flags,
|
||||
op.u.creat.uuid[0], op.u.creat.uuid[1]);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* For other commands, create per-client tmem structure dynamically on
|
||||
* first use by client.
|
||||
@@ -1999,6 +1992,8 @@ long do_tmem_op(tmem_cli_op_t uops)
|
||||
tmem_stats.errored_tmem_ops++;
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
out:
|
||||
write_unlock(&tmem_rwlock);
|
||||
|
||||
@@ -402,6 +402,101 @@ static int tmemc_get_pool(int cli_id,
|
||||
return rc ? : idx;
|
||||
}
|
||||
|
||||
static int tmemc_set_pools(int cli_id,
|
||||
XEN_GUEST_HANDLE(xen_tmem_pool_info_t) pools,
|
||||
uint32_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc = 0;
|
||||
unsigned int nr = len / sizeof(xen_tmem_pool_info_t);
|
||||
struct client *client = tmem_client_from_cli_id(cli_id);
|
||||
|
||||
if ( len % sizeof(xen_tmem_pool_info_t) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( nr > MAX_POOLS_PER_DOMAIN )
|
||||
return -E2BIG;
|
||||
|
||||
if ( !guest_handle_okay(pools, nr) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( !client )
|
||||
{
|
||||
client = client_create(cli_id);
|
||||
if ( !client )
|
||||
return -ENOMEM;
|
||||
}
|
||||
for ( i = 0; i < nr; i++ )
|
||||
{
|
||||
xen_tmem_pool_info_t pool;
|
||||
|
||||
if ( __copy_from_guest_offset(&pool, pools, i, 1 ) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( pool.n_pages )
|
||||
return -EINVAL;
|
||||
|
||||
rc = do_tmem_new_pool(cli_id, pool.id, pool.flags.raw,
|
||||
pool.uuid[0], pool.uuid[1]);
|
||||
if ( rc < 0 )
|
||||
break;
|
||||
|
||||
pool.id = rc;
|
||||
if ( __copy_to_guest_offset(pools, i, &pool, 1) )
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* And how many we have processed. */
|
||||
return rc ? : i;
|
||||
}
|
||||
|
||||
static int tmemc_auth_pools(int cli_id,
|
||||
XEN_GUEST_HANDLE(xen_tmem_pool_info_t) pools,
|
||||
uint32_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc = 0;
|
||||
unsigned int nr = len / sizeof(xen_tmem_pool_info_t);
|
||||
struct client *client = tmem_client_from_cli_id(cli_id);
|
||||
|
||||
if ( len % sizeof(xen_tmem_pool_info_t) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( nr > MAX_POOLS_PER_DOMAIN )
|
||||
return -E2BIG;
|
||||
|
||||
if ( !guest_handle_okay(pools, nr) )
|
||||
return -EINVAL;
|
||||
|
||||
if ( !client )
|
||||
{
|
||||
client = client_create(cli_id);
|
||||
if ( !client )
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for ( i = 0; i < nr; i++ )
|
||||
{
|
||||
xen_tmem_pool_info_t pool;
|
||||
|
||||
if ( __copy_from_guest_offset(&pool, pools, i, 1 ) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( pool.n_pages )
|
||||
return -EINVAL;
|
||||
|
||||
rc = tmemc_shared_pool_auth(cli_id, pool.uuid[0], pool.uuid[1],
|
||||
pool.flags.u.auth);
|
||||
|
||||
if ( rc < 0 )
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* And how many we have processed. */
|
||||
return rc ? : i;
|
||||
}
|
||||
|
||||
int tmem_control(struct xen_sysctl_tmem_op *op)
|
||||
{
|
||||
int ret;
|
||||
@@ -438,6 +533,12 @@ int tmem_control(struct xen_sysctl_tmem_op *op)
|
||||
case XEN_SYSCTL_TMEM_OP_GET_POOLS:
|
||||
ret = tmemc_get_pool(op->cli_id, op->u.pool, op->len);
|
||||
break;
|
||||
case XEN_SYSCTL_TMEM_OP_SET_POOLS: /* TMEM_RESTORE_NEW */
|
||||
ret = tmemc_set_pools(op->cli_id, op->u.pool, op->len);
|
||||
break;
|
||||
case XEN_SYSCTL_TMEM_OP_SET_AUTH: /* TMEM_AUTH */
|
||||
ret = tmemc_auth_pools(op->cli_id, op->u.pool, op->len);
|
||||
break;
|
||||
default:
|
||||
ret = do_tmem_control(op);
|
||||
break;
|
||||
|
||||
@@ -20,9 +20,6 @@ boolean_param("tmem", opt_tmem);
|
||||
bool_t __read_mostly opt_tmem_compress = 0;
|
||||
boolean_param("tmem_compress", opt_tmem_compress);
|
||||
|
||||
bool_t __read_mostly opt_tmem_shared_auth = 0;
|
||||
boolean_param("tmem_shared_auth", opt_tmem_shared_auth);
|
||||
|
||||
atomic_t freeable_page_count = ATOMIC_INIT(0);
|
||||
|
||||
/* these are a concurrency bottleneck, could be percpu and dynamically
|
||||
|
||||
+24
-12
@@ -90,11 +90,15 @@ compat/xlat.h: $(addprefix compat/.xlat/,$(xlat-y)) Makefile
|
||||
|
||||
ifeq ($(XEN_TARGET_ARCH),$(XEN_COMPILE_ARCH))
|
||||
|
||||
all: headers.chk headers++.chk
|
||||
all: headers.chk headers99.chk headers++.chk
|
||||
|
||||
PUBLIC_HEADERS := $(filter-out public/arch-% public/dom0_ops.h, $(wildcard public/*.h public/*/*.h) $(public-y))
|
||||
|
||||
PUBLIC_ANSI_HEADERS := $(filter-out public/%ctl.h public/xsm/% public/%hvm/save.h, $(PUBLIC_HEADERS))
|
||||
PUBLIC_C99_HEADERS := public/io/9pfs.h public/io/pvcalls.h
|
||||
PUBLIC_ANSI_HEADERS := $(filter-out public/%ctl.h public/xsm/% public/%hvm/save.h $(PUBLIC_C99_HEADERS), $(PUBLIC_HEADERS))
|
||||
|
||||
public/io/9pfs.h-prereq := string
|
||||
public/io/pvcalls.h-prereq := string
|
||||
|
||||
headers.chk: $(PUBLIC_ANSI_HEADERS) Makefile
|
||||
for i in $(filter %.h,$^); do \
|
||||
@@ -104,16 +108,24 @@ headers.chk: $(PUBLIC_ANSI_HEADERS) Makefile
|
||||
done >$@.new
|
||||
mv $@.new $@
|
||||
|
||||
headers99.chk: $(PUBLIC_C99_HEADERS) Makefile
|
||||
rm -f $@.new
|
||||
$(foreach i, $(filter %.h,$^), \
|
||||
$(CC) -x c -std=c99 -Wall -Werror \
|
||||
-include stdint.h $(foreach j, $($(i)-prereq), -include $(j).h) \
|
||||
-S -o /dev/null $(i) \
|
||||
|| exit $$?; echo $(i) >> $@.new;)
|
||||
mv $@.new $@
|
||||
|
||||
headers++.chk: $(PUBLIC_HEADERS) Makefile
|
||||
if $(CXX) -v >/dev/null 2>&1; then \
|
||||
for i in $(filter %.h,$^); do \
|
||||
echo '#include "'$$i'"' \
|
||||
| $(CXX) -x c++ -std=gnu++98 -Wall -Werror -D__XEN_TOOLS__ \
|
||||
-include stdint.h -include public/xen.h -S -o /dev/null - \
|
||||
|| exit 1; \
|
||||
echo $$i; \
|
||||
done ; \
|
||||
fi >$@.new
|
||||
rm -f $@.new
|
||||
$(CXX) -v >/dev/null 2>&1 || exit 0; \
|
||||
$(foreach i, $(filter %.h,$^), \
|
||||
echo "#include "\"$(i)\" \
|
||||
| $(CXX) -x c++ -std=gnu++98 -Wall -Werror -D__XEN_TOOLS__ \
|
||||
-include stdint.h -include public/xen.h \
|
||||
$(foreach j, $($(i)-prereq), -include c$(j)) -S -o /dev/null - \
|
||||
|| exit $$?; echo $(i) >> $@.new;)
|
||||
mv $@.new $@
|
||||
|
||||
endif
|
||||
@@ -128,5 +140,5 @@ all: $(BASEDIR)/include/asm-x86/cpuid-autogen.h
|
||||
endif
|
||||
|
||||
clean::
|
||||
rm -rf compat headers.chk headers++.chk
|
||||
rm -rf compat headers*.chk
|
||||
rm -f $(BASEDIR)/include/asm-x86/cpuid-autogen.h
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 9pfs.h -- Xen 9PFS transport
|
||||
*
|
||||
* Refer to docs/misc/9pfs.markdown for the specification
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright (C) 2017 Stefano Stabellini <stefano@aporeto.com>
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PUBLIC_IO_9PFS_H__
|
||||
#define __XEN_PUBLIC_IO_9PFS_H__
|
||||
|
||||
#include "../grant_table.h"
|
||||
#include "ring.h"
|
||||
|
||||
/*
|
||||
* See docs/misc/9pfs.markdown in xen.git for the full specification:
|
||||
* https://xenbits.xen.org/docs/unstable/misc/9pfs.html
|
||||
*/
|
||||
DEFINE_XEN_FLEX_RING_AND_INTF(xen_9pfs);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,864 @@
|
||||
/******************************************************************************
|
||||
* displif.h
|
||||
*
|
||||
* Unified display device I/O interface for Xen guest OSes.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright (C) 2016-2017 EPAM Systems Inc.
|
||||
*
|
||||
* Authors: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
|
||||
* Oleksandr Grytsov <oleksandr_grytsov@epam.com>
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PUBLIC_IO_DISPLIF_H__
|
||||
#define __XEN_PUBLIC_IO_DISPLIF_H__
|
||||
|
||||
#include "ring.h"
|
||||
#include "../grant_table.h"
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* Protocol version
|
||||
******************************************************************************
|
||||
*/
|
||||
#define XENDISPL_PROTOCOL_VERSION "1"
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* Main features provided by the protocol
|
||||
******************************************************************************
|
||||
* This protocol aims to provide a unified protocol which fits more
|
||||
* sophisticated use-cases than a framebuffer device can handle. At the
|
||||
* moment basic functionality is supported with the intention to be extended:
|
||||
* o multiple dynamically allocated/destroyed framebuffers
|
||||
* o buffers of arbitrary sizes
|
||||
* o buffer allocation at either back or front end
|
||||
* o better configuration options including multiple display support
|
||||
*
|
||||
* Note: existing fbif can be used together with displif running at the
|
||||
* same time, e.g. on Linux one provides framebuffer and another DRM/KMS
|
||||
*
|
||||
* Note: display resolution (XenStore's "resolution" property) defines
|
||||
* visible area of the virtual display. At the same time resolution of
|
||||
* the display and frame buffers may differ: buffers can be smaller, equal
|
||||
* or bigger than the visible area. This is to enable use-cases, where backend
|
||||
* may do some post-processing of the display and frame buffers supplied,
|
||||
* e.g. those buffers can be just a part of the final composition.
|
||||
*
|
||||
******************************************************************************
|
||||
* Direction of improvements
|
||||
******************************************************************************
|
||||
* Future extensions to the existing protocol may include:
|
||||
* o display/connector cloning
|
||||
* o allocation of objects other than display buffers
|
||||
* o plane/overlay support
|
||||
* o scaling support
|
||||
* o rotation support
|
||||
*
|
||||
******************************************************************************
|
||||
* Feature and Parameter Negotiation
|
||||
******************************************************************************
|
||||
*
|
||||
* Front->back notifications: when enqueuing a new request, sending a
|
||||
* notification can be made conditional on xendispl_req (i.e., the generic
|
||||
* hold-off mechanism provided by the ring macros). Backends must set
|
||||
* xendispl_req appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
|
||||
*
|
||||
* Back->front notifications: when enqueuing a new response, sending a
|
||||
* notification can be made conditional on xendispl_resp (i.e., the generic
|
||||
* hold-off mechanism provided by the ring macros). Frontends must set
|
||||
* xendispl_resp appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
|
||||
*
|
||||
* The two halves of a para-virtual display driver utilize nodes within
|
||||
* XenStore to communicate capabilities and to negotiate operating parameters.
|
||||
* This section enumerates these nodes which reside in the respective front and
|
||||
* backend portions of XenStore, following the XenBus convention.
|
||||
*
|
||||
* All data in XenStore is stored as strings. Nodes specifying numeric
|
||||
* values are encoded in decimal. Integer value ranges listed below are
|
||||
* expressed as fixed sized integer types capable of storing the conversion
|
||||
* of a properly formated node string, without loss of information.
|
||||
*
|
||||
******************************************************************************
|
||||
* Example configuration
|
||||
******************************************************************************
|
||||
*
|
||||
* Note: depending on the use-case backend can expose more display connectors
|
||||
* than the underlying HW physically has by employing SW graphics compositors
|
||||
*
|
||||
* This is an example of backend and frontend configuration:
|
||||
*
|
||||
*--------------------------------- Backend -----------------------------------
|
||||
*
|
||||
* /local/domain/0/backend/vdispl/1/0/frontend-id = "1"
|
||||
* /local/domain/0/backend/vdispl/1/0/frontend = "/local/domain/1/device/vdispl/0"
|
||||
* /local/domain/0/backend/vdispl/1/0/state = "4"
|
||||
* /local/domain/0/backend/vdispl/1/0/versions = "1,2"
|
||||
*
|
||||
*--------------------------------- Frontend ----------------------------------
|
||||
*
|
||||
* /local/domain/1/device/vdispl/0/backend-id = "0"
|
||||
* /local/domain/1/device/vdispl/0/backend = "/local/domain/0/backend/vdispl/1/0"
|
||||
* /local/domain/1/device/vdispl/0/state = "4"
|
||||
* /local/domain/1/device/vdispl/0/version = "1"
|
||||
* /local/domain/1/device/vdispl/0/be-alloc = "1"
|
||||
*
|
||||
*-------------------------- Connector 0 configuration ------------------------
|
||||
*
|
||||
* /local/domain/1/device/vdispl/0/0/resolution = "1920x1080"
|
||||
* /local/domain/1/device/vdispl/0/0/req-ring-ref = "2832"
|
||||
* /local/domain/1/device/vdispl/0/0/req-event-channel = "15"
|
||||
* /local/domain/1/device/vdispl/0/0/evt-ring-ref = "387"
|
||||
* /local/domain/1/device/vdispl/0/0/evt-event-channel = "16"
|
||||
*
|
||||
*-------------------------- Connector 1 configuration ------------------------
|
||||
*
|
||||
* /local/domain/1/device/vdispl/0/1/resolution = "800x600"
|
||||
* /local/domain/1/device/vdispl/0/1/req-ring-ref = "2833"
|
||||
* /local/domain/1/device/vdispl/0/1/req-event-channel = "17"
|
||||
* /local/domain/1/device/vdispl/0/1/evt-ring-ref = "388"
|
||||
* /local/domain/1/device/vdispl/0/1/evt-event-channel = "18"
|
||||
*
|
||||
******************************************************************************
|
||||
* Backend XenBus Nodes
|
||||
******************************************************************************
|
||||
*
|
||||
*----------------------------- Protocol version ------------------------------
|
||||
*
|
||||
* versions
|
||||
* Values: <string>
|
||||
*
|
||||
* List of XENDISPL_LIST_SEPARATOR separated protocol versions supported
|
||||
* by the backend. For example "1,2,3".
|
||||
*
|
||||
******************************************************************************
|
||||
* Frontend XenBus Nodes
|
||||
******************************************************************************
|
||||
*
|
||||
*-------------------------------- Addressing ---------------------------------
|
||||
*
|
||||
* dom-id
|
||||
* Values: <uint16_t>
|
||||
*
|
||||
* Domain identifier.
|
||||
*
|
||||
* dev-id
|
||||
* Values: <uint16_t>
|
||||
*
|
||||
* Device identifier.
|
||||
*
|
||||
* conn-idx
|
||||
* Values: <uint8_t>
|
||||
*
|
||||
* Zero based contigous index of the connector.
|
||||
* /local/domain/<dom-id>/device/vdispl/<dev-id>/<conn-idx>/...
|
||||
*
|
||||
*----------------------------- Protocol version ------------------------------
|
||||
*
|
||||
* version
|
||||
* Values: <string>
|
||||
*
|
||||
* Protocol version, chosen among the ones supported by the backend.
|
||||
*
|
||||
*------------------------- Backend buffer allocation -------------------------
|
||||
*
|
||||
* be-alloc
|
||||
* Values: "0", "1"
|
||||
*
|
||||
* If value is set to "1", then backend can be a buffer provider/allocator
|
||||
* for this domain during XENDISPL_OP_DBUF_CREATE operation (see below
|
||||
* for negotiation).
|
||||
* If value is not "1" or omitted frontend must allocate buffers itself.
|
||||
*
|
||||
*----------------------------- Connector settings ----------------------------
|
||||
*
|
||||
* resolution
|
||||
* Values: <width, uint32_t>x<height, uint32_t>
|
||||
*
|
||||
* Width and height of the connector in pixels separated by
|
||||
* XENDISPL_RESOLUTION_SEPARATOR. This defines visible area of the
|
||||
* display.
|
||||
*
|
||||
*------------------ Connector Request Transport Parameters -------------------
|
||||
*
|
||||
* This communication path is used to deliver requests from frontend to backend
|
||||
* and get the corresponding responses from backend to frontend,
|
||||
* set up per connector.
|
||||
*
|
||||
* req-event-channel
|
||||
* Values: <uint32_t>
|
||||
*
|
||||
* The identifier of the Xen connector's control event channel
|
||||
* used to signal activity in the ring buffer.
|
||||
*
|
||||
* req-ring-ref
|
||||
* Values: <uint32_t>
|
||||
*
|
||||
* The Xen grant reference granting permission for the backend to map
|
||||
* a sole page of connector's control ring buffer.
|
||||
*
|
||||
*------------------- Connector Event Transport Parameters --------------------
|
||||
*
|
||||
* This communication path is used to deliver asynchronous events from backend
|
||||
* to frontend, set up per connector.
|
||||
*
|
||||
* evt-event-channel
|
||||
* Values: <uint32_t>
|
||||
*
|
||||
* The identifier of the Xen connector's event channel
|
||||
* used to signal activity in the ring buffer.
|
||||
*
|
||||
* evt-ring-ref
|
||||
* Values: <uint32_t>
|
||||
*
|
||||
* The Xen grant reference granting permission for the backend to map
|
||||
* a sole page of connector's event ring buffer.
|
||||
*/
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* STATE DIAGRAMS
|
||||
******************************************************************************
|
||||
*
|
||||
* Tool stack creates front and back state nodes with initial state
|
||||
* XenbusStateInitialising.
|
||||
* Tool stack creates and sets up frontend display configuration
|
||||
* nodes per domain.
|
||||
*
|
||||
*-------------------------------- Normal flow --------------------------------
|
||||
*
|
||||
* Front Back
|
||||
* ================================= =====================================
|
||||
* XenbusStateInitialising XenbusStateInitialising
|
||||
* o Query backend device identification
|
||||
* data.
|
||||
* o Open and validate backend device.
|
||||
* |
|
||||
* |
|
||||
* V
|
||||
* XenbusStateInitWait
|
||||
*
|
||||
* o Query frontend configuration
|
||||
* o Allocate and initialize
|
||||
* event channels per configured
|
||||
* connector.
|
||||
* o Publish transport parameters
|
||||
* that will be in effect during
|
||||
* this connection.
|
||||
* |
|
||||
* |
|
||||
* V
|
||||
* XenbusStateInitialised
|
||||
*
|
||||
* o Query frontend transport parameters.
|
||||
* o Connect to the event channels.
|
||||
* |
|
||||
* |
|
||||
* V
|
||||
* XenbusStateConnected
|
||||
*
|
||||
* o Create and initialize OS
|
||||
* virtual display connectors
|
||||
* as per configuration.
|
||||
* |
|
||||
* |
|
||||
* V
|
||||
* XenbusStateConnected
|
||||
*
|
||||
* XenbusStateUnknown
|
||||
* XenbusStateClosed
|
||||
* XenbusStateClosing
|
||||
* o Remove virtual display device
|
||||
* o Remove event channels
|
||||
* |
|
||||
* |
|
||||
* V
|
||||
* XenbusStateClosed
|
||||
*
|
||||
*------------------------------- Recovery flow -------------------------------
|
||||
*
|
||||
* In case of frontend unrecoverable errors backend handles that as
|
||||
* if frontend goes into the XenbusStateClosed state.
|
||||
*
|
||||
* In case of backend unrecoverable errors frontend tries removing
|
||||
* the virtualized device. If this is possible at the moment of error,
|
||||
* then frontend goes into the XenbusStateInitialising state and is ready for
|
||||
* new connection with backend. If the virtualized device is still in use and
|
||||
* cannot be removed, then frontend goes into the XenbusStateReconfiguring state
|
||||
* until either the virtualized device is removed or backend initiates a new
|
||||
* connection. On the virtualized device removal frontend goes into the
|
||||
* XenbusStateInitialising state.
|
||||
*
|
||||
* Note on XenbusStateReconfiguring state of the frontend: if backend has
|
||||
* unrecoverable errors then frontend cannot send requests to the backend
|
||||
* and thus cannot provide functionality of the virtualized device anymore.
|
||||
* After backend is back to normal the virtualized device may still hold some
|
||||
* state: configuration in use, allocated buffers, client application state etc.
|
||||
* In most cases, this will require frontend to implement complex recovery
|
||||
* reconnect logic. Instead, by going into XenbusStateReconfiguring state,
|
||||
* frontend will make sure no new clients of the virtualized device are
|
||||
* accepted, allow existing client(s) to exit gracefully by signaling error
|
||||
* state etc.
|
||||
* Once all the clients are gone frontend can reinitialize the virtualized
|
||||
* device and get into XenbusStateInitialising state again signaling the
|
||||
* backend that a new connection can be made.
|
||||
*
|
||||
* There are multiple conditions possible under which frontend will go from
|
||||
* XenbusStateReconfiguring into XenbusStateInitialising, some of them are OS
|
||||
* specific. For example:
|
||||
* 1. The underlying OS framework may provide callbacks to signal that the last
|
||||
* client of the virtualized device has gone and the device can be removed
|
||||
* 2. Frontend can schedule a deferred work (timer/tasklet/workqueue)
|
||||
* to periodically check if this is the right time to re-try removal of
|
||||
* the virtualized device.
|
||||
* 3. By any other means.
|
||||
*
|
||||
******************************************************************************
|
||||
* REQUEST CODES
|
||||
******************************************************************************
|
||||
* Request codes [0; 15] are reserved and must not be used
|
||||
*/
|
||||
|
||||
#define XENDISPL_OP_DBUF_CREATE 0x10
|
||||
#define XENDISPL_OP_DBUF_DESTROY 0x11
|
||||
#define XENDISPL_OP_FB_ATTACH 0x12
|
||||
#define XENDISPL_OP_FB_DETACH 0x13
|
||||
#define XENDISPL_OP_SET_CONFIG 0x14
|
||||
#define XENDISPL_OP_PG_FLIP 0x15
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* EVENT CODES
|
||||
******************************************************************************
|
||||
*/
|
||||
#define XENDISPL_EVT_PG_FLIP 0x00
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* XENSTORE FIELD AND PATH NAME STRINGS, HELPERS
|
||||
******************************************************************************
|
||||
*/
|
||||
#define XENDISPL_DRIVER_NAME "vdispl"
|
||||
|
||||
#define XENDISPL_LIST_SEPARATOR ","
|
||||
#define XENDISPL_RESOLUTION_SEPARATOR "x"
|
||||
|
||||
#define XENDISPL_FIELD_BE_VERSIONS "versions"
|
||||
#define XENDISPL_FIELD_FE_VERSION "version"
|
||||
#define XENDISPL_FIELD_REQ_RING_REF "req-ring-ref"
|
||||
#define XENDISPL_FIELD_REQ_CHANNEL "req-event-channel"
|
||||
#define XENDISPL_FIELD_EVT_RING_REF "evt-ring-ref"
|
||||
#define XENDISPL_FIELD_EVT_CHANNEL "evt-event-channel"
|
||||
#define XENDISPL_FIELD_RESOLUTION "resolution"
|
||||
#define XENDISPL_FIELD_BE_ALLOC "be-alloc"
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* STATUS RETURN CODES
|
||||
******************************************************************************
|
||||
*
|
||||
* Status return code is zero on success and -XEN_EXX on failure.
|
||||
*
|
||||
******************************************************************************
|
||||
* Assumptions
|
||||
******************************************************************************
|
||||
* o usage of grant reference 0 as invalid grant reference:
|
||||
* grant reference 0 is valid, but never exposed to a PV driver,
|
||||
* because of the fact it is already in use/reserved by the PV console.
|
||||
* o all references in this document to page sizes must be treated
|
||||
* as pages of size XEN_PAGE_SIZE unless otherwise noted.
|
||||
*
|
||||
******************************************************************************
|
||||
* Description of the protocol between frontend and backend driver
|
||||
******************************************************************************
|
||||
*
|
||||
* The two halves of a Para-virtual display driver communicate with
|
||||
* each other using shared pages and event channels.
|
||||
* Shared page contains a ring with request/response packets.
|
||||
*
|
||||
* All reserved fields in the structures below must be 0.
|
||||
* Display buffers's cookie of value 0 is treated as invalid.
|
||||
* Framebuffer's cookie of value 0 is treated as invalid.
|
||||
*
|
||||
* For all request/response/event packets that use cookies:
|
||||
* dbuf_cookie - uint64_t, unique to guest domain value used by the backend
|
||||
* to map remote display buffer to its local one
|
||||
* fb_cookie - uint64_t, unique to guest domain value used by the backend
|
||||
* to map remote framebuffer to its local one
|
||||
*
|
||||
*---------------------------------- Requests ---------------------------------
|
||||
*
|
||||
* All requests/responses, which are not connector specific, must be sent over
|
||||
* control ring of the connector which has the index value of 0:
|
||||
* /local/domain/<dom-id>/device/vdispl/<dev-id>/0/req-ring-ref
|
||||
*
|
||||
* All request packets have the same length (64 octets)
|
||||
* All request packets have common header:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | operation | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* id - uint16_t, private guest value, echoed in response
|
||||
* operation - uint8_t, operation code, XENDISPL_OP_???
|
||||
*
|
||||
* Request dbuf creation - request creation of a display buffer.
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id |_OP_DBUF_CREATE | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | dbuf_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | dbuf_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | width | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | height | 24
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | bpp | 28
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | buffer_sz | 32
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | flags | 36
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | gref_directory | 40
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 44
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* Must be sent over control ring of the connector which has the index
|
||||
* value of 0:
|
||||
* /local/domain/<dom-id>/device/vdispl/<dev-id>/0/req-ring-ref
|
||||
* All unused bits in flags field must be set to 0.
|
||||
*
|
||||
* An attempt to create multiple display buffers with the same dbuf_cookie is
|
||||
* an error. dbuf_cookie can be re-used after destroying the corresponding
|
||||
* display buffer.
|
||||
*
|
||||
* Width and height of the display buffers can be smaller, equal or bigger
|
||||
* than the connector's resolution. Depth/pixel format of the individual
|
||||
* buffers can differ as well.
|
||||
*
|
||||
* width - uint32_t, width in pixels
|
||||
* height - uint32_t, height in pixels
|
||||
* bpp - uint32_t, bits per pixel
|
||||
* buffer_sz - uint32_t, buffer size to be allocated, octets
|
||||
* flags - uint32_t, flags of the operation
|
||||
* o XENDISPL_DBUF_FLG_REQ_ALLOC - if set, then backend is requested
|
||||
* to allocate the buffer with the parameters provided in this request.
|
||||
* Page directory is handled as follows:
|
||||
* Frontend on request:
|
||||
* o allocates pages for the directory (gref_directory,
|
||||
* gref_dir_next_page(s)
|
||||
* o grants permissions for the pages of the directory to the backend
|
||||
* o sets gref_dir_next_page fields
|
||||
* Backend on response:
|
||||
* o grants permissions for the pages of the buffer allocated to
|
||||
* the frontend
|
||||
* o fills in page directory with grant references
|
||||
* (gref[] in struct xendispl_page_directory)
|
||||
* gref_directory - grant_ref_t, a reference to the first shared page
|
||||
* describing shared buffer references. At least one page exists. If shared
|
||||
* buffer size (buffer_sz) exceeds what can be addressed by this single page,
|
||||
* then reference to the next page must be supplied (see gref_dir_next_page
|
||||
* below)
|
||||
*/
|
||||
|
||||
#define XENDISPL_DBUF_FLG_REQ_ALLOC (1 << 0)
|
||||
|
||||
struct xendispl_dbuf_create_req {
|
||||
uint64_t dbuf_cookie;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t bpp;
|
||||
uint32_t buffer_sz;
|
||||
uint32_t flags;
|
||||
grant_ref_t gref_directory;
|
||||
};
|
||||
|
||||
/*
|
||||
* Shared page for XENDISPL_OP_DBUF_CREATE buffer descriptor (gref_directory in
|
||||
* the request) employs a list of pages, describing all pages of the shared
|
||||
* data buffer:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | gref_dir_next_page | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | gref[0] | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | gref[i] | i*4+8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | gref[N - 1] | N*4+8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* gref_dir_next_page - grant_ref_t, reference to the next page describing
|
||||
* page directory. Must be 0 if there are no more pages in the list.
|
||||
* gref[i] - grant_ref_t, reference to a shared page of the buffer
|
||||
* allocated at XENDISPL_OP_DBUF_CREATE
|
||||
*
|
||||
* Number of grant_ref_t entries in the whole page directory is not
|
||||
* passed, but instead can be calculated as:
|
||||
* num_grefs_total = (XENDISPL_OP_DBUF_CREATE.buffer_sz + XEN_PAGE_SIZE - 1) /
|
||||
* XEN_PAGE_SIZE
|
||||
*/
|
||||
|
||||
struct xendispl_page_directory {
|
||||
grant_ref_t gref_dir_next_page;
|
||||
grant_ref_t gref[1]; /* Variable length */
|
||||
};
|
||||
|
||||
/*
|
||||
* Request dbuf destruction - destroy a previously allocated display buffer:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id |_OP_DBUF_DESTROY| reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | dbuf_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | dbuf_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* Must be sent over control ring of the connector which has the index
|
||||
* value of 0:
|
||||
* /local/domain/<dom-id>/device/vdispl/<dev-id>/0/req-ring-ref
|
||||
*/
|
||||
|
||||
struct xendispl_dbuf_destroy_req {
|
||||
uint64_t dbuf_cookie;
|
||||
};
|
||||
|
||||
/*
|
||||
* Request framebuffer attachment - request attachment of a framebuffer to
|
||||
* previously created display buffer.
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | _OP_FB_ATTACH | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | dbuf_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | dbuf_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie low 32-bit | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie high 32-bit | 24
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | width | 28
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | height | 32
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | pixel_format | 36
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 40
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* Must be sent over control ring of the connector which has the index
|
||||
* value of 0:
|
||||
* /local/domain/<dom-id>/device/vdispl/<dev-id>/0/req-ring-ref
|
||||
* Width and height can be smaller, equal or bigger than the connector's
|
||||
* resolution.
|
||||
*
|
||||
* An attempt to create multiple frame buffers with the same fb_cookie is
|
||||
* an error. fb_cookie can be re-used after destroying the corresponding
|
||||
* frame buffer.
|
||||
*
|
||||
* width - uint32_t, width in pixels
|
||||
* height - uint32_t, height in pixels
|
||||
* pixel_format - uint32_t, pixel format of the framebuffer, FOURCC code
|
||||
*/
|
||||
|
||||
struct xendispl_fb_attach_req {
|
||||
uint64_t dbuf_cookie;
|
||||
uint64_t fb_cookie;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t pixel_format;
|
||||
};
|
||||
|
||||
/*
|
||||
* Request framebuffer detach - detach a previously
|
||||
* attached framebuffer from the display buffer in request:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | _OP_FB_DETACH | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* Must be sent over control ring of the connector which has the index
|
||||
* value of 0:
|
||||
* /local/domain/<dom-id>/device/vdispl/<dev-id>/0/req-ring-ref
|
||||
*/
|
||||
|
||||
struct xendispl_fb_detach_req {
|
||||
uint64_t fb_cookie;
|
||||
};
|
||||
|
||||
/*
|
||||
* Request configuration set/reset - request to set or reset
|
||||
* the configuration/mode of the display:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | _OP_SET_CONFIG | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | x | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | y | 24
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | width | 28
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | height | 32
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | bpp | 40
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 44
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* Pass all zeros to reset, otherwise command is treated as
|
||||
* configuration set.
|
||||
* Framebuffer's cookie defines which framebuffer/dbuf must be
|
||||
* displayed while enabling display (applying configuration).
|
||||
* x, y, width and height are bound by the connector's resolution and must not
|
||||
* exceed it.
|
||||
*
|
||||
* x - uint32_t, starting position in pixels by X axis
|
||||
* y - uint32_t, starting position in pixels by Y axis
|
||||
* width - uint32_t, width in pixels
|
||||
* height - uint32_t, height in pixels
|
||||
* bpp - uint32_t, bits per pixel
|
||||
*/
|
||||
|
||||
struct xendispl_set_config_req {
|
||||
uint64_t fb_cookie;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t bpp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Request page flip - request to flip a page identified by the framebuffer
|
||||
* cookie:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | _OP_PG_FLIP | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*/
|
||||
|
||||
struct xendispl_page_flip_req {
|
||||
uint64_t fb_cookie;
|
||||
};
|
||||
|
||||
/*
|
||||
*---------------------------------- Responses --------------------------------
|
||||
*
|
||||
* All response packets have the same length (64 octets)
|
||||
*
|
||||
* All response packets have common header:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | status | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* id - uint16_t, private guest value, echoed from request
|
||||
* status - int32_t, response status, zero on success and -XEN_EXX on failure
|
||||
*
|
||||
*----------------------------------- Events ----------------------------------
|
||||
*
|
||||
* Events are sent via a shared page allocated by the front and propagated by
|
||||
* evt-event-channel/evt-ring-ref XenStore entries
|
||||
* All event packets have the same length (64 octets)
|
||||
* All event packets have common header:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | type | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*
|
||||
* id - uint16_t, event id, may be used by front
|
||||
* type - uint8_t, type of the event
|
||||
*
|
||||
*
|
||||
* Page flip complete event - event from back to front on page flip completed:
|
||||
* 0 1 2 3 octet
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | id | _EVT_PG_FLIP | reserved | 4
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 8
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie low 32-bit | 12
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | fb_cookie high 32-bit | 16
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 20
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/|
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
* | reserved | 64
|
||||
* +----------------+----------------+----------------+----------------+
|
||||
*/
|
||||
|
||||
struct xendispl_pg_flip_evt {
|
||||
uint64_t fb_cookie;
|
||||
};
|
||||
|
||||
struct xendispl_req {
|
||||
uint16_t id;
|
||||
uint8_t operation;
|
||||
uint8_t reserved[5];
|
||||
union {
|
||||
struct xendispl_dbuf_create_req dbuf_create;
|
||||
struct xendispl_dbuf_destroy_req dbuf_destroy;
|
||||
struct xendispl_fb_attach_req fb_attach;
|
||||
struct xendispl_fb_detach_req fb_detach;
|
||||
struct xendispl_set_config_req set_config;
|
||||
struct xendispl_page_flip_req pg_flip;
|
||||
uint8_t reserved[56];
|
||||
} op;
|
||||
};
|
||||
|
||||
struct xendispl_resp {
|
||||
uint16_t id;
|
||||
uint8_t operation;
|
||||
uint8_t reserved;
|
||||
int32_t status;
|
||||
uint8_t reserved1[56];
|
||||
};
|
||||
|
||||
struct xendispl_evt {
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
uint8_t reserved[5];
|
||||
union {
|
||||
struct xendispl_pg_flip_evt pg_flip;
|
||||
uint8_t reserved[56];
|
||||
} op;
|
||||
};
|
||||
|
||||
DEFINE_RING_TYPES(xen_displif, struct xendispl_req, struct xendispl_resp);
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* Back to front events delivery
|
||||
******************************************************************************
|
||||
* In order to deliver asynchronous events from back to front a shared page is
|
||||
* allocated by front and its granted reference propagated to back via
|
||||
* XenStore entries (evt-ring-ref/evt-event-channel).
|
||||
* This page has a common header used by both front and back to synchronize
|
||||
* access and control event's ring buffer, while back being a producer of the
|
||||
* events and front being a consumer. The rest of the page after the header
|
||||
* is used for event packets.
|
||||
*
|
||||
* Upon reception of an event(s) front may confirm its reception
|
||||
* for either each event, group of events or none.
|
||||
*/
|
||||
|
||||
struct xendispl_event_page {
|
||||
uint32_t in_cons;
|
||||
uint32_t in_prod;
|
||||
uint8_t reserved[56];
|
||||
};
|
||||
|
||||
#define XENDISPL_EVENT_PAGE_SIZE 4096
|
||||
#define XENDISPL_IN_RING_OFFS (sizeof(struct xendispl_event_page))
|
||||
#define XENDISPL_IN_RING_SIZE (XENDISPL_EVENT_PAGE_SIZE - XENDISPL_IN_RING_OFFS)
|
||||
#define XENDISPL_IN_RING_LEN (XENDISPL_IN_RING_SIZE / sizeof(struct xendispl_evt))
|
||||
#define XENDISPL_IN_RING(page) \
|
||||
((struct xendispl_evt *)((char *)(page) + XENDISPL_IN_RING_OFFS))
|
||||
#define XENDISPL_IN_RING_REF(page, idx) \
|
||||
(XENDISPL_IN_RING((page))[(idx) % XENDISPL_IN_RING_LEN])
|
||||
|
||||
#endif /* __XEN_PUBLIC_IO_DISPLIF_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* pvcalls.h -- Xen PV Calls Protocol
|
||||
*
|
||||
* Refer to docs/misc/pvcalls.markdown for the specification
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright (C) 2017 Stefano Stabellini <stefano@aporeto.com>
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PUBLIC_IO_PVCALLS_H__
|
||||
#define __XEN_PUBLIC_IO_PVCALLS_H__
|
||||
|
||||
#include "../grant_table.h"
|
||||
#include "ring.h"
|
||||
|
||||
/*
|
||||
* See docs/misc/pvcalls.markdown in xen.git for the full specification:
|
||||
* https://xenbits.xen.org/docs/unstable/misc/pvcalls.html
|
||||
*/
|
||||
struct pvcalls_data_intf {
|
||||
RING_IDX in_cons, in_prod, in_error;
|
||||
|
||||
uint8_t pad1[52];
|
||||
|
||||
RING_IDX out_cons, out_prod, out_error;
|
||||
|
||||
uint8_t pad2[52];
|
||||
|
||||
RING_IDX ring_order;
|
||||
grant_ref_t ref[];
|
||||
};
|
||||
DEFINE_XEN_FLEX_RING(pvcalls);
|
||||
|
||||
#define PVCALLS_SOCKET 0
|
||||
#define PVCALLS_CONNECT 1
|
||||
#define PVCALLS_RELEASE 2
|
||||
#define PVCALLS_BIND 3
|
||||
#define PVCALLS_LISTEN 4
|
||||
#define PVCALLS_ACCEPT 5
|
||||
#define PVCALLS_POLL 6
|
||||
|
||||
struct xen_pvcalls_request {
|
||||
uint32_t req_id; /* private to guest, echoed in response */
|
||||
uint32_t cmd; /* command to execute */
|
||||
union {
|
||||
struct xen_pvcalls_socket {
|
||||
uint64_t id;
|
||||
uint32_t domain;
|
||||
uint32_t type;
|
||||
uint32_t protocol;
|
||||
} socket;
|
||||
struct xen_pvcalls_connect {
|
||||
uint64_t id;
|
||||
uint8_t addr[28];
|
||||
uint32_t len;
|
||||
uint32_t flags;
|
||||
grant_ref_t ref;
|
||||
uint32_t evtchn;
|
||||
} connect;
|
||||
struct xen_pvcalls_release {
|
||||
uint64_t id;
|
||||
uint8_t reuse;
|
||||
} release;
|
||||
struct xen_pvcalls_bind {
|
||||
uint64_t id;
|
||||
uint8_t addr[28];
|
||||
uint32_t len;
|
||||
} bind;
|
||||
struct xen_pvcalls_listen {
|
||||
uint64_t id;
|
||||
uint32_t backlog;
|
||||
} listen;
|
||||
struct xen_pvcalls_accept {
|
||||
uint64_t id;
|
||||
uint64_t id_new;
|
||||
grant_ref_t ref;
|
||||
uint32_t evtchn;
|
||||
} accept;
|
||||
struct xen_pvcalls_poll {
|
||||
uint64_t id;
|
||||
} poll;
|
||||
/* dummy member to force sizeof(struct xen_pvcalls_request)
|
||||
* to match across archs */
|
||||
struct xen_pvcalls_dummy {
|
||||
uint8_t dummy[56];
|
||||
} dummy;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct xen_pvcalls_response {
|
||||
uint32_t req_id;
|
||||
uint32_t cmd;
|
||||
int32_t ret;
|
||||
uint32_t pad;
|
||||
union {
|
||||
struct _xen_pvcalls_socket {
|
||||
uint64_t id;
|
||||
} socket;
|
||||
struct _xen_pvcalls_connect {
|
||||
uint64_t id;
|
||||
} connect;
|
||||
struct _xen_pvcalls_release {
|
||||
uint64_t id;
|
||||
} release;
|
||||
struct _xen_pvcalls_bind {
|
||||
uint64_t id;
|
||||
} bind;
|
||||
struct _xen_pvcalls_listen {
|
||||
uint64_t id;
|
||||
} listen;
|
||||
struct _xen_pvcalls_accept {
|
||||
uint64_t id;
|
||||
} accept;
|
||||
struct _xen_pvcalls_poll {
|
||||
uint64_t id;
|
||||
} poll;
|
||||
struct _xen_pvcalls_dummy {
|
||||
uint8_t dummy[8];
|
||||
} dummy;
|
||||
} u;
|
||||
};
|
||||
|
||||
DEFINE_RING_TYPES(xen_pvcalls, struct xen_pvcalls_request,
|
||||
struct xen_pvcalls_response);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -27,6 +27,21 @@
|
||||
#ifndef __XEN_PUBLIC_IO_RING_H__
|
||||
#define __XEN_PUBLIC_IO_RING_H__
|
||||
|
||||
/*
|
||||
* When #include'ing this header, you need to provide the following
|
||||
* declaration upfront:
|
||||
* - standard integers types (uint8_t, uint16_t, etc)
|
||||
* They are provided by stdint.h of the standard headers.
|
||||
*
|
||||
* In addition, if you intend to use the FLEX macros, you also need to
|
||||
* provide the following, before invoking the FLEX macros:
|
||||
* - size_t
|
||||
* - memcpy
|
||||
* - grant_ref_t
|
||||
* These declarations are provided by string.h of the standard headers,
|
||||
* and grant_table.h from the Xen public headers.
|
||||
*/
|
||||
|
||||
#include "../xen-compat.h"
|
||||
|
||||
#if __XEN_INTERFACE_VERSION__ < 0x00030208
|
||||
@@ -313,6 +328,149 @@ typedef struct __name##_back_ring __name##_back_ring_t
|
||||
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* DEFINE_XEN_FLEX_RING_AND_INTF defines two monodirectional rings and
|
||||
* functions to check if there is data on the ring, and to read and
|
||||
* write to them.
|
||||
*
|
||||
* DEFINE_XEN_FLEX_RING is similar to DEFINE_XEN_FLEX_RING_AND_INTF, but
|
||||
* does not define the indexes page. As different protocols can have
|
||||
* extensions to the basic format, this macro allow them to define their
|
||||
* own struct.
|
||||
*
|
||||
* XEN_FLEX_RING_SIZE
|
||||
* Convenience macro to calculate the size of one of the two rings
|
||||
* from the overall order.
|
||||
*
|
||||
* $NAME_mask
|
||||
* Function to apply the size mask to an index, to reduce the index
|
||||
* within the range [0-size].
|
||||
*
|
||||
* $NAME_read_packet
|
||||
* Function to read data from the ring. The amount of data to read is
|
||||
* specified by the "size" argument.
|
||||
*
|
||||
* $NAME_write_packet
|
||||
* Function to write data to the ring. The amount of data to write is
|
||||
* specified by the "size" argument.
|
||||
*
|
||||
* $NAME_get_ring_ptr
|
||||
* Convenience function that returns a pointer to read/write to the
|
||||
* ring at the right location.
|
||||
*
|
||||
* $NAME_data_intf
|
||||
* Indexes page, shared between frontend and backend. It also
|
||||
* contains the array of grant refs.
|
||||
*
|
||||
* $NAME_queued
|
||||
* Function to calculate how many bytes are currently on the ring,
|
||||
* ready to be read. It can also be used to calculate how much free
|
||||
* space is currently on the ring (XEN_FLEX_RING_SIZE() -
|
||||
* $NAME_queued()).
|
||||
*/
|
||||
|
||||
#ifndef XEN_PAGE_SHIFT
|
||||
/* The PAGE_SIZE for ring protocols and hypercall interfaces is always
|
||||
* 4K, regardless of the architecture, and page granularity chosen by
|
||||
* operating systems.
|
||||
*/
|
||||
#define XEN_PAGE_SHIFT 12
|
||||
#endif
|
||||
#define XEN_FLEX_RING_SIZE(order) \
|
||||
(1UL << ((order) + XEN_PAGE_SHIFT - 1))
|
||||
|
||||
#define DEFINE_XEN_FLEX_RING(name) \
|
||||
static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \
|
||||
{ \
|
||||
return idx & (ring_size - 1); \
|
||||
} \
|
||||
\
|
||||
static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \
|
||||
RING_IDX idx, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
return buf + name##_mask(idx, ring_size); \
|
||||
} \
|
||||
\
|
||||
static inline void name##_read_packet(void *opaque, \
|
||||
const unsigned char *buf, \
|
||||
size_t size, \
|
||||
RING_IDX masked_prod, \
|
||||
RING_IDX *masked_cons, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
if (*masked_cons < masked_prod || \
|
||||
size <= ring_size - *masked_cons) { \
|
||||
memcpy(opaque, buf + *masked_cons, size); \
|
||||
} else { \
|
||||
memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \
|
||||
memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \
|
||||
size - (ring_size - *masked_cons)); \
|
||||
} \
|
||||
*masked_cons = name##_mask(*masked_cons + size, ring_size); \
|
||||
} \
|
||||
\
|
||||
static inline void name##_write_packet(unsigned char *buf, \
|
||||
const void *opaque, \
|
||||
size_t size, \
|
||||
RING_IDX *masked_prod, \
|
||||
RING_IDX masked_cons, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
if (*masked_prod < masked_cons || \
|
||||
size <= ring_size - *masked_prod) { \
|
||||
memcpy(buf + *masked_prod, opaque, size); \
|
||||
} else { \
|
||||
memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \
|
||||
memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \
|
||||
size - (ring_size - *masked_prod)); \
|
||||
} \
|
||||
*masked_prod = name##_mask(*masked_prod + size, ring_size); \
|
||||
} \
|
||||
\
|
||||
static inline RING_IDX name##_queued(RING_IDX prod, \
|
||||
RING_IDX cons, \
|
||||
RING_IDX ring_size) \
|
||||
{ \
|
||||
RING_IDX size; \
|
||||
\
|
||||
if (prod == cons) \
|
||||
return 0; \
|
||||
\
|
||||
prod = name##_mask(prod, ring_size); \
|
||||
cons = name##_mask(cons, ring_size); \
|
||||
\
|
||||
if (prod == cons) \
|
||||
return ring_size; \
|
||||
\
|
||||
if (prod > cons) \
|
||||
size = prod - cons; \
|
||||
else \
|
||||
size = ring_size - (cons - prod); \
|
||||
return size; \
|
||||
} \
|
||||
\
|
||||
struct name##_data { \
|
||||
unsigned char *in; /* half of the allocation */ \
|
||||
unsigned char *out; /* half of the allocation */ \
|
||||
}
|
||||
|
||||
#define DEFINE_XEN_FLEX_RING_AND_INTF(name) \
|
||||
struct name##_data_intf { \
|
||||
RING_IDX in_cons, in_prod; \
|
||||
\
|
||||
uint8_t pad1[56]; \
|
||||
\
|
||||
RING_IDX out_cons, out_prod; \
|
||||
\
|
||||
uint8_t pad2[56]; \
|
||||
\
|
||||
RING_IDX ring_order; \
|
||||
grant_ref_t ref[]; \
|
||||
}; \
|
||||
DEFINE_XEN_FLEX_RING(name)
|
||||
|
||||
#endif /* __XEN_PUBLIC_IO_RING_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -770,7 +770,9 @@ DEFINE_XEN_GUEST_HANDLE(xen_sysctl_psr_cat_op_t);
|
||||
#define XEN_SYSCTL_TMEM_OP_SET_CLIENT_INFO 6
|
||||
#define XEN_SYSCTL_TMEM_OP_GET_POOLS 7
|
||||
#define XEN_SYSCTL_TMEM_OP_QUERY_FREEABLE_MB 8
|
||||
#define XEN_SYSCTL_TMEM_OP_SET_POOLS 9
|
||||
#define XEN_SYSCTL_TMEM_OP_SAVE_BEGIN 10
|
||||
#define XEN_SYSCTL_TMEM_OP_SET_AUTH 11
|
||||
#define XEN_SYSCTL_TMEM_OP_SAVE_GET_NEXT_PAGE 19
|
||||
#define XEN_SYSCTL_TMEM_OP_SAVE_GET_NEXT_INV 20
|
||||
#define XEN_SYSCTL_TMEM_OP_SAVE_END 21
|
||||
@@ -812,10 +814,14 @@ typedef struct xen_tmem_client xen_tmem_client_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_tmem_client_t);
|
||||
|
||||
/*
|
||||
* XEN_SYSCTL_TMEM_OP_GET_POOLS uses the 'pool' array in
|
||||
* xen_sysctl_tmem_op with this structure. The hypercall will
|
||||
* XEN_SYSCTL_TMEM_OP_[GET|SET]_POOLS or XEN_SYSCTL_TMEM_OP_SET_AUTH
|
||||
* uses the 'pool' array in * xen_sysctl_tmem_op with this structure.
|
||||
* The XEN_SYSCTL_TMEM_OP_GET_POOLS hypercall will
|
||||
* return the number of entries in 'pool' or a negative value
|
||||
* if an error was encountered.
|
||||
* The XEN_SYSCTL_TMEM_OP_SET_[AUTH|POOLS] will return the number of
|
||||
* entries in 'pool' processed or a negative value if an error
|
||||
* was encountered.
|
||||
*/
|
||||
struct xen_tmem_pool_info {
|
||||
union {
|
||||
@@ -823,14 +829,15 @@ struct xen_tmem_pool_info {
|
||||
struct {
|
||||
uint32_t persist:1, /* See TMEM_POOL_PERSIST. */
|
||||
shared:1, /* See TMEM_POOL_SHARED. */
|
||||
rsv:2,
|
||||
auth:1, /* See TMEM_POOL_AUTH. */
|
||||
rsv1:1,
|
||||
pagebits:8, /* TMEM_POOL_PAGESIZE_[SHIFT,MASK]. */
|
||||
rsv2:12,
|
||||
version:8; /* TMEM_POOL_VERSION_[SHIFT,MASK]. */
|
||||
} u;
|
||||
} flags;
|
||||
uint32_t id; /* Less than tmem_client.maxpools. */
|
||||
uint64_t n_pages;
|
||||
uint64_t n_pages; /* Zero on XEN_SYSCTL_TMEM_OP_SET_[AUTH|POOLS]. */
|
||||
uint64_aligned_t uuid[2];
|
||||
};
|
||||
typedef struct xen_tmem_pool_info xen_tmem_pool_info_t;
|
||||
|
||||
@@ -51,9 +51,9 @@
|
||||
#define TMEM_XCHG 10
|
||||
#endif
|
||||
|
||||
/* Privileged commands to HYPERVISOR_tmem_op() */
|
||||
#define TMEM_AUTH 101
|
||||
#define TMEM_RESTORE_NEW 102
|
||||
/* Privileged commands now called via XEN_SYSCTL_tmem_op. */
|
||||
#define TMEM_AUTH 101 /* as XEN_SYSCTL_TMEM_OP_SET_AUTH. */
|
||||
#define TMEM_RESTORE_NEW 102 /* as XEN_SYSCTL_TMEM_OP_SET_POOL. */
|
||||
|
||||
/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
|
||||
#define TMEM_POOL_PERSIST 1
|
||||
@@ -92,7 +92,7 @@ struct tmem_op {
|
||||
uint64_t uuid[2];
|
||||
uint32_t flags;
|
||||
uint32_t arg1;
|
||||
} creat; /* for cmd == TMEM_NEW_POOL, TMEM_AUTH, TMEM_RESTORE_NEW */
|
||||
} creat; /* for cmd == TMEM_NEW_POOL. */
|
||||
struct {
|
||||
#if __XEN_INTERFACE_VERSION__ < 0x00040600
|
||||
uint64_t oid[3];
|
||||
|
||||
@@ -18,6 +18,12 @@ extern rwlock_t tmem_rwlock;
|
||||
int tmem_evict(void);
|
||||
int do_tmem_control(struct xen_sysctl_tmem_op *op);
|
||||
|
||||
struct client *client_create(domid_t cli_id);
|
||||
int do_tmem_new_pool(domid_t this_cli_id, uint32_t d_poolid, uint32_t flags,
|
||||
uint64_t uuid_lo, uint64_t uuid_hi);
|
||||
|
||||
int tmemc_shared_pool_auth(domid_t cli_id, uint64_t uuid_lo,
|
||||
uint64_t uuid_hi, bool auth);
|
||||
#endif /* CONFIG_TMEM */
|
||||
|
||||
#endif /* __XEN_TMEM_CONTROL_H__ */
|
||||
|
||||
@@ -41,12 +41,6 @@ static inline bool_t tmem_compression_enabled(void)
|
||||
return opt_tmem_compress;
|
||||
}
|
||||
|
||||
extern bool_t opt_tmem_shared_auth;
|
||||
static inline bool_t tmem_shared_auth(void)
|
||||
{
|
||||
return opt_tmem_shared_auth;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TMEM
|
||||
extern bool_t opt_tmem;
|
||||
static inline bool_t tmem_enabled(void)
|
||||
@@ -198,8 +192,6 @@ static inline int tmem_get_tmemop_from_client(tmem_op_t *op, tmem_cli_op_t uops)
|
||||
switch ( cop.cmd )
|
||||
{
|
||||
case TMEM_NEW_POOL: u = XLAT_tmem_op_u_creat; break;
|
||||
case TMEM_AUTH: u = XLAT_tmem_op_u_creat; break;
|
||||
case TMEM_RESTORE_NEW:u = XLAT_tmem_op_u_creat; break;
|
||||
default: u = XLAT_tmem_op_u_gen ; break;
|
||||
}
|
||||
XLAT_tmem_op(op, &cop);
|
||||
@@ -293,7 +285,6 @@ struct client {
|
||||
long eph_count, eph_count_max;
|
||||
domid_t cli_id;
|
||||
xen_tmem_client_t info;
|
||||
bool_t shared_auth_required;
|
||||
/* For save/restore/migration. */
|
||||
bool_t was_frozen;
|
||||
struct list_head persistent_invalidated_list;
|
||||
|
||||