[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] MCA support - Add sal emulation



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 7452d58e4a3be6a348a3e06717af7cffb3140a7a
# Parent  6384ff71140557d9c1eef684a85b47e9fcdea0ad
[IA64] MCA support - Add sal emulation

Signed-off-by: Yutaka Ezaki <yutaka.ezaki@xxxxxxxxxxxxxx>
Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
Signed-off-by: Kazuhiro Suzuki <kaz@xxxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/fw_emul.c |  238 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 228 insertions(+), 10 deletions(-)

diff -r 6384ff711405 -r 7452d58e4a3b xen/arch/ia64/xen/fw_emul.c
--- a/xen/arch/ia64/xen/fw_emul.c       Sun Oct 29 09:27:15 2006 -0700
+++ b/xen/arch/ia64/xen/fw_emul.c       Sun Oct 29 09:27:16 2006 -0700
@@ -22,6 +22,7 @@
 #include <linux/efi.h>
 #include <asm/pal.h>
 #include <asm/sal.h>
+#include <asm/xenmca.h>
 
 #include <public/sched.h>
 #include "hpsim_ssc.h"
@@ -34,6 +35,93 @@
 
 extern unsigned long running_on_sim;
 
+struct sal_mc_params {
+       u64 param_type;
+       u64 i_or_m;
+       u64 i_or_m_val;
+       u64 timeout;
+       u64 rz_always;
+} sal_mc_params[SAL_MC_PARAM_CPE_INT + 1];
+
+struct sal_vectors {
+       u64 vector_type;
+       u64 handler_addr1;
+       u64 gp1;
+       u64 handler_len1;
+       u64 handler_addr2;
+       u64 gp2;
+       u64 handler_len2;
+} sal_vectors[SAL_VECTOR_OS_BOOT_RENDEZ + 1];
+
+struct smp_call_args_t {
+       u64 type;
+       u64 ret;
+       u64 target;
+       struct domain *domain;
+       int corrected;
+       int status;
+       void *data;
+}; 
+
+extern sal_log_record_header_t *sal_record;
+DEFINE_SPINLOCK(sal_record_lock);
+
+extern spinlock_t sal_queue_lock;
+
+#define IA64_SAL_NO_INFORMATION_AVAILABLE      -5
+
+#if defined(IA64_SAL_DEBUG_INFO)
+static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
+
+# define IA64_SAL_DEBUG(fmt...)        printk("sal_emulator: " fmt)
+#else
+# define IA64_SAL_DEBUG(fmt...)
+#endif
+
+void get_state_info_on(void *data) {
+       struct smp_call_args_t *arg = data;
+       int flags;
+
+       spin_lock_irqsave(&sal_record_lock, flags);
+       memset(sal_record, 0, ia64_sal_get_state_info_size(arg->type));
+       arg->ret = ia64_sal_get_state_info(arg->type, (u64 *)sal_record);
+       IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) on CPU#%d returns %ld.\n",
+                      rec_name[arg->type], smp_processor_id(), arg->ret);
+       if (arg->corrected) {
+               sal_record->severity = sal_log_severity_corrected;
+               IA64_SAL_DEBUG("%s: 
IA64_SAL_CLEAR_STATE_INFO(SAL_INFO_TYPE_MCA)"
+                              " force\n", __FUNCTION__);
+       }
+       if (arg->ret > 0) {
+               /*
+                * Save current->domain and set to local(caller) domain for
+                * xencomm_paddr_to_maddr() which calculates maddr from
+                * paddr using mpa value of current->domain.
+                */
+               struct domain *save;
+               save = current->domain;
+               current->domain = arg->domain;
+               if (xencomm_copy_to_guest((void*)arg->target,
+                                         sal_record, arg->ret, 0)) {
+                       printk("SAL_GET_STATE_INFO can't copy to user!!!!\n");
+                       arg->status = IA64_SAL_NO_INFORMATION_AVAILABLE;
+                       arg->ret = 0;
+               }
+               /* Restore current->domain to saved value. */
+               current->domain = save;
+       }
+       spin_unlock_irqrestore(&sal_record_lock, flags);
+}
+
+void clear_state_info_on(void *data) {
+       struct smp_call_args_t *arg = data;
+
+       arg->ret = ia64_sal_clear_state_info(arg->type);
+       IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) on CPU#%d returns %ld.\n",
+                      rec_name[arg->type], smp_processor_id(), arg->ret);
+
+}
+  
 struct sal_ret_values
 sal_emulator (long index, unsigned long in1, unsigned long in2,
              unsigned long in3, unsigned long in4, unsigned long in5,
@@ -104,27 +192,157 @@ sal_emulator (long index, unsigned long 
                        }
                }
                else
-                       printk("*** CALLED SAL_SET_VECTORS %lu.  IGNORED...\n",
-                              in1);
+               {
+                       if (in1 > sizeof(sal_vectors)/sizeof(sal_vectors[0])-1)
+                               BUG();
+                       sal_vectors[in1].vector_type    = in1;
+                       sal_vectors[in1].handler_addr1  = in2;
+                       sal_vectors[in1].gp1            = in3;
+                       sal_vectors[in1].handler_len1   = in4;
+                       sal_vectors[in1].handler_addr2  = in5;
+                       sal_vectors[in1].gp2            = in6;
+                       sal_vectors[in1].handler_len2   = in7;
+               }
                break;
            case SAL_GET_STATE_INFO:
-               /* No more info.  */
-               status = -5;
-               r9 = 0;
+               {
+                       sal_queue_entry_t *e;
+                       unsigned long flags;
+                       struct smp_call_args_t arg;
+
+                       spin_lock_irqsave(&sal_queue_lock, flags);
+                       if (list_empty(&sal_queue[in1])) {
+                               sal_log_record_header_t header;
+                               XEN_GUEST_HANDLE(void) handle =
+                                       *(XEN_GUEST_HANDLE(void)*)&in3;
+
+                               IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) "
+                                              "no sal_queue entry found.\n",
+                                              rec_name[in1]);
+                               memset(&header, 0, sizeof(header));
+
+                               if (copy_to_guest(handle, &header, 1)) {
+                                       printk("sal_emulator: "
+                                              "SAL_GET_STATE_INFO can't copy "
+                                              "empty header to user: 0x%lx\n",
+                                              in3);
+                               }
+                               status = IA64_SAL_NO_INFORMATION_AVAILABLE;
+                               r9 = 0;
+                               spin_unlock_irqrestore(&sal_queue_lock, flags);
+                               break;
+                       }
+                       e = list_entry(sal_queue[in1].next,
+                                      sal_queue_entry_t, list);
+                       spin_unlock_irqrestore(&sal_queue_lock, flags);
+
+                       IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s <= %s) "
+                                      "on CPU#%d.\n",
+                                      rec_name[e->sal_info_type],
+                                      rec_name[in1], e->cpuid);
+
+                       arg.type = e->sal_info_type;
+                       arg.target = in3;
+                       arg.corrected = !!((in1 != e->sal_info_type) && 
+                                       (e->sal_info_type == 
SAL_INFO_TYPE_MCA));
+                       arg.domain = current->domain;
+                       arg.status = 0;
+
+                       if (e->cpuid == smp_processor_id()) {
+                               IA64_SAL_DEBUG("SAL_GET_STATE_INFO: local\n");
+                               get_state_info_on(&arg);
+                       } else {
+                               int ret;
+                               IA64_SAL_DEBUG("SAL_GET_STATE_INFO: remote\n");
+                               ret = smp_call_function_single(e->cpuid,
+                                                              
get_state_info_on,
+                                                              &arg, 0, 1);
+                               if (ret < 0) {
+                                       printk("SAL_GET_STATE_INFO "
+                                              "smp_call_function_single error:"
+                                              " %d\n", ret);
+                                       arg.ret = 0;
+                                       arg.status =
+                                            IA64_SAL_NO_INFORMATION_AVAILABLE;
+                               }
+                       }
+                       r9 = arg.ret;
+                       status = arg.status;
+                       if (r9 == 0) {
+                               spin_lock_irqsave(&sal_queue_lock, flags);
+                               list_del(&e->list);
+                               spin_unlock_irqrestore(&sal_queue_lock, flags);
+                               xfree(e);
+                       }
+               }
                break;
            case SAL_GET_STATE_INFO_SIZE:
-               /* Return a dummy size.  */
-               status = 0;
-               r9 = 128;
+               r9 = ia64_sal_get_state_info_size(in1);
                break;
            case SAL_CLEAR_STATE_INFO:
-               /* Noop.  */
+               {
+                       sal_queue_entry_t *e;
+                       unsigned long flags;
+                       struct smp_call_args_t arg;
+
+                       spin_lock_irqsave(&sal_queue_lock, flags);
+                       if (list_empty(&sal_queue[in1])) {
+                               IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) "
+                                              "no sal_queue entry found.\n",
+                                              rec_name[in1]);
+                               status = IA64_SAL_NO_INFORMATION_AVAILABLE;
+                               r9 = 0;
+                               spin_unlock_irqrestore(&sal_queue_lock, flags);
+                               break;
+                       }
+                       e = list_entry(sal_queue[in1].next,
+                                      sal_queue_entry_t, list);
+
+                       list_del(&e->list);
+                       spin_unlock_irqrestore(&sal_queue_lock, flags);
+
+                       IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s <= %s) "
+                                      "on CPU#%d.\n",
+                                      rec_name[e->sal_info_type],
+                                      rec_name[in1], e->cpuid);
+                       
+
+                       arg.type = e->sal_info_type;
+                       arg.status = 0;
+                       if (e->cpuid == smp_processor_id()) {
+                               IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: local\n");
+                               clear_state_info_on(&arg);
+                       } else {
+                               int ret;
+                               IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: 
remote\n");
+                               ret = smp_call_function_single(e->cpuid,
+                                       clear_state_info_on, &arg, 0, 1);
+                               if (ret < 0) {
+                                       printk("sal_emulator: "
+                                              "SAL_CLEAR_STATE_INFO "
+                                              "smp_call_function_single error:"
+                                              " %d\n", ret);
+                                       arg.ret = 0;
+                                       arg.status =
+                                            IA64_SAL_NO_INFORMATION_AVAILABLE;
+                               }
+                       }
+                       r9 = arg.ret;
+                       status = arg.status;
+                       xfree(e);
+               }
                break;
            case SAL_MC_RENDEZ:
                printk("*** CALLED SAL_MC_RENDEZ.  IGNORED...\n");
                break;
            case SAL_MC_SET_PARAMS:
-               printk("*** CALLED SAL_MC_SET_PARAMS.  IGNORED...\n");
+               if (in1 > sizeof(sal_mc_params)/sizeof(sal_mc_params[0]))
+                       BUG();
+               sal_mc_params[in1].param_type   = in1;
+               sal_mc_params[in1].i_or_m       = in2;
+               sal_mc_params[in1].i_or_m_val   = in3;
+               sal_mc_params[in1].timeout      = in4;
+               sal_mc_params[in1].rz_always    = in5;
                break;
            case SAL_CACHE_FLUSH:
                if (1) {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.