# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1204195547 0
# Node ID 90ae3dfdd3cc02aca07f5b8b53b4266e8fc48f95
# Parent f8624b023d67820a9ee92f3cf149ffc2f808311a
kexec: limit scope of the use of compat_kexec_range_t
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.
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
xen/common/compat/kexec.c | 5 --
xen/common/kexec.c | 87 ++++++++++++++++++++++++++++++++++------------
2 files changed, 66 insertions(+), 26 deletions(-)
diff -r f8624b023d67 -r 90ae3dfdd3cc xen/common/compat/kexec.c
--- a/xen/common/compat/kexec.c Thu Feb 28 10:31:45 2008 +0000
+++ b/xen/common/compat/kexec.c Thu Feb 28 10:45:47 2008 +0000
@@ -8,11 +8,6 @@
#define ret_t int
#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
diff -r f8624b023d67 -r 90ae3dfdd3cc xen/common/kexec.c
--- a/xen/common/kexec.c Thu Feb 28 10:31:45 2008 +0000
+++ b/xen/common/kexec.c Thu Feb 28 10:45:47 2008 +0000
@@ -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,7 +219,27 @@ 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)
+{
+ int ret = -EINVAL;
+
+ switch ( range->range )
+ {
+ case KEXEC_RANGE_MA_CRASH:
+ ret = kexec_get_reserve(range);
+ break;
+ case KEXEC_RANGE_MA_XEN:
+ ret = kexec_get_xen(range);
+ break;
+ case KEXEC_RANGE_MA_CPU:
+ 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;
@@ -231,24 +247,49 @@ static int kexec_get(range)(XEN_GUEST_HA
if ( unlikely(copy_from_guest(&range, uarg, 1)) )
return -EFAULT;
- switch ( range.range )
- {
- case KEXEC_RANGE_MA_CRASH:
- ret = kexec_get(reserve)(&range);
- break;
- case KEXEC_RANGE_MA_XEN:
- ret = kexec_get(xen)(&range);
- break;
- case KEXEC_RANGE_MA_CPU:
- ret = kexec_get(cpu)(&range);
- break;
- }
+ 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
@@ -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:
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|