ia64/xen-unstable

changeset 19466:37f67d8224b7

x86 mce: fix c/s 17968 for 32-on-64

32-on-64 aspects were not properly considered. Add respective
checking, and adjust structure layouts for the cases where the
checking pointed out issues.

Also,
- fix a potential memory corruption issue (do_mca() could write beyond
log_cpus' end if the guest specified less than the number of online
CPUs
- there is no reason to make the (not even properly prefixed)
definitions in xen/public/arch-x86/xen-mca.h globally visible by
including the file from xen/public/arch-x86/xen.h.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 31 13:11:56 2009 +0100 (2009-03-31)
parents f2cf89a4e762
children 28a4dacea7ab
files xen/arch/x86/cpu/mcheck/mce.c xen/arch/x86/cpu/mcheck/x86_mca.h xen/include/public/arch-x86/xen-mca.h xen/include/public/arch-x86/xen.h xen/include/xlat.lst xen/tools/get-fields.sh
line diff
     1.1 --- a/xen/arch/x86/cpu/mcheck/mce.c	Tue Mar 31 12:06:57 2009 +0100
     1.2 +++ b/xen/arch/x86/cpu/mcheck/mce.c	Tue Mar 31 13:11:56 2009 +0100
     1.3 @@ -984,14 +984,76 @@ static void x86_mc_mceinject(void *data)
     1.4  #error BITS_PER_LONG definition absent
     1.5  #endif
     1.6  
     1.7 +#ifdef CONFIG_COMPAT
     1.8 +# include <compat/arch-x86/xen-mca.h>
     1.9 +
    1.10 +# define xen_mcinfo_msr              mcinfo_msr
    1.11 +CHECK_mcinfo_msr;
    1.12 +# undef xen_mcinfo_msr
    1.13 +# undef CHECK_mcinfo_msr
    1.14 +# define CHECK_mcinfo_msr            struct mcinfo_msr
    1.15 +
    1.16 +# define xen_mcinfo_common           mcinfo_common
    1.17 +CHECK_mcinfo_common;
    1.18 +# undef xen_mcinfo_common
    1.19 +# undef CHECK_mcinfo_common
    1.20 +# define CHECK_mcinfo_common         struct mcinfo_common
    1.21 +
    1.22 +CHECK_FIELD_(struct, mc_fetch, flags);
    1.23 +CHECK_FIELD_(struct, mc_fetch, fetch_id);
    1.24 +# define CHECK_compat_mc_fetch       struct mc_fetch
    1.25 +
    1.26 +CHECK_FIELD_(struct, mc_physcpuinfo, ncpus);
    1.27 +# define CHECK_compat_mc_physcpuinfo struct mc_physcpuinfo
    1.28 +
    1.29 +CHECK_mc;
    1.30 +# undef CHECK_compat_mc_fetch
    1.31 +# undef CHECK_compat_mc_physcpuinfo
    1.32 +
    1.33 +# define xen_mc_info                 mc_info
    1.34 +CHECK_mc_info;
    1.35 +# undef xen_mc_info
    1.36 +
    1.37 +# define xen_mcinfo_global           mcinfo_global
    1.38 +CHECK_mcinfo_global;
    1.39 +# undef xen_mcinfo_global
    1.40 +
    1.41 +# define xen_mcinfo_bank             mcinfo_bank
    1.42 +CHECK_mcinfo_bank;
    1.43 +# undef xen_mcinfo_bank
    1.44 +
    1.45 +# define xen_mcinfo_extended         mcinfo_extended
    1.46 +CHECK_mcinfo_extended;
    1.47 +# undef xen_mcinfo_extended
    1.48 +
    1.49 +# define xen_mcinfo_recovery         mcinfo_recovery
    1.50 +# define xen_cpu_offline_action      cpu_offline_action
    1.51 +# define xen_page_offline_action     page_offline_action
    1.52 +CHECK_mcinfo_recovery;
    1.53 +# undef xen_cpu_offline_action
    1.54 +# undef xen_page_offline_action
    1.55 +# undef xen_mcinfo_recovery
    1.56 +#else
    1.57 +# define compat_mc_fetch xen_mc_fetch
    1.58 +# define compat_mc_physcpuinfo xen_mc_physcpuinfo
    1.59 +# define compat_handle_is_null guest_handle_is_null
    1.60 +# define copy_to_compat copy_to_guest
    1.61 +#endif
    1.62 +
    1.63  /* Machine Check Architecture Hypercall */
    1.64  long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u_xen_mc)
    1.65  {
    1.66  	long ret = 0;
    1.67  	struct xen_mc curop, *op = &curop;
    1.68  	struct vcpu *v = current;
    1.69 -	struct xen_mc_fetch *mc_fetch;
    1.70 -	struct xen_mc_physcpuinfo *mc_physcpuinfo;
    1.71 +	union {
    1.72 +		struct xen_mc_fetch *nat;
    1.73 +		struct compat_mc_fetch *cmp;
    1.74 +	} mc_fetch;
    1.75 +	union {
    1.76 +		struct xen_mc_physcpuinfo *nat;
    1.77 +		struct compat_mc_physcpuinfo *cmp;
    1.78 +	} mc_physcpuinfo;
    1.79  	uint32_t flags, cmdflags;
    1.80  	int nlcpu;
    1.81  	xen_mc_logical_cpu_t *log_cpus = NULL;
    1.82 @@ -1009,8 +1071,8 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
    1.83  
    1.84  	switch (op->cmd) {
    1.85  	case XEN_MC_fetch:
    1.86 -		mc_fetch = &op->u.mc_fetch;
    1.87 -		cmdflags = mc_fetch->flags;
    1.88 +		mc_fetch.nat = &op->u.mc_fetch;
    1.89 +		cmdflags = mc_fetch.nat->flags;
    1.90  
    1.91  		/* This hypercall is for Dom0 only */
    1.92  		if (!IS_PRIV(v->domain) )
    1.93 @@ -1032,30 +1094,35 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
    1.94  		flags = XEN_MC_OK;
    1.95  
    1.96  		if (cmdflags & XEN_MC_ACK) {
    1.97 -			mctelem_cookie_t cookie = ID2COOKIE(mc_fetch->fetch_id);
    1.98 +			mctelem_cookie_t cookie = ID2COOKIE(mc_fetch.nat->fetch_id);
    1.99  			mctelem_ack(which, cookie);
   1.100  		} else {
   1.101 -			if (guest_handle_is_null(mc_fetch->data))
   1.102 +			if (!is_pv_32on64_vcpu(v)
   1.103 +			    ? guest_handle_is_null(mc_fetch.nat->data)
   1.104 +			    : compat_handle_is_null(mc_fetch.cmp->data))
   1.105  				return x86_mcerr("do_mca fetch: guest buffer "
   1.106  				    "invalid", -EINVAL);
   1.107  
   1.108  			if ((mctc = mctelem_consume_oldest_begin(which))) {
   1.109  				struct mc_info *mcip = mctelem_dataptr(mctc);
   1.110 -				if (copy_to_guest(mc_fetch->data, mcip, 1)) {
   1.111 +				if (!is_pv_32on64_vcpu(v)
   1.112 +				    ? copy_to_guest(mc_fetch.nat->data, mcip, 1)
   1.113 +				    : copy_to_compat(mc_fetch.cmp->data,
   1.114 +						     mcip, 1)) {
   1.115  					ret = -EFAULT;
   1.116  					flags |= XEN_MC_FETCHFAILED;
   1.117 -					mc_fetch->fetch_id = 0;
   1.118 +					mc_fetch.nat->fetch_id = 0;
   1.119  				} else {
   1.120 -					mc_fetch->fetch_id = COOKIE2ID(mctc);
   1.121 +					mc_fetch.nat->fetch_id = COOKIE2ID(mctc);
   1.122  				}
   1.123  				mctelem_consume_oldest_end(mctc);
   1.124  			} else {
   1.125  				/* There is no data */
   1.126  				flags |= XEN_MC_NODATA;
   1.127 -				mc_fetch->fetch_id = 0;
   1.128 +				mc_fetch.nat->fetch_id = 0;
   1.129  			}
   1.130  
   1.131 -			mc_fetch->flags = flags;
   1.132 +			mc_fetch.nat->flags = flags;
   1.133  			if (copy_to_guest(u_xen_mc, op, 1) != 0)
   1.134  				ret = -EFAULT;
   1.135  		}
   1.136 @@ -1069,14 +1136,16 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
   1.137  		if ( !IS_PRIV(v->domain) )
   1.138  			return x86_mcerr("do_mca cpuinfo", -EPERM);
   1.139  
   1.140 -		mc_physcpuinfo = &op->u.mc_physcpuinfo;
   1.141 +		mc_physcpuinfo.nat = &op->u.mc_physcpuinfo;
   1.142  		nlcpu = num_online_cpus();
   1.143  
   1.144 -		if (!guest_handle_is_null(mc_physcpuinfo->info)) {
   1.145 -			if (mc_physcpuinfo->ncpus <= 0)
   1.146 +		if (!is_pv_32on64_vcpu(v)
   1.147 +		    ? !guest_handle_is_null(mc_physcpuinfo.nat->info)
   1.148 +		    : !compat_handle_is_null(mc_physcpuinfo.cmp->info)) {
   1.149 +			if (mc_physcpuinfo.nat->ncpus <= 0)
   1.150  				return x86_mcerr("do_mca cpuinfo: ncpus <= 0",
   1.151  				    -EINVAL);
   1.152 -			nlcpu = min(nlcpu, (int)mc_physcpuinfo->ncpus);
   1.153 +			nlcpu = min(nlcpu, (int)mc_physcpuinfo.nat->ncpus);
   1.154  			log_cpus = xmalloc_array(xen_mc_logical_cpu_t, nlcpu);
   1.155  			if (log_cpus == NULL)
   1.156  				return x86_mcerr("do_mca cpuinfo", -ENOMEM);
   1.157 @@ -1086,22 +1155,20 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u
   1.158  				xfree(log_cpus);
   1.159  				return x86_mcerr("do_mca cpuinfo", -EIO);
   1.160  			}
   1.161 -		}
   1.162 -
   1.163 -		mc_physcpuinfo->ncpus = nlcpu;
   1.164 -
   1.165 -		if (copy_to_guest(u_xen_mc, op, 1)) {
   1.166 -			if (log_cpus != NULL)
   1.167 -				xfree(log_cpus);
   1.168 -			return x86_mcerr("do_mca cpuinfo", -EFAULT);
   1.169 -		}
   1.170 -
   1.171 -		if (!guest_handle_is_null(mc_physcpuinfo->info)) {
   1.172 -			if (copy_to_guest(mc_physcpuinfo->info,
   1.173 -			    log_cpus, nlcpu))
   1.174 +			if (!is_pv_32on64_vcpu(v)
   1.175 +			    ? copy_to_guest(mc_physcpuinfo.nat->info,
   1.176 +					    log_cpus, nlcpu)
   1.177 +			    : copy_to_compat(mc_physcpuinfo.cmp->info,
   1.178 +					    log_cpus, nlcpu))
   1.179  				ret = -EFAULT;
   1.180  			xfree(log_cpus);
   1.181  		}
   1.182 +
   1.183 +		mc_physcpuinfo.nat->ncpus = nlcpu;
   1.184 +
   1.185 +		if (copy_to_guest(u_xen_mc, op, 1))
   1.186 +			return x86_mcerr("do_mca cpuinfo", -EFAULT);
   1.187 +
   1.188  		break;
   1.189  
   1.190  	case XEN_MC_msrinject:
     2.1 --- a/xen/arch/x86/cpu/mcheck/x86_mca.h	Tue Mar 31 12:06:57 2009 +0100
     2.2 +++ b/xen/arch/x86/cpu/mcheck/x86_mca.h	Tue Mar 31 13:11:56 2009 +0100
     2.3 @@ -18,9 +18,9 @@
     2.4   */
     2.5  
     2.6  #ifndef X86_MCA_H
     2.7 -
     2.8  #define X86_MCA_H
     2.9  
    2.10 +#include <public/arch-x86/xen-mca.h>
    2.11  
    2.12  /* The MCA/MCE MSRs should not be used anywhere else.
    2.13   * They are cpu family/model specific and are only for use
     3.1 --- a/xen/include/public/arch-x86/xen-mca.h	Tue Mar 31 12:06:57 2009 +0100
     3.2 +++ b/xen/include/public/arch-x86/xen-mca.h	Tue Mar 31 13:11:56 2009 +0100
     3.3 @@ -62,7 +62,7 @@
     3.4   * choose a different version number range that is numerically less
     3.5   * than that used in xen-unstable.
     3.6   */
     3.7 -#define XEN_MCA_INTERFACE_VERSION 0x01ecc002
     3.8 +#define XEN_MCA_INTERFACE_VERSION 0x01ecc003
     3.9  
    3.10  /* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */
    3.11  #define XEN_MC_NONURGENT  0x0001
    3.12 @@ -125,13 +125,13 @@ struct mcinfo_global {
    3.13  
    3.14      /* running domain at the time in error (most likely the impacted one) */
    3.15      uint16_t mc_domid;
    3.16 +    uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
    3.17      uint32_t mc_socketid; /* physical socket of the physical core */
    3.18      uint16_t mc_coreid; /* physical impacted core */
    3.19 -    uint32_t mc_apicid;
    3.20      uint16_t mc_core_threadid; /* core thread of physical core */
    3.21 -    uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
    3.22 +    uint32_t mc_apicid;
    3.23 +    uint32_t mc_flags;
    3.24      uint64_t mc_gstatus; /* global status */
    3.25 -    uint32_t mc_flags;
    3.26  };
    3.27  
    3.28  /* contains bank local x86 mc information */
    3.29 @@ -216,8 +216,9 @@ struct cpu_offline_action
    3.30  };
    3.31  
    3.32  #define MAX_UNION_SIZE 16
    3.33 -struct mc_recovery
    3.34 +struct mcinfo_recovery
    3.35  {
    3.36 +    struct mcinfo_common common;
    3.37      uint16_t mc_bank; /* bank nr */
    3.38      uint8_t action_flags;
    3.39      uint8_t action_types;
    3.40 @@ -228,12 +229,6 @@ struct mc_recovery
    3.41      } action_info;
    3.42  };
    3.43  
    3.44 -struct mcinfo_recovery
    3.45 -{
    3.46 -    struct mcinfo_common common;
    3.47 -    struct mc_recovery mc_action;
    3.48 -};
    3.49 -
    3.50  
    3.51  #define MCINFO_HYPERCALLSIZE	1024
    3.52  #define MCINFO_MAXSIZE		768
    3.53 @@ -241,8 +236,8 @@ struct mcinfo_recovery
    3.54  struct mc_info {
    3.55      /* Number of mcinfo_* entries in mi_data */
    3.56      uint32_t mi_nentries;
    3.57 -
    3.58 -    uint8_t mi_data[MCINFO_MAXSIZE - sizeof(uint32_t)];
    3.59 +    uint32_t _pad0;
    3.60 +    uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8];
    3.61  };
    3.62  typedef struct mc_info mc_info_t;
    3.63  DEFINE_XEN_GUEST_HANDLE(mc_info_t);
    3.64 @@ -258,7 +253,7 @@ DEFINE_XEN_GUEST_HANDLE(mc_info_t);
    3.65  #define MC_CAPS_VIA	5	/* cpuid level 0xc0000001 */
    3.66  #define MC_CAPS_AMD_ECX	6	/* cpuid level 0x80000001 (%ecx) */
    3.67  
    3.68 -typedef struct mcinfo_logical_cpu {
    3.69 +struct mcinfo_logical_cpu {
    3.70      uint32_t mc_cpunr;          
    3.71      uint32_t mc_chipid; 
    3.72      uint16_t mc_coreid;
    3.73 @@ -280,7 +275,8 @@ typedef struct mcinfo_logical_cpu {
    3.74      uint32_t mc_cache_alignment;
    3.75      int32_t mc_nmsrvals;
    3.76      struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
    3.77 -} xen_mc_logical_cpu_t;
    3.78 +};
    3.79 +typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t;
    3.80  DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_t);
    3.81  
    3.82  
    3.83 @@ -299,12 +295,12 @@ DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_c
    3.84   *    struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi);
    3.85   */
    3.86  #define x86_mcinfo_first(_mi)       \
    3.87 -    (struct mcinfo_common *)((_mi)->mi_data)
    3.88 +    ((struct mcinfo_common *)(_mi)->mi_data)
    3.89  /* Prototype:
    3.90   *    struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic);
    3.91   */
    3.92  #define x86_mcinfo_next(_mic)       \
    3.93 -    (struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size)
    3.94 +    ((struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size))
    3.95  
    3.96  /* Prototype:
    3.97   *    void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type);
    3.98 @@ -350,6 +346,7 @@ struct xen_mc_fetch {
    3.99                             XEN_MC_ACK if ack'ing an earlier fetch */
   3.100  			/* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED,
   3.101  			   XEN_MC_NODATA, XEN_MC_NOMATCH */
   3.102 +    uint32_t _pad0;
   3.103      uint64_t fetch_id;	/* OUT: id for ack, IN: id we are ack'ing */
   3.104  
   3.105      /* OUT variables. */
   3.106 @@ -382,7 +379,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydom
   3.107  struct xen_mc_physcpuinfo {
   3.108  	/* IN/OUT */
   3.109  	uint32_t ncpus;
   3.110 -	uint32_t pad0;
   3.111 +	uint32_t _pad0;
   3.112  	/* OUT */
   3.113  	XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info;
   3.114  };
   3.115 @@ -391,10 +388,10 @@ struct xen_mc_physcpuinfo {
   3.116  #define MC_MSRINJ_MAXMSRS       8
   3.117  struct xen_mc_msrinject {
   3.118         /* IN */
   3.119 -	unsigned int mcinj_cpunr;       /* target processor id */
   3.120 +	uint32_t mcinj_cpunr;           /* target processor id */
   3.121  	uint32_t mcinj_flags;           /* see MC_MSRINJ_F_* below */
   3.122  	uint32_t mcinj_count;           /* 0 .. count-1 in array are valid */
   3.123 -	uint32_t mcinj_pad0;
   3.124 +	uint32_t _pad0;
   3.125  	struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
   3.126  };
   3.127  
   3.128 @@ -406,18 +403,16 @@ struct xen_mc_mceinject {
   3.129  	unsigned int mceinj_cpunr;      /* target processor id */
   3.130  };
   3.131  
   3.132 -typedef union {
   3.133 -    struct xen_mc_fetch        mc_fetch;
   3.134 -    struct xen_mc_notifydomain mc_notifydomain;
   3.135 -    struct xen_mc_physcpuinfo  mc_physcpuinfo;
   3.136 -    struct xen_mc_msrinject    mc_msrinject;
   3.137 -    struct xen_mc_mceinject    mc_mceinject;
   3.138 -} xen_mc_arg_t;
   3.139 -
   3.140  struct xen_mc {
   3.141      uint32_t cmd;
   3.142      uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
   3.143 -    xen_mc_arg_t u;
   3.144 +    union {
   3.145 +        struct xen_mc_fetch        mc_fetch;
   3.146 +        struct xen_mc_notifydomain mc_notifydomain;
   3.147 +        struct xen_mc_physcpuinfo  mc_physcpuinfo;
   3.148 +        struct xen_mc_msrinject    mc_msrinject;
   3.149 +        struct xen_mc_mceinject    mc_mceinject;
   3.150 +    } u;
   3.151  };
   3.152  typedef struct xen_mc xen_mc_t;
   3.153  DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
     4.1 --- a/xen/include/public/arch-x86/xen.h	Tue Mar 31 12:06:57 2009 +0100
     4.2 +++ b/xen/include/public/arch-x86/xen.h	Tue Mar 31 13:11:56 2009 +0100
     4.3 @@ -76,10 +76,6 @@ typedef unsigned long xen_pfn_t;
     4.4  /* Maximum number of virtual CPUs in multi-processor guests. */
     4.5  #define MAX_VIRT_CPUS 32
     4.6  
     4.7 -
     4.8 -/* Machine check support */
     4.9 -#include "xen-mca.h"
    4.10 -
    4.11  #ifndef __ASSEMBLY__
    4.12  
    4.13  typedef unsigned long xen_ulong_t;
     5.1 --- a/xen/include/xlat.lst	Tue Mar 31 12:06:57 2009 +0100
     5.2 +++ b/xen/include/xlat.lst	Tue Mar 31 13:11:56 2009 +0100
     5.3 @@ -10,6 +10,22 @@
     5.4  !	cpu_user_regs			arch-x86/xen-@arch@.h
     5.5  !	trap_info			arch-x86/xen.h
     5.6  !	vcpu_guest_context		arch-x86/xen.h
     5.7 +?	cpu_offline_action		arch-x86/xen-mca.h
     5.8 +?	mc				arch-x86/xen-mca.h
     5.9 +?	mcinfo_bank			arch-x86/xen-mca.h
    5.10 +?	mcinfo_common			arch-x86/xen-mca.h
    5.11 +?	mcinfo_extended			arch-x86/xen-mca.h
    5.12 +?	mcinfo_global			arch-x86/xen-mca.h
    5.13 +?	mcinfo_logical_cpu		arch-x86/xen-mca.h
    5.14 +?	mcinfo_msr			arch-x86/xen-mca.h
    5.15 +?	mcinfo_recovery			arch-x86/xen-mca.h
    5.16 +!	mc_fetch			arch-x86/xen-mca.h
    5.17 +?	mc_info				arch-x86/xen-mca.h
    5.18 +?	mc_mceinject			arch-x86/xen-mca.h
    5.19 +?	mc_msrinject			arch-x86/xen-mca.h
    5.20 +?	mc_notifydomain			arch-x86/xen-mca.h
    5.21 +!	mc_physcpuinfo			arch-x86/xen-mca.h
    5.22 +?	page_offline_action		arch-x86/xen-mca.h
    5.23  ?	evtchn_alloc_unbound		event_channel.h
    5.24  ?	evtchn_bind_interdomain		event_channel.h
    5.25  ?	evtchn_bind_ipi			event_channel.h
     6.1 --- a/xen/tools/get-fields.sh	Tue Mar 31 12:06:57 2009 +0100
     6.2 +++ b/xen/tools/get-fields.sh	Tue Mar 31 13:11:56 2009 +0100
     6.3 @@ -328,7 +328,7 @@ check_field ()
     6.4  				struct|union)
     6.5  					;;
     6.6  				[a-zA-Z_]*)
     6.7 -					echo -n "    CHECK_$n"
     6.8 +					echo -n "    CHECK_${n#xen_}"
     6.9  					break
    6.10  					;;
    6.11  				*)