⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fw_emul.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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/sn/hubdev.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>#include <asm/debugger.h>#include <asm/vmx_phy_mode.h>static DEFINE_SPINLOCK(efi_time_services_lock);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...)#endifvoid 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_valuessal_emulator (long index, unsigned long in1, unsigned long in2,	      unsigned long in3, unsigned long in4, unsigned long in5,	      unsigned long in6, unsigned long in7){	struct ia64_sal_retval ret_stuff;	unsigned long r9  = 0;	unsigned long r10 = 0;	long r11 = 0;	long status;	debugger_event(XEN_IA64_DEBUG_ON_SAL);	status = 0;	switch (index) {	    case SAL_FREQ_BASE:		if (likely(!running_on_sim))			status = ia64_sal_freq_base(in1,&r9,&r10);		else switch (in1) {		      case SAL_FREQ_BASE_PLATFORM:			r9 = 200000000;			break;		      case SAL_FREQ_BASE_INTERVAL_TIMER:			r9 = 700000000;			break;		      case SAL_FREQ_BASE_REALTIME_CLOCK:			r9 = 1;			break;		      default:			status = -1;			break;		}		break;	    case SAL_PCI_CONFIG_READ:		if (current->domain == dom0) {			u64 value;			// note that args 2&3 are swapped!!			status = ia64_sal_pci_config_read(in1,in3,in2,&value);			r9 = value;		}		else		     printk("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_READ\n");		break;	    case SAL_PCI_CONFIG_WRITE:		if (current->domain == dom0) {			if (((in1 & ~0xffffffffUL) && (in4 == 0)) ||			    (in4 > 1) ||			    (in2 > 8) || (in2 & (in2-1)))				printk("*** SAL_PCI_CONF_WRITE?!?(adr=0x%lx,typ=0x%lx,sz=0x%lx,val=0x%lx)\n",					in1,in4,in2,in3);			// note that args are in a different order!!			status = ia64_sal_pci_config_write(in1,in4,in2,in3);		}		else		     printk("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n");		break;	    case SAL_SET_VECTORS: 		if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) { 			if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) { 				/* Sanity check: cs_length1 must be 0, 				   second vector is reserved.  */ 				status = -2; 			} 			else {				struct domain *d = current->domain;				d->arch.sal_data->boot_rdv_ip = in2;				d->arch.sal_data->boot_rdv_r1 = in3;			} 		} 		else if (current->domain == dom0) {			if (in1 >			    sizeof(sal_vectors)/sizeof(sal_vectors[0])-1) {				gdprintk(XENLOG_DEBUG,					 "SAL_SET_VECTORS invalid in1 %ld\n",					 in1);				status = -2;				break;			}			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;		} else {			gdprintk(XENLOG_DEBUG, "NON-PRIV DOMAIN CALLED "				 "SAL_SET_VECTORS %ld\n", in1);			/*			 * status = -2;			 * Temporal work around untill gfw support:			 * windows 2003 sp2/sp1 dislike -2 to crash.			 */			status = 0; 		}		break;	    case SAL_GET_STATE_INFO:		if (current->domain == dom0) {			sal_queue_entry_t *e;			unsigned long flags;			struct smp_call_args_t arg;			spin_lock_irqsave(&sal_queue_lock, flags);			if (!sal_queue || 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);			list_del(&e->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) {				xfree(e);			} else {				/* Re-add the entry to sal_queue */				spin_lock_irqsave(&sal_queue_lock, flags);				list_add(&e->list, &sal_queue[in1]);				spin_unlock_irqrestore(&sal_queue_lock, flags);			}		} else {			status = IA64_SAL_NO_INFORMATION_AVAILABLE;			r9 = 0;		}		break;	    case SAL_GET_STATE_INFO_SIZE:		r9 = ia64_sal_get_state_info_size(in1);		break;	    case SAL_CLEAR_STATE_INFO:		if (current->domain == dom0) {			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:		if (current->domain == dom0) {			if (in1 > 			    sizeof(sal_mc_params) / sizeof(sal_mc_params[0])) {				gdprintk(XENLOG_DEBUG,					 "SAL_MC_SET_PARAMS invalid in1 %ld\n",					 in1);				status = -2;				break;			}			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;		} else {			gdprintk(XENLOG_DEBUG,				 "*** CALLED SAL_MC_SET_PARAMS. IGNORED...\n");			/*			 * status = -1;			 * Temporal work around untill gfw support:			 * windows 2003 sp2/sp1 dislike -1(not implemented)			 * to crash.			 */			status = 0;		}		break;	    case SAL_CACHE_FLUSH:		if (1) {			/*  Flush using SAL.			    This method is faster but has a side effect on			    other vcpu running on this cpu.  */			status = ia64_sal_cache_flush (in1);		}		else {			/*  Flush with fc all the domain.			    This method is slower but has no side effects.  */			domain_cache_flush (current->domain, in1 == 4 ? 1 : 0);			status = 0;		}		break;	    case SAL_CACHE_INIT:		printk("*** CALLED SAL_CACHE_INIT.  IGNORED...\n");		break;	    case SAL_UPDATE_PAL:		printk("*** CALLED SAL_UPDATE_PAL.  IGNORED...\n");		break;	    case SAL_PHYSICAL_ID_INFO:		status = -1;		break;	    case SAL_XEN_SAL_RETURN:	        if (!test_and_set_bit(_VPF_down, &current->pause_flags))			vcpu_sleep_nosync(current);		break;	    case SN_SAL_GET_MASTER_NASID:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_GET_MASTER_NASID ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_MASTER_NASID,					0, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_GET_KLCONFIG_ADDR:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_GET_KLCONFIG_ADDR ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_KLCONFIG_ADDR,					in1, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_GET_SAPIC_INFO:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_GET_SAPIC_INFO ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SAPIC_INFO,					in1, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_GET_SN_INFO:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_GET_SN_INFO ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO,					in1, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_IOIF_GET_HUBDEV_INFO:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_IOIF_GET_HUBDEV_INFO ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_IOIF_GET_HUBDEV_INFO,					in1, in2, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_IOIF_INIT:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_IOIF_INIT ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_IOIF_INIT,					0, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_GET_PROM_FEATURE_SET:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_GET_PROM_FEATURE_SET ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_PROM_FEATURE_SET,					in1, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_SET_OS_FEATURE_SET:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_SET_OS_FEATURE_SET ***\n"); */			SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SET_OS_FEATURE_SET,					in1, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;	    case SN_SAL_SET_ERROR_HANDLING_FEATURES:		status = -1;		if (current->domain == dom0) {			/* printk("*** Emulating SN_SAL_SET_ERROR_HANDLING_FEATURES ***\n"); */			SAL_CALL_NOLOCK(ret_stuff,					SN_SAL_SET_ERROR_HANDLING_FEATURES,					in1, 0, 0, 0, 0, 0, 0);			status = ret_stuff.status;			r9 = ret_stuff.v0;			r10 = ret_stuff.v1;			r11 = ret_stuff.v2;		}		break;#if 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -