zcore.c

来自「linux 内核源代码」· C语言 代码 · 共 653 行 · 第 1/2 页

C
653
字号
	end = start + count;	while (zfcpdump_save_areas[i]) {		unsigned long cp_start, cp_end; /* copy range */		unsigned long sa_start, sa_end; /* save area range */		unsigned long prefix;		unsigned long sa_off, len, buf_off;		if (sys_info.arch == ARCH_S390)			prefix = zfcpdump_save_areas[i]->s390.pref_reg;		else			prefix = zfcpdump_save_areas[i]->s390x.pref_reg;		sa_start = prefix + sys_info.sa_base;		sa_end = prefix + sys_info.sa_base + sys_info.sa_size;		if ((end < sa_start) || (start > sa_end))			goto next;		cp_start = max(start, sa_start);		cp_end = min(end, sa_end);		buf_off = cp_start - start;		sa_off = cp_start - sa_start;		len = cp_end - cp_start;		TRACE("copy_lc for: %lx\n", start);		if (copy_lc(buf + buf_off, zfcpdump_save_areas[i], sa_off, len))			return -EFAULT;next:		i++;	}	return 0;}/* * Read routine for zcore character device * First 4K are dump header * Next 32MB are HSA Memory * Rest is read from absolute Memory */static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,			  loff_t *ppos){	unsigned long mem_start; /* Start address in memory */	size_t mem_offs;	 /* Offset in dump memory */	size_t hdr_count;	 /* Size of header part of output buffer */	size_t size;	int rc;	mutex_lock(&zcore_mutex);	if (*ppos > (sys_info.mem_size + HEADER_SIZE)) {		rc = -EINVAL;		goto fail;	}	count = min(count, (size_t) (sys_info.mem_size + HEADER_SIZE - *ppos));	/* Copy dump header */	if (*ppos < HEADER_SIZE) {		size = min(count, (size_t) (HEADER_SIZE - *ppos));		if (copy_to_user(buf, &zcore_header + *ppos, size)) {			rc = -EFAULT;			goto fail;		}		hdr_count = size;		mem_start = 0;	} else {		hdr_count = 0;		mem_start = *ppos - HEADER_SIZE;	}	mem_offs = 0;	/* Copy from HSA data */	if (*ppos < (ZFCPDUMP_HSA_SIZE + HEADER_SIZE)) {		size = min((count - hdr_count), (size_t) (ZFCPDUMP_HSA_SIZE			   - mem_start));		rc = memcpy_hsa_user(buf + hdr_count, mem_start, size);		if (rc)			goto fail;		mem_offs += size;	}	/* Copy from real mem */	size = count - mem_offs - hdr_count;	rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,			      size);	if (rc)		goto fail;	/*	 * Since s390 dump analysis tools like lcrash or crash	 * expect register sets in the prefix pages of the cpus,	 * we copy them into the read buffer, if necessary.	 * buf + hdr_count: Start of memory part of output buffer	 * mem_start: Start memory address to copy from	 * count - hdr_count: Size of memory area to copy	 */	if (zcore_add_lc(buf + hdr_count, mem_start, count - hdr_count)) {		rc = -EFAULT;		goto fail;	}	*ppos += count;fail:	mutex_unlock(&zcore_mutex);	return (rc < 0) ? rc : count;}static int zcore_open(struct inode *inode, struct file *filp){	if (!hsa_available)		return -ENODATA;	else		return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;}static int zcore_release(struct inode *inode, struct file *filep){	diag308(DIAG308_REL_HSA, NULL);	hsa_available = 0;	return 0;}static loff_t zcore_lseek(struct file *file, loff_t offset, int orig){	loff_t rc;	mutex_lock(&zcore_mutex);	switch (orig) {	case 0:		file->f_pos = offset;		rc = file->f_pos;		break;	case 1:		file->f_pos += offset;		rc = file->f_pos;		break;	default:		rc = -EINVAL;	}	mutex_unlock(&zcore_mutex);	return rc;}static struct file_operations zcore_fops = {	.owner		= THIS_MODULE,	.llseek		= zcore_lseek,	.read		= zcore_read,	.open		= zcore_open,	.release	= zcore_release,};static void __init set_s390_lc_mask(union save_area *map){	memset(&map->s390.ext_save, 0xff, sizeof(map->s390.ext_save));	memset(&map->s390.timer, 0xff, sizeof(map->s390.timer));	memset(&map->s390.clk_cmp, 0xff, sizeof(map->s390.clk_cmp));	memset(&map->s390.psw, 0xff, sizeof(map->s390.psw));	memset(&map->s390.pref_reg, 0xff, sizeof(map->s390.pref_reg));	memset(&map->s390.acc_regs, 0xff, sizeof(map->s390.acc_regs));	memset(&map->s390.fp_regs, 0xff, sizeof(map->s390.fp_regs));	memset(&map->s390.gp_regs, 0xff, sizeof(map->s390.gp_regs));	memset(&map->s390.ctrl_regs, 0xff, sizeof(map->s390.ctrl_regs));}static void __init set_s390x_lc_mask(union save_area *map){	memset(&map->s390x.fp_regs, 0xff, sizeof(map->s390x.fp_regs));	memset(&map->s390x.gp_regs, 0xff, sizeof(map->s390x.gp_regs));	memset(&map->s390x.psw, 0xff, sizeof(map->s390x.psw));	memset(&map->s390x.pref_reg, 0xff, sizeof(map->s390x.pref_reg));	memset(&map->s390x.fp_ctrl_reg, 0xff, sizeof(map->s390x.fp_ctrl_reg));	memset(&map->s390x.tod_reg, 0xff, sizeof(map->s390x.tod_reg));	memset(&map->s390x.timer, 0xff, sizeof(map->s390x.timer));	memset(&map->s390x.clk_cmp, 0xff, sizeof(map->s390x.clk_cmp));	memset(&map->s390x.acc_regs, 0xff, sizeof(map->s390x.acc_regs));	memset(&map->s390x.ctrl_regs, 0xff, sizeof(map->s390x.ctrl_regs));}/* * Initialize dump globals for a given architecture */static int __init sys_info_init(enum arch_id arch){	switch (arch) {	case ARCH_S390X:		MSG("DETECTED 'S390X (64 bit) OS'\n");		sys_info.sa_base = SAVE_AREA_BASE_S390X;		sys_info.sa_size = sizeof(struct save_area_s390x);		set_s390x_lc_mask(&sys_info.lc_mask);		break;	case ARCH_S390:		MSG("DETECTED 'S390 (32 bit) OS'\n");		sys_info.sa_base = SAVE_AREA_BASE_S390;		sys_info.sa_size = sizeof(struct save_area_s390);		set_s390_lc_mask(&sys_info.lc_mask);		break;	default:		ERROR_MSG("unknown architecture 0x%x.\n",arch);		return -EINVAL;	}	sys_info.arch = arch;	if (init_cpu_info(arch)) {		ERROR_MSG("get cpu info failed\n");		return -ENOMEM;	}	sys_info.mem_size = real_memory_size;	return 0;}static int __init check_sdias(void){	int rc, act_hsa_size;	rc = sclp_sdias_blk_count();	if (rc < 0) {		ERROR_MSG("Could not determine HSA size\n");		return rc;	}	act_hsa_size = (rc - 1) * PAGE_SIZE;	if (act_hsa_size < ZFCPDUMP_HSA_SIZE) {		ERROR_MSG("HSA size too small: %i\n", act_hsa_size);		return -EINVAL;	}	return 0;}static void __init zcore_header_init(int arch, struct zcore_header *hdr){	if (arch == ARCH_S390X)		hdr->arch_id = DUMP_ARCH_S390X;	else		hdr->arch_id = DUMP_ARCH_S390;	hdr->mem_size = sys_info.mem_size;	hdr->rmem_size = sys_info.mem_size;	hdr->mem_end = sys_info.mem_size;	hdr->num_pages = sys_info.mem_size / PAGE_SIZE;	hdr->tod = get_clock();	get_cpu_id(&hdr->cpu_id);}static int __init zcore_init(void){	unsigned char arch;	int rc;	if (ipl_info.type != IPL_TYPE_FCP_DUMP)		return -ENODATA;	zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));	debug_register_view(zcore_dbf, &debug_sprintf_view);	debug_set_level(zcore_dbf, 6);	TRACE("devno:  %x\n", ipl_info.data.fcp.dev_id.devno);	TRACE("wwpn:   %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn);	TRACE("lun:    %llx\n", (unsigned long long) ipl_info.data.fcp.lun);	rc = sclp_sdias_init();	if (rc)		goto fail;	rc = check_sdias();	if (rc) {		ERROR_MSG("Dump initialization failed\n");		goto fail;	}	rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1);	if (rc) {		ERROR_MSG("sdial memcpy for arch id failed\n");		goto fail;	}#ifndef __s390x__	if (arch == ARCH_S390X) {		ERROR_MSG("32 bit dumper can't dump 64 bit system!\n");		rc = -EINVAL;		goto fail;	}#endif	rc = sys_info_init(arch);	if (rc) {		ERROR_MSG("arch init failed\n");		goto fail;	}	zcore_header_init(arch, &zcore_header);	zcore_dir = debugfs_create_dir("zcore" , NULL);	if (!zcore_dir) {		rc = -ENOMEM;		goto fail;	}	zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL,					 &zcore_fops);	if (!zcore_file) {		debugfs_remove(zcore_dir);		rc = -ENOMEM;		goto fail;	}	hsa_available = 1;	return 0;fail:	diag308(DIAG308_REL_HSA, NULL);	return rc;}static void __exit zcore_exit(void){	debug_unregister(zcore_dbf);	sclp_sdias_exit();	diag308(DIAG308_REL_HSA, NULL);}MODULE_AUTHOR("Copyright IBM Corp. 2003,2007");MODULE_DESCRIPTION("zcore module for zfcpdump support");MODULE_LICENSE("GPL");subsys_initcall(zcore_init);module_exit(zcore_exit);

⌨️ 快捷键说明

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