/*
* fw_emul.c:
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <xen/config.h>
#include <asm/system.h>
#include <asm/pgalloc.h>
#include <linux/efi.h>
#include <asm/pal.h>
#include <asm/sal.h>
#include <asm/sn/sn_sal.h>
#include <asm/xenmca.h>
#include <public/sched.h>
#include "hpsim_ssc.h"
#include <asm/vcpu.h>
#include <asm/vmx_vcpu.h>
#include <asm/dom_fw.h>
#include <asm/uaccess.h>
#include <xen/console.h>
#include <xen/hypercall.h>
#include <xen/softirq.h>
#include <xen/time.h>
static DEFINE_SPINLOCK(efi_time_services_lock);
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)) {