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

📄 hypfs_diag.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static void diag204_free_buffer(void){	if (!diag204_buf)		return;	if (diag204_buf_vmalloc) {		vfree(diag204_buf_vmalloc);		diag204_buf_vmalloc = NULL;	} else {		free_pages((unsigned long) diag204_buf, 0);	}	diag204_buf_pages = 0;	diag204_buf = NULL;}static void *diag204_alloc_vbuf(int pages){	/* The buffer has to be page aligned! */	diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));	if (!diag204_buf_vmalloc)		return ERR_PTR(-ENOMEM);	diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc				& ~0xfffUL) + 0x1000;	diag204_buf_pages = pages;	return diag204_buf;}static void *diag204_alloc_rbuf(void){	diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);	if (!diag204_buf)		return ERR_PTR(-ENOMEM);	diag204_buf_pages = 1;	return diag204_buf;}static void *diag204_get_buffer(enum diag204_format fmt, int *pages){	if (diag204_buf) {		*pages = diag204_buf_pages;		return diag204_buf;	}	if (fmt == INFO_SIMPLE) {		*pages = 1;		return diag204_alloc_rbuf();	} else {/* INFO_EXT */		*pages = diag204((unsigned long)SUBC_RSI |				 (unsigned long)INFO_EXT, 0, NULL);		if (*pages <= 0)			return ERR_PTR(-ENOSYS);		else			return diag204_alloc_vbuf(*pages);	}}/* * diag204_probe() has to find out, which type of diagnose 204 implementation * we have on our machine. Currently there are three possible scanarios: *   - subcode 4   + simple data format (only one page) *   - subcode 4-6 + extended data format *   - subcode 4-7 + extended data format * * Subcode 5 is used to retrieve the size of the data, provided by subcodes * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition * to subcode 6 it provides also information about secondary cpus. * In order to get as much information as possible, we first try * subcode 7, then 6 and if both fail, we use subcode 4. */static int diag204_probe(void){	void *buf;	int pages, rc;	buf = diag204_get_buffer(INFO_EXT, &pages);	if (!IS_ERR(buf)) {		if (diag204((unsigned long)SUBC_STIB7 |			    (unsigned long)INFO_EXT, pages, buf) >= 0) {			diag204_store_sc = SUBC_STIB7;			diag204_info_type = INFO_EXT;			goto out;		}		if (diag204((unsigned long)SUBC_STIB6 |			    (unsigned long)INFO_EXT, pages, buf) >= 0) {			diag204_store_sc = SUBC_STIB7;			diag204_info_type = INFO_EXT;			goto out;		}		diag204_free_buffer();	}	/* subcodes 6 and 7 failed, now try subcode 4 */	buf = diag204_get_buffer(INFO_SIMPLE, &pages);	if (IS_ERR(buf)) {		rc = PTR_ERR(buf);		goto fail_alloc;	}	if (diag204((unsigned long)SUBC_STIB4 |		    (unsigned long)INFO_SIMPLE, pages, buf) >= 0) {		diag204_store_sc = SUBC_STIB4;		diag204_info_type = INFO_SIMPLE;		goto out;	} else {		rc = -ENOSYS;		goto fail_store;	}out:	rc = 0;fail_store:	diag204_free_buffer();fail_alloc:	return rc;}static void *diag204_store(void){	void *buf;	int pages;	buf = diag204_get_buffer(diag204_info_type, &pages);	if (IS_ERR(buf))		goto out;	if (diag204((unsigned long)diag204_store_sc |		    (unsigned long)diag204_info_type, pages, buf) < 0)		return ERR_PTR(-ENOSYS);out:	return buf;}/* Diagnose 224 functions */static int diag224(void *ptr){	int rc = -ENOTSUPP;	asm volatile(		"	diag	%1,%2,0x224\n"		"0:	lhi	%0,0x0\n"		"1:\n"		EX_TABLE(0b,1b)		: "+d" (rc) :"d" (0), "d" (ptr) : "memory");	return rc;}static int diag224_get_name_table(void){	/* memory must be below 2GB */	diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);	if (!diag224_cpu_names)		return -ENOMEM;	if (diag224(diag224_cpu_names)) {		kfree(diag224_cpu_names);		return -ENOTSUPP;	}	EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);	return 0;}static void diag224_delete_name_table(void){	kfree(diag224_cpu_names);}static int diag224_idx2name(int index, char *name){	memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),		CPU_NAME_LEN);	name[CPU_NAME_LEN] = 0;	strstrip(name);	return 0;}__init int hypfs_diag_init(void){	int rc;	if (diag204_probe()) {		printk(KERN_ERR "hypfs: diag 204 not working.");		return -ENODATA;	}	rc = diag224_get_name_table();	if (rc) {		diag204_free_buffer();		printk(KERN_ERR "hypfs: could not get name table.\n");	}	return rc;}void hypfs_diag_exit(void){	diag224_delete_name_table();	diag204_free_buffer();}/* * Functions to create the directory structure * ******************************************* */static int hypfs_create_cpu_files(struct super_block *sb,				  struct dentry *cpus_dir, void *cpu_info){	struct dentry *cpu_dir;	char buffer[TMP_SIZE];	void *rc;	snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,							    cpu_info));	cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);	rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",			      cpu_info__acc_time(diag204_info_type, cpu_info) -			      cpu_info__lp_time(diag204_info_type, cpu_info));	if (IS_ERR(rc))		return PTR_ERR(rc);	rc = hypfs_create_u64(sb, cpu_dir, "cputime",			      cpu_info__lp_time(diag204_info_type, cpu_info));	if (IS_ERR(rc))		return PTR_ERR(rc);	if (diag204_info_type == INFO_EXT) {		rc = hypfs_create_u64(sb, cpu_dir, "onlinetime",				      cpu_info__online_time(diag204_info_type,							    cpu_info));		if (IS_ERR(rc))			return PTR_ERR(rc);	}	diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);	rc = hypfs_create_str(sb, cpu_dir, "type", buffer);	if (IS_ERR(rc))		return PTR_ERR(rc);	return 0;}static void *hypfs_create_lpar_files(struct super_block *sb,				     struct dentry *systems_dir, void *part_hdr){	struct dentry *cpus_dir;	struct dentry *lpar_dir;	char lpar_name[LPAR_NAME_LEN + 1];	void *cpu_info;	int i;	part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);	lpar_name[LPAR_NAME_LEN] = 0;	lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name);	if (IS_ERR(lpar_dir))		return lpar_dir;	cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus");	if (IS_ERR(cpus_dir))		return cpus_dir;	cpu_info = part_hdr + part_hdr__size(diag204_info_type);	for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {		int rc;		rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);		if (rc)			return ERR_PTR(rc);		cpu_info += cpu_info__size(diag204_info_type);	}	return cpu_info;}static int hypfs_create_phys_cpu_files(struct super_block *sb,				       struct dentry *cpus_dir, void *cpu_info){	struct dentry *cpu_dir;	char buffer[TMP_SIZE];	void *rc;	snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,							    cpu_info));	cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);	if (IS_ERR(cpu_dir))		return PTR_ERR(cpu_dir);	rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",			      phys_cpu__mgm_time(diag204_info_type, cpu_info));	if (IS_ERR(rc))		return PTR_ERR(rc);	diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);	rc = hypfs_create_str(sb, cpu_dir, "type", buffer);	if (IS_ERR(rc))		return PTR_ERR(rc);	return 0;}static void *hypfs_create_phys_files(struct super_block *sb,				     struct dentry *parent_dir, void *phys_hdr){	int i;	void *cpu_info;	struct dentry *cpus_dir;	cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus");	if (IS_ERR(cpus_dir))		return cpus_dir;	cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);	for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {		int rc;		rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);		if (rc)			return ERR_PTR(rc);		cpu_info += phys_cpu__size(diag204_info_type);	}	return cpu_info;}int hypfs_diag_create_files(struct super_block *sb, struct dentry *root){	struct dentry *systems_dir, *hyp_dir;	void *time_hdr, *part_hdr;	int i, rc;	void *buffer, *ptr;	buffer = diag204_store();	if (IS_ERR(buffer))		return PTR_ERR(buffer);	systems_dir = hypfs_mkdir(sb, root, "systems");	if (IS_ERR(systems_dir)) {		rc = PTR_ERR(systems_dir);		goto err_out;	}	time_hdr = (struct x_info_blk_hdr *)buffer;	part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);	for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {		part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);		if (IS_ERR(part_hdr)) {			rc = PTR_ERR(part_hdr);			goto err_out;		}	}	if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) {		ptr = hypfs_create_phys_files(sb, root, part_hdr);		if (IS_ERR(ptr)) {			rc = PTR_ERR(ptr);			goto err_out;		}	}	hyp_dir = hypfs_mkdir(sb, root, "hyp");	if (IS_ERR(hyp_dir)) {		rc = PTR_ERR(hyp_dir);		goto err_out;	}	ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor");	if (IS_ERR(ptr)) {		rc = PTR_ERR(ptr);		goto err_out;	}	rc = 0;err_out:	return rc;}

⌨️ 快捷键说明

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