ia64/xen-unstable

changeset 17166:f476727b1683

kexec: Add explicit kexec_load_unload_compat()

Add an explicit kexec_load_unload_compat() using the same method
that was used to create kexec_range_compat()

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Mar 03 10:58:06 2008 +0000 (2008-03-03)
parents df31d8e294ff
children 750788fdd42f
files xen/common/compat/kexec.c xen/common/kexec.c
line diff
     1.1 --- a/xen/common/compat/kexec.c	Mon Mar 03 10:56:09 2008 +0000
     1.2 +++ b/xen/common/compat/kexec.c	Mon Mar 03 10:58:06 2008 +0000
     1.3 @@ -5,13 +5,6 @@
     1.4  #include <compat/kexec.h>
     1.5  
     1.6  #define COMPAT
     1.7 -#define ret_t int
     1.8 -
     1.9 -#define do_kexec_op compat_kexec_op
    1.10 -
    1.11 -#define kexec_load_unload compat_kexec_load_unload
    1.12 -#define xen_kexec_load    compat_kexec_load
    1.13 -#define xen_kexec_load_t  compat_kexec_load_t
    1.14  
    1.15  CHECK_kexec_exec;
    1.16  
     2.1 --- a/xen/common/kexec.c	Mon Mar 03 10:56:09 2008 +0000
     2.2 +++ b/xen/common/kexec.c	Mon Mar 03 10:58:06 2008 +0000
     2.3 @@ -29,8 +29,6 @@
     2.4  
     2.5  #ifndef COMPAT
     2.6  
     2.7 -typedef long ret_t;
     2.8 -
     2.9  static DEFINE_PER_CPU(void *, crash_notes);
    2.10  
    2.11  static Elf_Note *xen_crash_note;
    2.12 @@ -248,9 +246,9 @@ static int kexec_get_range(XEN_GUEST_HAN
    2.13      return ret;
    2.14  }
    2.15  
    2.16 -#ifdef CONFIG_COMPAT
    2.17  static int kexec_get_range_compat(XEN_GUEST_HANDLE(void) uarg)
    2.18  {
    2.19 +#ifdef CONFIG_COMPAT
    2.20      xen_kexec_range_t range;
    2.21      compat_kexec_range_t compat_range;
    2.22      int ret = -EINVAL;
    2.23 @@ -269,13 +267,10 @@ static int kexec_get_range_compat(XEN_GU
    2.24      }
    2.25  
    2.26      return ret;
    2.27 -}
    2.28 +#else /* CONFIG_COMPAT */
    2.29 +    return 0;
    2.30  #endif /* CONFIG_COMPAT */
    2.31 -
    2.32 -#endif /* COMPAT */
    2.33 -
    2.34 -
    2.35 -#ifndef COMPAT
    2.36 +}
    2.37  
    2.38  static int kexec_load_get_bits(int type, int *base, int *bit)
    2.39  {
    2.40 @@ -295,19 +290,13 @@ static int kexec_load_get_bits(int type,
    2.41      return 0;
    2.42  }
    2.43  
    2.44 -#endif
    2.45 -
    2.46 -static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
    2.47 +static int kexec_load_unload_internal(unsigned long op, xen_kexec_load_t *load)
    2.48  {
    2.49 -    xen_kexec_load_t load;
    2.50      xen_kexec_image_t *image;
    2.51      int base, bit, pos;
    2.52      int ret = 0;
    2.53  
    2.54 -    if ( unlikely(copy_from_guest(&load, uarg, 1)) )
    2.55 -        return -EFAULT;
    2.56 -
    2.57 -    if ( kexec_load_get_bits(load.type, &base, &bit) )
    2.58 +    if ( kexec_load_get_bits(load->type, &base, &bit) )
    2.59          return -EINVAL;
    2.60  
    2.61      pos = (test_bit(bit, &kexec_flags) != 0);
    2.62 @@ -319,13 +308,9 @@ static int kexec_load_unload(unsigned lo
    2.63  
    2.64          BUG_ON(test_bit((base + !pos), &kexec_flags)); /* must be free */
    2.65  
    2.66 -#ifndef COMPAT
    2.67 -        memcpy(image, &load.image, sizeof(*image));
    2.68 -#else
    2.69 -        XLAT_kexec_image(image, &load.image);
    2.70 -#endif
    2.71 +        memcpy(image, &load->image, sizeof(*image));
    2.72  
    2.73 -        if ( !(ret = machine_kexec_load(load.type, base + !pos, image)) )
    2.74 +        if ( !(ret = machine_kexec_load(load->type, base + !pos, image)) )
    2.75          {
    2.76              /* Set image present bit */
    2.77              set_bit((base + !pos), &kexec_flags);
    2.78 @@ -341,14 +326,48 @@ static int kexec_load_unload(unsigned lo
    2.79          if ( test_and_clear_bit((base + pos), &kexec_flags) )
    2.80          {
    2.81              image = &kexec_image[base + pos];
    2.82 -            machine_kexec_unload(load.type, base + pos, image);
    2.83 +            machine_kexec_unload(load->type, base + pos, image);
    2.84          }
    2.85      }
    2.86  
    2.87      return ret;
    2.88  }
    2.89  
    2.90 -#ifndef COMPAT
    2.91 +static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
    2.92 +{
    2.93 +    xen_kexec_load_t load;
    2.94 +
    2.95 +    if ( unlikely(copy_from_guest(&load, uarg, 1)) )
    2.96 +        return -EFAULT;
    2.97 +
    2.98 +    return kexec_load_unload_internal(op, &load);
    2.99 +}
   2.100 +
   2.101 +static int kexec_load_unload_compat(unsigned long op,
   2.102 +                                    XEN_GUEST_HANDLE(void) uarg)
   2.103 +{
   2.104 +#ifdef CONFIG_COMPAT
   2.105 +    compat_kexec_load_t compat_load;
   2.106 +    xen_kexec_load_t load;
   2.107 +
   2.108 +    if ( unlikely(copy_from_guest(&compat_load, uarg, 1)) )
   2.109 +        return -EFAULT;
   2.110 +
   2.111 +    /* This is a bit dodgy, load.image is inside load,
   2.112 +     * but XLAT_kexec_load (which is automatically generated)
   2.113 +     * doesn't translate load.image (correctly)
   2.114 +     * Just copy load->type, the only other member, manually instead.
   2.115 +     *
   2.116 +     * XLAT_kexec_load(&load, &compat_load);
   2.117 +     */
   2.118 +    load.type = compat_load.type;
   2.119 +    XLAT_kexec_image(&load.image, &compat_load.image);
   2.120 +
   2.121 +    return kexec_load_unload_internal(op, &load);
   2.122 +#else /* CONFIG_COMPAT */
   2.123 +    return 0;
   2.124 +#endif /* CONFIG_COMPAT */
   2.125 +}
   2.126  
   2.127  static int kexec_exec(XEN_GUEST_HANDLE(void) uarg)
   2.128  {
   2.129 @@ -383,9 +402,8 @@ static int kexec_exec(XEN_GUEST_HANDLE(v
   2.130      return -EINVAL; /* never reached */
   2.131  }
   2.132  
   2.133 -#endif
   2.134 -
   2.135 -ret_t do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
   2.136 +int do_kexec_op_internal(unsigned long op, XEN_GUEST_HANDLE(void) uarg,
   2.137 +                           int compat)
   2.138  {
   2.139      unsigned long flags;
   2.140      int ret = -EINVAL;
   2.141 @@ -400,18 +418,20 @@ ret_t do_kexec_op(unsigned long op, XEN_
   2.142      switch ( op )
   2.143      {
   2.144      case KEXEC_CMD_kexec_get_range:
   2.145 -#ifndef COMPAT
   2.146 -        ret = kexec_get_range(uarg);
   2.147 -#else
   2.148 -        ret = kexec_get_range_compat(uarg);
   2.149 -#endif
   2.150 +        if (compat)
   2.151 +                ret = kexec_get_range_compat(uarg);
   2.152 +        else
   2.153 +                ret = kexec_get_range(uarg);
   2.154          break;
   2.155      case KEXEC_CMD_kexec_load:
   2.156      case KEXEC_CMD_kexec_unload:
   2.157          spin_lock_irqsave(&kexec_lock, flags);
   2.158          if (!test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
   2.159          {
   2.160 -            ret = kexec_load_unload(op, uarg);
   2.161 +                if (compat)
   2.162 +                        ret = kexec_load_unload_compat(op, uarg);
   2.163 +                else
   2.164 +                        ret = kexec_load_unload(op, uarg);
   2.165          }
   2.166          spin_unlock_irqrestore(&kexec_lock, flags);
   2.167          break;
   2.168 @@ -423,6 +443,20 @@ ret_t do_kexec_op(unsigned long op, XEN_
   2.169      return ret;
   2.170  }
   2.171  
   2.172 +long do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
   2.173 +{
   2.174 +    return do_kexec_op_internal(op, uarg, 0);
   2.175 +}
   2.176 +
   2.177 +#ifdef CONFIG_COMPAT
   2.178 +int compat_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
   2.179 +{
   2.180 +    return do_kexec_op_internal(op, uarg, 1);
   2.181 +}
   2.182 +#endif
   2.183 +
   2.184 +#endif /* COMPAT */
   2.185 +
   2.186  #if defined(CONFIG_COMPAT) && !defined(COMPAT)
   2.187  #include "compat/kexec.c"
   2.188  #endif