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

📄 ipl.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * dump section *//* FCP dump device attributes */DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",		   dump_block_fcp->ipl_info.fcp.wwpn);DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",		   dump_block_fcp->ipl_info.fcp.lun);DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",		   dump_block_fcp->ipl_info.fcp.bootprog);DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",		   dump_block_fcp->ipl_info.fcp.br_lba);DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",		   dump_block_fcp->ipl_info.fcp.devno);static struct attribute *dump_fcp_attrs[] = {	&sys_dump_fcp_device_attr.attr,	&sys_dump_fcp_wwpn_attr.attr,	&sys_dump_fcp_lun_attr.attr,	&sys_dump_fcp_bootprog_attr.attr,	&sys_dump_fcp_br_lba_attr.attr,	NULL,};static struct attribute_group dump_fcp_attr_group = {	.name  = IPL_FCP_STR,	.attrs = dump_fcp_attrs,};/* CCW dump device attributes */DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",		   dump_block_ccw->ipl_info.ccw.devno);static struct attribute *dump_ccw_attrs[] = {	&sys_dump_ccw_device_attr.attr,	NULL,};static struct attribute_group dump_ccw_attr_group = {	.name  = IPL_CCW_STR,	.attrs = dump_ccw_attrs,};/* dump type */static int dump_set_type(enum dump_type type){	if (!(dump_capabilities & type))		return -EINVAL;	switch(type) {	case DUMP_TYPE_CCW:		if (MACHINE_IS_VM)			dump_method = DUMP_METHOD_CCW_VM;		else if (diag308_set_works)			dump_method = DUMP_METHOD_CCW_DIAG;		else			dump_method = DUMP_METHOD_CCW_CIO;		break;	case DUMP_TYPE_FCP:		dump_method = DUMP_METHOD_FCP_DIAG;		break;	default:		dump_method = DUMP_METHOD_NONE;	}	dump_type = type;	return 0;}static ssize_t dump_type_show(struct kset *kset, char *page){	return sprintf(page, "%s\n", dump_type_str(dump_type));}static ssize_t dump_type_store(struct kset *kset, const char *buf,			       size_t len){	int rc = -EINVAL;	if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)		rc = dump_set_type(DUMP_TYPE_NONE);	else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)		rc = dump_set_type(DUMP_TYPE_CCW);	else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)		rc = dump_set_type(DUMP_TYPE_FCP);	return (rc != 0) ? rc : len;}static struct subsys_attribute dump_type_attr =		__ATTR(dump_type, 0644, dump_type_show, dump_type_store);static decl_subsys(dump, NULL, NULL);/* * Shutdown actions section */static decl_subsys(shutdown_actions, NULL, NULL);/* on panic */static ssize_t on_panic_show(struct kset *kset, char *page){	return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));}static ssize_t on_panic_store(struct kset *kset, const char *buf,			      size_t len){	if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)		on_panic_action = SHUTDOWN_REIPL;	else if (strncmp(buf, SHUTDOWN_DUMP_STR,			 strlen(SHUTDOWN_DUMP_STR)) == 0)		on_panic_action = SHUTDOWN_DUMP;	else if (strncmp(buf, SHUTDOWN_STOP_STR,			 strlen(SHUTDOWN_STOP_STR)) == 0)		on_panic_action = SHUTDOWN_STOP;	else		return -EINVAL;	return len;}static struct subsys_attribute on_panic_attr =		__ATTR(on_panic, 0644, on_panic_show, on_panic_store);void do_reipl(void){	struct ccw_dev_id devid;	static char buf[100];	char loadparm[LOADPARM_LEN + 1];	switch (reipl_method) {	case REIPL_METHOD_CCW_CIO:		devid.devno = reipl_block_ccw->ipl_info.ccw.devno;		if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)			diag308(DIAG308_IPL, NULL);		devid.ssid  = 0;		reipl_ccw_dev(&devid);		break;	case REIPL_METHOD_CCW_VM:		reipl_get_ascii_loadparm(loadparm);		if (strlen(loadparm) == 0)			sprintf(buf, "IPL %X CLEAR",				reipl_block_ccw->ipl_info.ccw.devno);		else			sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",				reipl_block_ccw->ipl_info.ccw.devno, loadparm);		__cpcmd(buf, NULL, 0, NULL);		break;	case REIPL_METHOD_CCW_DIAG:		diag308(DIAG308_SET, reipl_block_ccw);		diag308(DIAG308_IPL, NULL);		break;	case REIPL_METHOD_FCP_RW_DIAG:		diag308(DIAG308_SET, reipl_block_fcp);		diag308(DIAG308_IPL, NULL);		break;	case REIPL_METHOD_FCP_RO_DIAG:		diag308(DIAG308_IPL, NULL);		break;	case REIPL_METHOD_FCP_RO_VM:		__cpcmd("IPL", NULL, 0, NULL);		break;	case REIPL_METHOD_NSS:		sprintf(buf, "IPL %s", reipl_nss_name);		__cpcmd(buf, NULL, 0, NULL);		break;	case REIPL_METHOD_DEFAULT:		if (MACHINE_IS_VM)			__cpcmd("IPL", NULL, 0, NULL);		diag308(DIAG308_IPL, NULL);		break;	case REIPL_METHOD_FCP_DUMP:	default:		break;	}	signal_processor(smp_processor_id(), sigp_stop_and_store_status);}static void do_dump(void){	struct ccw_dev_id devid;	static char buf[100];	switch (dump_method) {	case DUMP_METHOD_CCW_CIO:		smp_send_stop();		devid.devno = dump_block_ccw->ipl_info.ccw.devno;		devid.ssid  = 0;		reipl_ccw_dev(&devid);		break;	case DUMP_METHOD_CCW_VM:		smp_send_stop();		sprintf(buf, "STORE STATUS");		__cpcmd(buf, NULL, 0, NULL);		sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);		__cpcmd(buf, NULL, 0, NULL);		break;	case DUMP_METHOD_CCW_DIAG:		diag308(DIAG308_SET, dump_block_ccw);		diag308(DIAG308_DUMP, NULL);		break;	case DUMP_METHOD_FCP_DIAG:		diag308(DIAG308_SET, dump_block_fcp);		diag308(DIAG308_DUMP, NULL);		break;	case DUMP_METHOD_NONE:	default:		return;	}	printk(KERN_EMERG "Dump failed!\n");}/* init functions */static int __init ipl_register_fcp_files(void){	int rc;	rc = sysfs_create_group(&ipl_subsys.kobj,				&ipl_fcp_attr_group);	if (rc)		goto out;	rc = sysfs_create_bin_file(&ipl_subsys.kobj,				   &ipl_parameter_attr);	if (rc)		goto out_ipl_parm;	rc = sysfs_create_bin_file(&ipl_subsys.kobj,				   &ipl_scp_data_attr);	if (!rc)		goto out;	sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);out_ipl_parm:	sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group);out:	return rc;}static int __init ipl_init(void){	int rc;	rc = firmware_register(&ipl_subsys);	if (rc)		return rc;	switch (ipl_info.type) {	case IPL_TYPE_CCW:		rc = sysfs_create_group(&ipl_subsys.kobj,					&ipl_ccw_attr_group);		break;	case IPL_TYPE_FCP:	case IPL_TYPE_FCP_DUMP:		rc = ipl_register_fcp_files();		break;	case IPL_TYPE_NSS:		rc = sysfs_create_group(&ipl_subsys.kobj,					&ipl_nss_attr_group);		break;	default:		rc = sysfs_create_group(&ipl_subsys.kobj,					&ipl_unknown_attr_group);		break;	}	if (rc)		firmware_unregister(&ipl_subsys);	return rc;}static void __init reipl_probe(void){	void *buffer;	buffer = (void *) get_zeroed_page(GFP_KERNEL);	if (!buffer)		return;	if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)		diag308_set_works = 1;	free_page((unsigned long)buffer);}static int __init reipl_nss_init(void){	int rc;	if (!MACHINE_IS_VM)		return 0;	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group);	if (rc)		return rc;	strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);	reipl_capabilities |= IPL_TYPE_NSS;	return 0;}static int __init reipl_ccw_init(void){	int rc;	reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);	if (!reipl_block_ccw)		return -ENOMEM;	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group);	if (rc) {		free_page((unsigned long)reipl_block_ccw);		return rc;	}	reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;	reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;	reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;	reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;	/* check if read scp info worked and set loadparm */	if (sclp_ipl_info.is_valid)		memcpy(reipl_block_ccw->ipl_info.ccw.load_param,		       &sclp_ipl_info.loadparm, LOADPARM_LEN);	else		/* read scp info failed: set empty loadparm (EBCDIC blanks) */		memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,		       LOADPARM_LEN);	/* FIXME: check for diag308_set_works when enabling diag ccw reipl */	if (!MACHINE_IS_VM)		sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;	if (ipl_info.type == IPL_TYPE_CCW)		reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;	reipl_capabilities |= IPL_TYPE_CCW;	return 0;}static int __init reipl_fcp_init(void){	int rc;	if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))		return 0;	if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))		make_attrs_ro(reipl_fcp_attrs);	reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);	if (!reipl_block_fcp)		return -ENOMEM;	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group);	if (rc) {		free_page((unsigned long)reipl_block_fcp);		return rc;	}	if (ipl_info.type == IPL_TYPE_FCP) {		memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);	} else {		reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;		reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;		reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;		reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;		reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;	}	reipl_capabilities |= IPL_TYPE_FCP;	return 0;}static int __init reipl_init(void){	int rc;	rc = firmware_register(&reipl_subsys);	if (rc)		return rc;	rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);	if (rc) {		firmware_unregister(&reipl_subsys);		return rc;	}	rc = reipl_ccw_init();	if (rc)		return rc;	rc = reipl_fcp_init();	if (rc)		return rc;	rc = reipl_nss_init();	if (rc)		return rc;	rc = reipl_set_type(ipl_info.type);	if (rc)		return rc;	return 0;}static int __init dump_ccw_init(void){	int rc;	dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);	if (!dump_block_ccw)		return -ENOMEM;	rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group);	if (rc) {		free_page((unsigned long)dump_block_ccw);		return rc;	}	dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;	dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;	dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;	dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;	dump_capabilities |= DUMP_TYPE_CCW;	return 0;}static int __init dump_fcp_init(void){	int rc;	if (!sclp_ipl_info.has_dump)		return 0; /* LDIPL DUMP is not installed */	if (!diag308_set_works)		return 0;	dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);	if (!dump_block_fcp)		return -ENOMEM;	rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group);	if (rc) {		free_page((unsigned long)dump_block_fcp);		return rc;	}	dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;	dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;	dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;	dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;	dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;	dump_capabilities |= DUMP_TYPE_FCP;	return 0;}#define SHUTDOWN_ON_PANIC_PRIO 0static int shutdown_on_panic_notify(struct notifier_block *self,				    unsigned long event, void *data){	if (on_panic_action == SHUTDOWN_DUMP)		do_dump();	else if (on_panic_action == SHUTDOWN_REIPL)		do_reipl();	return NOTIFY_OK;}static struct notifier_block shutdown_on_panic_nb = {	.notifier_call = shutdown_on_panic_notify,	.priority = SHUTDOWN_ON_PANIC_PRIO};static int __init dump_init(void){	int rc;	rc = firmware_register(&dump_subsys);	if (rc)		return rc;	rc = subsys_create_file(&dump_subsys, &dump_type_attr);	if (rc) {		firmware_unregister(&dump_subsys);		return rc;	}	rc = dump_ccw_init();	if (rc)		return rc;	rc = dump_fcp_init();	if (rc)		return rc;	dump_set_type(DUMP_TYPE_NONE);	return 0;}static int __init shutdown_actions_init(void){	int rc;	rc = firmware_register(&shutdown_actions_subsys);	if (rc)		return rc;	rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);	if (rc) {		firmware_unregister(&shutdown_actions_subsys);		return rc;	}	atomic_notifier_chain_register(&panic_notifier_list,				       &shutdown_on_panic_nb);	return 0;}static int __init s390_ipl_init(void){	int rc;	sclp_get_ipl_info(&sclp_ipl_info);	reipl_probe();	rc = ipl_init();	if (rc)		return rc;	rc = reipl_init();	if (rc)		return rc;	rc = dump_init();	if (rc)		return rc;	rc = shutdown_actions_init();	if (rc)		return rc;	return 0;}__initcall(s390_ipl_init);void __init ipl_save_parameters(void){	struct cio_iplinfo iplinfo;	unsigned int *ipl_ptr;	void *src, *dst;	if (cio_get_iplinfo(&iplinfo))		return;	ipl_devno = iplinfo.devno;	ipl_flags |= IPL_DEVNO_VALID;	if (!iplinfo.is_qdio)		return;	ipl_flags |= IPL_PARMBLOCK_VALID;	ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;	src = (void *)(unsigned long)*ipl_ptr;	dst = (void *)IPL_PARMBLOCK_ORIGIN;	memmove(dst, src, PAGE_SIZE);	*ipl_ptr = IPL_PARMBLOCK_ORIGIN;}static LIST_HEAD(rcall);static DEFINE_MUTEX(rcall_mutex);void register_reset_call(struct reset_call *reset){	mutex_lock(&rcall_mutex);	list_add(&reset->list, &rcall);	mutex_unlock(&rcall_mutex);}EXPORT_SYMBOL_GPL(register_reset_call);void unregister_reset_call(struct reset_call *reset){	mutex_lock(&rcall_mutex);	list_del(&reset->list);	mutex_unlock(&rcall_mutex);}EXPORT_SYMBOL_GPL(unregister_reset_call);static void do_reset_calls(void){	struct reset_call *reset;	list_for_each_entry(reset, &rcall, list)		reset->fn();}u32 dump_prefix_page;void s390_reset_system(void){	struct _lowcore *lc;	lc = (struct _lowcore *)(unsigned long) store_prefix();	/* Stack for interrupt/machine check handler */	lc->panic_stack = S390_lowcore.panic_stack;	/* Save prefix page address for dump case */	dump_prefix_page = (u32)(unsigned long) lc;	/* Disable prefixing */	set_prefix(0);	/* Disable lowcore protection */	__ctl_clear_bit(0,28);	/* Set new machine check handler */	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;	S390_lowcore.mcck_new_psw.addr =		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;	/* Set new program check handler */	S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;	S390_lowcore.program_new_psw.addr =		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;	do_reset_calls();}

⌨️ 快捷键说明

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