aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Ackaouy <ack@xensource.com>2007-01-05 17:34:28 +0000
committerEmmanuel Ackaouy <ack@xensource.com>2007-01-05 17:34:28 +0000
commit8589463a257a56c0316b002b7d8affc5709e4672 (patch)
treee4d8b0b664e55eab662d7d88bffcd71a080e22c7
parent6224725e9357f6056cff046ba5da4c52f0bace8c (diff)
downloadxen-8589463a257a56c0316b002b7d8affc5709e4672.tar.gz
xen-8589463a257a56c0316b002b7d8affc5709e4672.tar.bz2
xen-8589463a257a56c0316b002b7d8affc5709e4672.zip
Handle the creation of startup info for compatibility mode guests. This
includes a script to auto-generate checking or translation code between native and compatibility mode hypercall argument structures. Signed-off-by: Jan Beulich <jbeulich@novell.com>
-rw-r--r--Config.mk2
-rw-r--r--xen/arch/x86/domain_build.c6
-rw-r--r--xen/arch/x86/setup.c12
-rw-r--r--xen/common/compat/Makefile1
-rw-r--r--xen/common/compat/xlat.c32
-rw-r--r--xen/include/Makefile9
-rw-r--r--xen/include/xlat.lst5
-rw-r--r--xen/tools/get-fields.sh425
8 files changed, 491 insertions, 1 deletions
diff --git a/Config.mk b/Config.mk
index 08873d69d4..6a7ed679ac 100644
--- a/Config.mk
+++ b/Config.mk
@@ -11,6 +11,8 @@ XEN_OS ?= $(shell uname -s)
CONFIG_$(XEN_OS) := y
+SHELL ?= /bin/sh
+
# Tools to run on system hosting the build
HOSTCC = gcc
HOSTCFLAGS = -Wall -Werror -Wstrict-prototypes -O2 -fomit-frame-pointer
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index 0e15b153e1..f9e6dafce1 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -19,6 +19,7 @@
#include <xen/version.h>
#include <xen/iocap.h>
#include <xen/bitops.h>
+#include <xen/compat.h>
#include <asm/regs.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -848,6 +849,11 @@ int construct_dom0(struct domain *d,
si->console.dom0.info_size = sizeof(struct dom0_vga_console_info);
}
+#ifdef CONFIG_COMPAT
+ if ( IS_COMPAT(d) )
+ xlat_start_info(si, XLAT_start_info_console_dom0);
+#endif
+
/* Reinstate the caller's page tables. */
write_ptbase(current);
local_irq_enable();
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 928ab8f286..76b3848174 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -18,6 +18,10 @@
#include <xen/keyhandler.h>
#include <xen/numa.h>
#include <public/version.h>
+#ifdef CONFIG_COMPAT
+#include <compat/platform.h>
+#include <compat/xen.h>
+#endif
#include <asm/bitops.h>
#include <asm/smp.h>
#include <asm/processor.h>
@@ -546,6 +550,14 @@ void __init __start_xen(multiboot_info_t *mbi)
BUILD_BUG_ON(sizeof(shared_info_t) > PAGE_SIZE);
BUILD_BUG_ON(sizeof(vcpu_info_t) != 64);
+#ifdef CONFIG_COMPAT
+ BUILD_BUG_ON(sizeof(((struct compat_platform_op *)0)->u) !=
+ sizeof(((struct compat_platform_op *)0)->u.pad));
+ BUILD_BUG_ON(sizeof(start_info_compat_t) > PAGE_SIZE);
+ BUILD_BUG_ON(sizeof(shared_info_compat_t) > PAGE_SIZE);
+ BUILD_BUG_ON(sizeof(vcpu_info_compat_t) != 64);
+#endif
+
/* Check definitions in public headers match internal defs. */
BUILD_BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START);
#ifdef HYPERVISOR_VIRT_END
diff --git a/xen/common/compat/Makefile b/xen/common/compat/Makefile
index 39e1c8ee3d..ba581f053c 100644
--- a/xen/common/compat/Makefile
+++ b/xen/common/compat/Makefile
@@ -1,4 +1,5 @@
obj-y += kernel.o
+obj-y += xlat.o
# extra dependencies
kernel.o: ../kernel.c
diff --git a/xen/common/compat/xlat.c b/xen/common/compat/xlat.c
new file mode 100644
index 0000000000..63f08b36f8
--- /dev/null
+++ b/xen/common/compat/xlat.c
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * xlat.c
+ */
+
+#include <xen/compat.h>
+#include <xen/lib.h>
+#include <public/xen.h>
+#include <compat/xen.h>
+
+/* In-place translation functons: */
+void xlat_start_info(struct start_info *native,
+ enum XLAT_start_info_console console)
+{
+ struct compat_start_info *compat = (void *)native;
+
+ BUILD_BUG_ON(sizeof(*native) < sizeof(*compat));
+ XLAT_start_info(compat, native);
+}
+
+#define xen_dom0_vga_console_info dom0_vga_console_info
+CHECK_dom0_vga_console_info;
+#undef dom0_vga_console_info
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/Makefile b/xen/include/Makefile
index 1cc0d79baf..57d8fe93de 100644
--- a/xen/include/Makefile
+++ b/xen/include/Makefile
@@ -4,7 +4,7 @@ compat-arch-$(CONFIG_X86) := x86_32
headers-y := $(shell echo public/*.h | sed -e 's,[^[:space:]]*-[^[:space:]]*,,g' -e 's,public/,compat/,g')
headers-y := $(filter-out %/dom0_ops.h,$(headers-y))
-headers-y += compat/arch-$(compat-arch-y).h
+headers-y += compat/arch-$(compat-arch-y).h compat/xlat.h
cppflags-y := -include public/xen-compat.h
cppflags-$(CONFIG_X86) += -m32
@@ -53,5 +53,12 @@ compat/%.c: public/%.h Makefile
>$@.new
mv -f $@.new $@
+compat/xlat.h: xlat.lst $(filter-out compat/xlat.h,$(headers-y)) $(BASEDIR)/tools/get-fields.sh Makefile
+ grep -v '^[[:space:]]*#' xlat.lst | \
+ while read what name hdr; do \
+ $(SHELL) $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $$(echo compat/$$hdr | sed 's,@arch@,$(compat-arch-y),g') || exit $$?; \
+ done >$@.new
+ mv -f $@.new $@
+
clean::
rm -rf compat
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
new file mode 100644
index 0000000000..8b7c96278a
--- /dev/null
+++ b/xen/include/xlat.lst
@@ -0,0 +1,5 @@
+# First column indicator:
+# ! - needs translation
+# ? - needs checking
+? dom0_vga_console_info xen.h
+! start_info xen.h
diff --git a/xen/tools/get-fields.sh b/xen/tools/get-fields.sh
new file mode 100644
index 0000000000..01af5eaaf3
--- /dev/null
+++ b/xen/tools/get-fields.sh
@@ -0,0 +1,425 @@
+#!/bin/sh
+test -n "$1" -a -n "$2" -a -n "$3"
+set -ef
+
+get_fields() {
+ local level=1 aggr=0 name= fields=
+ for token in $2
+ do
+ case "$token" in
+ struct|union)
+ test $level != 1 || aggr=1 fields= name=
+ ;;
+ "{")
+ level=$(expr $level + 1)
+ ;;
+ "}")
+ level=$(expr $level - 1)
+ if [ $level = 1 -a $name = $1 ]
+ then
+ echo "$fields }"
+ return 0
+ fi
+ ;;
+ [[:alpha:]_]*)
+ test $aggr = 0 -o -n "$name" || name="$token"
+ ;;
+ esac
+ test $aggr = 0 || fields="$fields $token"
+ done
+}
+
+build_enums() {
+ local level=1 kind= fields= members= named= id= token
+ for token in $2
+ do
+ case "$token" in
+ struct|union)
+ test $level != 2 || fields=" "
+ kind="$token;$kind"
+ ;;
+ "{")
+ level=$(expr $level + 1)
+ ;;
+ "}")
+ level=$(expr $level - 1)
+ if [ $level = 1 ]
+ then
+ if [ "${kind%%;*}" = union ]
+ then
+ echo
+ echo "enum XLAT_$1 {"
+ for m in $members
+ do
+ echo " XLAT_${1}_$m,"
+ done
+ echo "};"
+ fi
+ return 0
+ elif [ $level = 2 ]
+ then
+ named='?'
+ fi
+ ;;
+ [[:alpha:]]*)
+ id=$token
+ if [ -n "$named" -a -n "${kind#*;}" ]
+ then
+ build_enums ${1}_$token "$fields"
+ named='!'
+ fi
+ ;;
+ ",")
+ test $level != 2 || members="$members $id"
+ ;;
+ ";")
+ test $level != 2 || members="$members $id"
+ test -z "$named" || kind=${kind#*;}
+ named=
+ ;;
+ esac
+ test -z "$fields" || fields="$fields $token"
+ done
+}
+
+handle_field() {
+ if [ -z "$5" ]
+ then
+ echo " \\"
+ if [ -z "$4" ]
+ then
+ echo -n "$1(_d_)->$3 = (_s_)->$3;"
+ else
+ echo -n "$1XLAT_${2}_HNDL_$(echo $3 | sed 's,\.,_,g')(_d_, _s_);"
+ fi
+ elif [ -z "$(echo "$5" | sed 's,[^{}],,g')" ]
+ then
+ local tag=$(echo "$5" | sed 's,[[:space:]]*\(struct\|union\)[[:space:]]\+\(compat_\)\?\([[:alnum:]_]\+\)[[:space:]].*,\3,')
+ echo " \\"
+ echo -n "${1}XLAT_$tag(&(_d_)->$3, &(_s_)->$3);"
+ else
+ local level=1 kind= fields= id= array= arrlvl=1 array_type= type= token
+ for token in $5
+ do
+ case "$token" in
+ struct|union)
+ test $level != 2 || fields=" "
+ if [ $level == 1 ]
+ then
+ kind=$token
+ if [ $kind = union ]
+ then
+ echo " \\"
+ echo -n "${1}switch ($(echo $3 | sed 's,\.,_,g')) {"
+ fi
+ fi
+ ;;
+ "{")
+ level=$(expr $level + 1) id=
+ ;;
+ "}")
+ level=$(expr $level - 1) id=
+ if [ $level == 1 -a $kind = union ]
+ then
+ echo " \\"
+ echo -n "$1}"
+ fi
+ ;;
+ "[")
+ if [ $level != 2 -o $arrlvl != 1 ]
+ then
+ :
+ elif [ -z "$array" ]
+ then
+ array=" "
+ else
+ array="$array;"
+ fi
+ arrlvl=$(expr $arrlvl + 1)
+ ;;
+ "]")
+ arrlvl=$(expr $arrlvl - 1)
+ ;;
+ COMPAT_HANDLE\(*\))
+ if [ $level == 2 -a -z "$id" ]
+ then
+ type=${token#COMPAT_HANDLE?}
+ type=${type%?}
+ type=${type#compat_}
+ fi
+ ;;
+ compat_domain_handle_t)
+ if [ $level == 2 -a -z "$id" ]
+ then
+ array_type=$token
+ fi
+ ;;
+ [[:alpha:]]*)
+ id=$token
+ ;;
+ [\,\;])
+ if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ then
+ if [ $kind = union ]
+ then
+ echo " \\"
+ echo -n "${1}case XLAT_${2}_$(echo $3.$id | sed 's,\.,_,g'):"
+ handle_field "$1 " $2 $3.$id "$type" "$fields"
+ elif [ -z "$array" -a -z "$array_type" ]
+ then
+ handle_field "$1" $2 $3.$id "$type" "$fields"
+ elif [ -z "$array" ]
+ then
+ copy_array " " $3.$id
+ else
+ handle_array "$1" $2 $3.$id "${array#*;}" "$type" "$fields"
+ fi
+ test "$token" != ";" || fields= id= type=
+ array=
+ if [ $kind = union ]
+ then
+ echo " \\"
+ echo -n "$1 break;"
+ fi
+ fi
+ ;;
+ *)
+ if [ -n "$array" ]
+ then
+ array="$array $token"
+ fi
+ ;;
+ esac
+ test -z "$fields" || fields="$fields $token"
+ done
+ fi
+}
+
+copy_array() {
+ echo " \\"
+ echo "${1}if ((_d_)->$2 != (_s_)->$2) \\"
+ echo -n "$1 memcpy((_d_)->$2, (_s_)->$2, sizeof((_d_)->$2));"
+}
+
+handle_array() {
+ local i="i$(echo $4 | sed 's,[^;], ,g' | wc -w)"
+ echo " \\"
+ echo "$1{ \\"
+ echo "$1 unsigned int $i; \\"
+ echo -n "$1 for ($i = 0; $i < "${4%%;*}"; ++$i) {"
+ if [ "$4" = "${4#*;}" ]
+ then
+ handle_field "$1 " $2 $3[$i] "$5" "$6"
+ else
+ handle_array "$1 " $2 $3[$i] "${4#*;}" "$5" "$6"
+ fi
+ echo " \\"
+ echo "$1 } \\"
+ echo -n "$1}"
+}
+
+build_body() {
+ echo
+ echo -n "#define XLAT_$1(_d_, _s_)"
+ local level=1 fields= id= array= arrlvl=1 array_type= type= token
+ for token in $2
+ do
+ case "$token" in
+ struct|union)
+ test $level != 2 || fields=" "
+ ;;
+ "{")
+ level=$(expr $level + 1) id=
+ ;;
+ "}")
+ level=$(expr $level - 1) id=
+ ;;
+ "[")
+ if [ $level != 2 -o $arrlvl != 1 ]
+ then
+ :
+ elif [ -z "$array" ]
+ then
+ array=" "
+ else
+ array="$array;"
+ fi
+ arrlvl=$(expr $arrlvl + 1)
+ ;;
+ "]")
+ arrlvl=$(expr $arrlvl - 1)
+ ;;
+ COMPAT_HANDLE\(*\))
+ if [ $level == 2 -a -z "$id" ]
+ then
+ type=${token#COMPAT_HANDLE?}
+ type=${type%?}
+ type=${type#compat_}
+ fi
+ ;;
+ compat_domain_handle_t)
+ if [ $level == 2 -a -z "$id" ]
+ then
+ array_type=$token
+ fi
+ ;;
+ [[:alpha:]_]*)
+ if [ -n "$array" ]
+ then
+ array="$array $token"
+ else
+ id=$token
+ fi
+ ;;
+ [\,\;])
+ if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ then
+ if [ -z "$array" -a -z "$array_type" ]
+ then
+ handle_field " " $1 $id "$type" "$fields"
+ elif [ -z "$array" ]
+ then
+ copy_array " " $id
+ else
+ handle_array " " $1 $id "${array#*;}" "$type" "$fields"
+ fi
+ test "$token" != ";" || fields= id= type=
+ array=
+ fi
+ ;;
+ *)
+ if [ -n "$array" ]
+ then
+ array="$array $token"
+ fi
+ ;;
+ esac
+ test -z "$fields" || fields="$fields $token"
+ done
+ echo ""
+}
+
+check_field() {
+ if [ -z "$(echo "$4" | sed 's,[^{}],,g')" ]
+ then
+ echo "; \\"
+ local n=$(echo $3 | sed 's,[^.], ,g' | wc -w)
+ if [ -n "$4" ]
+ then
+ for n in $4
+ do
+ case $n in
+ struct|union)
+ ;;
+ [[:alpha:]_]*)
+ echo -n " CHECK_$n"
+ break
+ ;;
+ *)
+ echo "Malformed compound declaration: '$n'" >&2
+ exit 1
+ ;;
+ esac
+ done
+ elif [ $n = 0 ]
+ then
+ echo -n " CHECK_FIELD_($1, $2, $3)"
+ else
+ echo -n " CHECK_SUBFIELD_${n}_($1, $2, $(echo $3 | sed 's!\.!, !g'))"
+ fi
+ else
+ local level=1 fields= id= token
+ for token in $4
+ do
+ case "$token" in
+ struct|union)
+ test $level != 2 || fields=" "
+ ;;
+ "{")
+ level=$(expr $level + 1) id=
+ ;;
+ "}")
+ level=$(expr $level - 1) id=
+ ;;
+ [[:alpha:]]*)
+ id=$token
+ ;;
+ [\,\;])
+ if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ then
+ check_field $1 $2 $3.$id "$fields"
+ test "$token" != ";" || fields= id=
+ fi
+ ;;
+ esac
+ test -z "$fields" || fields="$fields $token"
+ done
+ fi
+}
+
+build_check() {
+ echo
+ echo "#define CHECK_$1 \\"
+ local level=1 fields= kind= id= arrlvl=1 token
+ for token in $2
+ do
+ case "$token" in
+ struct|union)
+ if [ $level == 1 ]
+ then
+ kind=$token
+ echo -n " CHECK_SIZE_($kind, $1)"
+ elif [ $level == 2 ]
+ then
+ fields=" "
+ fi
+ ;;
+ "{")
+ level=$(expr $level + 1) id=
+ ;;
+ "}")
+ level=$(expr $level - 1) id=
+ ;;
+ "[")
+ arrlvl=$(expr $arrlvl + 1)
+ ;;
+ "]")
+ arrlvl=$(expr $arrlvl - 1)
+ ;;
+ [[:alpha:]_]*)
+ test $level != 2 -o $arrlvl != 1 || id=$token
+ ;;
+ [\,\;])
+ if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ then
+ check_field $kind $1 $id "$fields"
+ test "$token" != ";" || fields= id=
+ fi
+ ;;
+ esac
+ test -z "$fields" || fields="$fields $token"
+ done
+ echo ""
+}
+
+fields="$(get_fields $(echo $2 | sed 's,^compat_xen,compat_,') "$(sed -e 's,^[[:space:]]#.*,,' -e 's!\([]\[,;:{}]\)! \1 !g' $3)")"
+if [ -z "$fields" ]
+then
+ echo "Fields of '$2' not found in '$3'" >&2
+ exit 1
+fi
+name=${2#compat_}
+name=${name#xen}
+case "$1" in
+"!")
+ build_enums $name "$fields"
+ build_body $name "$fields"
+ ;;
+"?")
+ build_check $name "$fields"
+ ;;
+*)
+ echo "Invalid translation indicator: '$1'" >&2
+ exit 1
+ ;;
+esac