Unless I am mistaken, the compat functions are provided a stable ABI. This
includes providing a stable version of xen_kexec_range_t in the form of
compat_kexec_range_t. However, internally it doesn't really matter how xen
represents the data.
Currently the code provides for the creation of a compat version of all
kexec range functions, which use the compat_kexec_range_t function. This
is difficult to extend if range code exists outside of xen/common/kexec.c.
The existence of "#ifdef CONFIG_X86_64" in the code suggests that some of
the range code might be better off in architecture specific code.
Furthermore, subsequent patches will introduce ia64-specific range handling
code, which really would be much better off somewhere in arch/ia64/ .
With this in mind, the handling of compat_kexec_range_t is changed such
that the code which reads and returns data from user-space translates
between compat_kexec_range_t and xen_kexec_range_t. As, padding aside, the
two structures are currently the same this is quite easy. Things may get
more tricky in the future, but I don't believe this change is likely to
make things significantly worse (or better) in that regard. In any case,
refactoring can occur again as required.
Subsequent patches will add architecture specific code under xen/arch/
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
xen/common/compat/kexec.c | 5 --
xen/common/kexec.c | 79 +++++++++++++++++++++++++++++++++++----------
2 files changed, 62 insertions(+), 22 deletions(-)
Index: xen-unstable.hg/xen/common/compat/kexec.c
===================================================================
--- xen-unstable.hg.orig/xen/common/compat/kexec.c 2008-02-25
16:24:12.000000000 +0900
+++ xen-unstable.hg/xen/common/compat/kexec.c 2008-02-25 16:31:10.000000000
+0900
@@ -9,11 +9,6 @@
#define do_kexec_op compat_kexec_op
-#undef kexec_get
-#define kexec_get(x) compat_kexec_get_##x
-#define xen_kexec_range compat_kexec_range
-#define xen_kexec_range_t compat_kexec_range_t
-
#define kexec_load_unload compat_kexec_load_unload
#define xen_kexec_load compat_kexec_load
#define xen_kexec_load_t compat_kexec_load_t
Index: xen-unstable.hg/xen/common/kexec.c
===================================================================
--- xen-unstable.hg.orig/xen/common/kexec.c 2008-02-25 16:06:24.000000000
+0900
+++ xen-unstable.hg/xen/common/kexec.c 2008-02-25 17:04:20.000000000 +0900
@@ -153,11 +153,7 @@ static int sizeof_note(const char *name,
ELFNOTE_ALIGN(descsz));
}
-#define kexec_get(x) kexec_get_##x
-
-#endif
-
-static int kexec_get(reserve)(xen_kexec_range_t *range)
+static int kexec_get_reserve(xen_kexec_range_t *range)
{
if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) {
range->start = kexec_crash_area.start;
@@ -168,7 +164,7 @@ static int kexec_get(reserve)(xen_kexec_
return 0;
}
-static int kexec_get(xen)(xen_kexec_range_t *range)
+static int kexec_get_xen(xen_kexec_range_t *range)
{
#ifdef CONFIG_X86_64
range->start = xenheap_phys_start;
@@ -179,7 +175,7 @@ static int kexec_get(xen)(xen_kexec_rang
return 0;
}
-static int kexec_get(cpu)(xen_kexec_range_t *range)
+static int kexec_get_cpu(xen_kexec_range_t *range)
{
int nr = range->nr;
int nr_bytes = 0;
@@ -223,33 +219,78 @@ static int kexec_get(cpu)(xen_kexec_rang
return 0;
}
-static int kexec_get(range)(XEN_GUEST_HANDLE(void) uarg)
+static int kexec_get_range_internal(xen_kexec_range_t *range)
{
- xen_kexec_range_t range;
int ret = -EINVAL;
- if ( unlikely(copy_from_guest(&range, uarg, 1)) )
- return -EFAULT;
-
- switch ( range.range )
+ switch ( range->range )
{
case KEXEC_RANGE_MA_CRASH:
- ret = kexec_get(reserve)(&range);
+ ret = kexec_get_reserve(range);
break;
case KEXEC_RANGE_MA_XEN:
- ret = kexec_get(xen)(&range);
+ ret = kexec_get_xen(range);
break;
case KEXEC_RANGE_MA_CPU:
- ret = kexec_get(cpu)(&range);
+ ret = kexec_get_cpu(range);
break;
}
+ return ret;
+}
+
+static int kexec_get_range(XEN_GUEST_HANDLE(void) uarg)
+{
+ xen_kexec_range_t range;
+ int ret = -EINVAL;
+
+ if ( unlikely(copy_from_guest(&range, uarg, 1)) )
+ return -EFAULT;
+
+ ret = kexec_get_range_internal(&range);
+
if ( ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)) )
return -EFAULT;
return ret;
}
+#else /* COMPAT */
+
+#ifdef CONFIG_COMPAT
+static int kexec_get_range_compat(XEN_GUEST_HANDLE(void) uarg)
+{
+ xen_kexec_range_t range;
+ compat_kexec_range_t compat_range;
+ int ret = -EINVAL;
+
+ if ( unlikely(copy_from_guest(&compat_range, uarg, 1)) )
+ return -EFAULT;
+
+ range.range = compat_range.range;
+ range.nr = compat_range.nr;
+ range.size = compat_range.size;
+ range.start = compat_range.start;
+
+ ret = kexec_get_range_internal(&range);
+
+ if ( ret == 0 ) {
+ range.range = compat_range.range;
+ range.nr = compat_range.nr;
+ range.size = compat_range.size;
+ range.start = compat_range.start;
+
+ if ( unlikely(copy_to_guest(uarg, &compat_range, 1)) )
+ return -EFAULT;
+ }
+
+ return ret;
+}
+#endif /* CONFIG_COMPAT */
+
+#endif /* COMPAT */
+
+
#ifndef COMPAT
static int kexec_load_get_bits(int type, int *base, int *bit)
@@ -375,7 +416,11 @@ ret_t do_kexec_op(unsigned long op, XEN_
switch ( op )
{
case KEXEC_CMD_kexec_get_range:
- ret = kexec_get(range)(uarg);
+#ifndef COMPAT
+ ret = kexec_get_range(uarg);
+#else
+ ret = kexec_get_range_compat(uarg);
+#endif
break;
case KEXEC_CMD_kexec_load:
case KEXEC_CMD_kexec_unload:
--
--
Horms
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|