ia64/xen-unstable

changeset 12451:7452d58e4a3b

[IA64] MCA support - Add sal emulation

Signed-off-by: Yutaka Ezaki <yutaka.ezaki@jp.fujitsu.com>
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
Signed-off-by: Kazuhiro Suzuki <kaz@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Sun Oct 29 09:27:16 2006 -0700 (2006-10-29)
parents 6384ff711405
children 5dd8306e9032
files xen/arch/ia64/xen/fw_emul.c
line diff
     1.1 --- a/xen/arch/ia64/xen/fw_emul.c	Sun Oct 29 09:27:15 2006 -0700
     1.2 +++ b/xen/arch/ia64/xen/fw_emul.c	Sun Oct 29 09:27:16 2006 -0700
     1.3 @@ -22,6 +22,7 @@
     1.4  #include <linux/efi.h>
     1.5  #include <asm/pal.h>
     1.6  #include <asm/sal.h>
     1.7 +#include <asm/xenmca.h>
     1.8  
     1.9  #include <public/sched.h>
    1.10  #include "hpsim_ssc.h"
    1.11 @@ -34,6 +35,93 @@
    1.12  
    1.13  extern unsigned long running_on_sim;
    1.14  
    1.15 +struct sal_mc_params {
    1.16 +	u64 param_type;
    1.17 +	u64 i_or_m;
    1.18 +	u64 i_or_m_val;
    1.19 +	u64 timeout;
    1.20 +	u64 rz_always;
    1.21 +} sal_mc_params[SAL_MC_PARAM_CPE_INT + 1];
    1.22 +
    1.23 +struct sal_vectors {
    1.24 +	u64 vector_type;
    1.25 +	u64 handler_addr1;
    1.26 +	u64 gp1;
    1.27 +	u64 handler_len1;
    1.28 +	u64 handler_addr2;
    1.29 +	u64 gp2;
    1.30 +	u64 handler_len2;
    1.31 +} sal_vectors[SAL_VECTOR_OS_BOOT_RENDEZ + 1];
    1.32 +
    1.33 +struct smp_call_args_t {
    1.34 +	u64 type;
    1.35 +	u64 ret;
    1.36 +	u64 target;
    1.37 +	struct domain *domain;
    1.38 +	int corrected;
    1.39 +	int status;
    1.40 +	void *data;
    1.41 +}; 
    1.42 +
    1.43 +extern sal_log_record_header_t	*sal_record;
    1.44 +DEFINE_SPINLOCK(sal_record_lock);
    1.45 +
    1.46 +extern spinlock_t sal_queue_lock;
    1.47 +
    1.48 +#define IA64_SAL_NO_INFORMATION_AVAILABLE	-5
    1.49 +
    1.50 +#if defined(IA64_SAL_DEBUG_INFO)
    1.51 +static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
    1.52 +
    1.53 +# define IA64_SAL_DEBUG(fmt...)	printk("sal_emulator: " fmt)
    1.54 +#else
    1.55 +# define IA64_SAL_DEBUG(fmt...)
    1.56 +#endif
    1.57 +
    1.58 +void get_state_info_on(void *data) {
    1.59 +	struct smp_call_args_t *arg = data;
    1.60 +	int flags;
    1.61 +
    1.62 +	spin_lock_irqsave(&sal_record_lock, flags);
    1.63 +	memset(sal_record, 0, ia64_sal_get_state_info_size(arg->type));
    1.64 +	arg->ret = ia64_sal_get_state_info(arg->type, (u64 *)sal_record);
    1.65 +	IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) on CPU#%d returns %ld.\n",
    1.66 +	               rec_name[arg->type], smp_processor_id(), arg->ret);
    1.67 +	if (arg->corrected) {
    1.68 +		sal_record->severity = sal_log_severity_corrected;
    1.69 +		IA64_SAL_DEBUG("%s: IA64_SAL_CLEAR_STATE_INFO(SAL_INFO_TYPE_MCA)"
    1.70 +		               " force\n", __FUNCTION__);
    1.71 +	}
    1.72 +	if (arg->ret > 0) {
    1.73 +	  	/*
    1.74 +		 * Save current->domain and set to local(caller) domain for
    1.75 +		 * xencomm_paddr_to_maddr() which calculates maddr from
    1.76 +		 * paddr using mpa value of current->domain.
    1.77 +		 */
    1.78 +		struct domain *save;
    1.79 +		save = current->domain;
    1.80 +		current->domain = arg->domain;
    1.81 +		if (xencomm_copy_to_guest((void*)arg->target,
    1.82 +		                          sal_record, arg->ret, 0)) {
    1.83 +			printk("SAL_GET_STATE_INFO can't copy to user!!!!\n");
    1.84 +			arg->status = IA64_SAL_NO_INFORMATION_AVAILABLE;
    1.85 +			arg->ret = 0;
    1.86 +		}
    1.87 +	  	/* Restore current->domain to saved value. */
    1.88 +		current->domain = save;
    1.89 +	}
    1.90 +	spin_unlock_irqrestore(&sal_record_lock, flags);
    1.91 +}
    1.92 +
    1.93 +void clear_state_info_on(void *data) {
    1.94 +	struct smp_call_args_t *arg = data;
    1.95 +
    1.96 +	arg->ret = ia64_sal_clear_state_info(arg->type);
    1.97 +	IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) on CPU#%d returns %ld.\n",
    1.98 +	               rec_name[arg->type], smp_processor_id(), arg->ret);
    1.99 +
   1.100 +}
   1.101 +  
   1.102  struct sal_ret_values
   1.103  sal_emulator (long index, unsigned long in1, unsigned long in2,
   1.104  	      unsigned long in3, unsigned long in4, unsigned long in5,
   1.105 @@ -104,27 +192,157 @@ sal_emulator (long index, unsigned long 
   1.106  			}
   1.107   		}
   1.108   		else
   1.109 - 			printk("*** CALLED SAL_SET_VECTORS %lu.  IGNORED...\n",
   1.110 - 			       in1);
   1.111 +		{
   1.112 +			if (in1 > sizeof(sal_vectors)/sizeof(sal_vectors[0])-1)
   1.113 +				BUG();
   1.114 +			sal_vectors[in1].vector_type	= in1;
   1.115 +			sal_vectors[in1].handler_addr1	= in2;
   1.116 +			sal_vectors[in1].gp1		= in3;
   1.117 +			sal_vectors[in1].handler_len1	= in4;
   1.118 +			sal_vectors[in1].handler_addr2	= in5;
   1.119 +			sal_vectors[in1].gp2		= in6;
   1.120 +			sal_vectors[in1].handler_len2	= in7;
   1.121 +		}
   1.122  		break;
   1.123  	    case SAL_GET_STATE_INFO:
   1.124 -		/* No more info.  */
   1.125 -		status = -5;
   1.126 -		r9 = 0;
   1.127 +		{
   1.128 +			sal_queue_entry_t *e;
   1.129 +			unsigned long flags;
   1.130 +			struct smp_call_args_t arg;
   1.131 +
   1.132 +			spin_lock_irqsave(&sal_queue_lock, flags);
   1.133 +			if (list_empty(&sal_queue[in1])) {
   1.134 +				sal_log_record_header_t header;
   1.135 +				XEN_GUEST_HANDLE(void) handle =
   1.136 +					*(XEN_GUEST_HANDLE(void)*)&in3;
   1.137 +
   1.138 +				IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) "
   1.139 +				               "no sal_queue entry found.\n",
   1.140 +				               rec_name[in1]);
   1.141 +				memset(&header, 0, sizeof(header));
   1.142 +
   1.143 +				if (copy_to_guest(handle, &header, 1)) {
   1.144 +					printk("sal_emulator: "
   1.145 +					       "SAL_GET_STATE_INFO can't copy "
   1.146 +					       "empty header to user: 0x%lx\n",
   1.147 +					       in3);
   1.148 +				}
   1.149 +				status = IA64_SAL_NO_INFORMATION_AVAILABLE;
   1.150 +				r9 = 0;
   1.151 +				spin_unlock_irqrestore(&sal_queue_lock, flags);
   1.152 +				break;
   1.153 +			}
   1.154 +			e = list_entry(sal_queue[in1].next,
   1.155 +			               sal_queue_entry_t, list);
   1.156 +			spin_unlock_irqrestore(&sal_queue_lock, flags);
   1.157 +
   1.158 +			IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s <= %s) "
   1.159 +			               "on CPU#%d.\n",
   1.160 +			               rec_name[e->sal_info_type],
   1.161 +			               rec_name[in1], e->cpuid);
   1.162 +
   1.163 +			arg.type = e->sal_info_type;
   1.164 +			arg.target = in3;
   1.165 +			arg.corrected = !!((in1 != e->sal_info_type) && 
   1.166 +			                (e->sal_info_type == SAL_INFO_TYPE_MCA));
   1.167 +			arg.domain = current->domain;
   1.168 +			arg.status = 0;
   1.169 +
   1.170 +			if (e->cpuid == smp_processor_id()) {
   1.171 +				IA64_SAL_DEBUG("SAL_GET_STATE_INFO: local\n");
   1.172 +				get_state_info_on(&arg);
   1.173 +			} else {
   1.174 +				int ret;
   1.175 +				IA64_SAL_DEBUG("SAL_GET_STATE_INFO: remote\n");
   1.176 +				ret = smp_call_function_single(e->cpuid,
   1.177 +				                               get_state_info_on,
   1.178 +				                               &arg, 0, 1);
   1.179 +				if (ret < 0) {
   1.180 +					printk("SAL_GET_STATE_INFO "
   1.181 +					       "smp_call_function_single error:"
   1.182 +					       " %d\n", ret);
   1.183 +					arg.ret = 0;
   1.184 +					arg.status =
   1.185 +					     IA64_SAL_NO_INFORMATION_AVAILABLE;
   1.186 +				}
   1.187 +			}
   1.188 +			r9 = arg.ret;
   1.189 +			status = arg.status;
   1.190 +			if (r9 == 0) {
   1.191 +				spin_lock_irqsave(&sal_queue_lock, flags);
   1.192 +				list_del(&e->list);
   1.193 +				spin_unlock_irqrestore(&sal_queue_lock, flags);
   1.194 +				xfree(e);
   1.195 +			}
   1.196 +		}
   1.197  		break;
   1.198  	    case SAL_GET_STATE_INFO_SIZE:
   1.199 -		/* Return a dummy size.  */
   1.200 -		status = 0;
   1.201 -		r9 = 128;
   1.202 +		r9 = ia64_sal_get_state_info_size(in1);
   1.203  		break;
   1.204  	    case SAL_CLEAR_STATE_INFO:
   1.205 -		/* Noop.  */
   1.206 +		{
   1.207 +			sal_queue_entry_t *e;
   1.208 +			unsigned long flags;
   1.209 +			struct smp_call_args_t arg;
   1.210 +
   1.211 +			spin_lock_irqsave(&sal_queue_lock, flags);
   1.212 +			if (list_empty(&sal_queue[in1])) {
   1.213 +				IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) "
   1.214 +				               "no sal_queue entry found.\n",
   1.215 +				               rec_name[in1]);
   1.216 +				status = IA64_SAL_NO_INFORMATION_AVAILABLE;
   1.217 +				r9 = 0;
   1.218 +				spin_unlock_irqrestore(&sal_queue_lock, flags);
   1.219 +				break;
   1.220 +			}
   1.221 +			e = list_entry(sal_queue[in1].next,
   1.222 +			               sal_queue_entry_t, list);
   1.223 +
   1.224 +			list_del(&e->list);
   1.225 +			spin_unlock_irqrestore(&sal_queue_lock, flags);
   1.226 +
   1.227 +			IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s <= %s) "
   1.228 +			               "on CPU#%d.\n",
   1.229 +			               rec_name[e->sal_info_type],
   1.230 +			               rec_name[in1], e->cpuid);
   1.231 +			
   1.232 +
   1.233 +			arg.type = e->sal_info_type;
   1.234 +			arg.status = 0;
   1.235 +			if (e->cpuid == smp_processor_id()) {
   1.236 +				IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: local\n");
   1.237 +				clear_state_info_on(&arg);
   1.238 +			} else {
   1.239 +				int ret;
   1.240 +				IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: remote\n");
   1.241 +				ret = smp_call_function_single(e->cpuid,
   1.242 +					clear_state_info_on, &arg, 0, 1);
   1.243 +				if (ret < 0) {
   1.244 +					printk("sal_emulator: "
   1.245 +					       "SAL_CLEAR_STATE_INFO "
   1.246 +					       "smp_call_function_single error:"
   1.247 +					       " %d\n", ret);
   1.248 +					arg.ret = 0;
   1.249 +					arg.status =
   1.250 +					     IA64_SAL_NO_INFORMATION_AVAILABLE;
   1.251 +				}
   1.252 +			}
   1.253 +			r9 = arg.ret;
   1.254 +			status = arg.status;
   1.255 +			xfree(e);
   1.256 +		}
   1.257  		break;
   1.258  	    case SAL_MC_RENDEZ:
   1.259  		printk("*** CALLED SAL_MC_RENDEZ.  IGNORED...\n");
   1.260  		break;
   1.261  	    case SAL_MC_SET_PARAMS:
   1.262 -		printk("*** CALLED SAL_MC_SET_PARAMS.  IGNORED...\n");
   1.263 +		if (in1 > sizeof(sal_mc_params)/sizeof(sal_mc_params[0]))
   1.264 +			BUG();
   1.265 +		sal_mc_params[in1].param_type	= in1;
   1.266 +		sal_mc_params[in1].i_or_m	= in2;
   1.267 +		sal_mc_params[in1].i_or_m_val	= in3;
   1.268 +		sal_mc_params[in1].timeout	= in4;
   1.269 +		sal_mc_params[in1].rz_always	= in5;
   1.270  		break;
   1.271  	    case SAL_CACHE_FLUSH:
   1.272  		if (1) {