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

📄 lparcfg.c

📁 linux-2.4.29操作系统的源码
💻 C
字号:
/* * PowerPC64 LPAR Configuration Information Driver * * Dave Engebretsen engebret@us.ibm.com *    Copyright (c) 2003 Dave Engebretsen * Will Schmidt willschm@us.ibm.com *    SPLPAR updates, Copyright (c) 2003 Will Schmidt IBM Corporation. * *      This program is free software; you can redistribute it and/or *      modify it under the terms of the GNU General Public License *      as published by the Free Software Foundation; either version *      2 of the License, or (at your option) any later version. * * This driver creates a proc file at /proc/ppc64/lparcfg which contains * keyword - value pairs that specify the configuration of the partition. */#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/iSeries/HvLpConfig.h>#include <asm/iSeries/ItLpPaca.h>#include <asm/hvcall.h>#include <asm/cputable.h>#define MODULE_VERSION "1.0"#define MODULE_NAME "lparcfg"static struct proc_dir_entry *proc_ppc64_lparcfg;#define LPARCFG_BUFF_SIZE 4096#ifdef CONFIG_PPC_ISERIESstatic unsigned char e2a(unsigned char x){	switch (x) {	case 0xF0:		return '0';	case 0xF1:		return '1';	case 0xF2:		return '2';	case 0xF3:		return '3';	case 0xF4:		return '4';	case 0xF5:		return '5';	case 0xF6:		return '6';	case 0xF7:		return '7';	case 0xF8:		return '8';	case 0xF9:		return '9';	case 0xC1:		return 'A';	case 0xC2:		return 'B';	case 0xC3:		return 'C';	case 0xC4:		return 'D';	case 0xC5:		return 'E';	case 0xC6:		return 'F';	case 0xC7:		return 'G';	case 0xC8:		return 'H';	case 0xC9:		return 'I';	case 0xD1:		return 'J';	case 0xD2:		return 'K';	case 0xD3:		return 'L';	case 0xD4:		return 'M';	case 0xD5:		return 'N';	case 0xD6:		return 'O';	case 0xD7:		return 'P';	case 0xD8:		return 'Q';	case 0xD9:		return 'R';	case 0xE2:		return 'S';	case 0xE3:		return 'T';	case 0xE4:		return 'U';	case 0xE5:		return 'V';	case 0xE6:		return 'W';	case 0xE7:		return 'X';	case 0xE8:		return 'Y';	case 0xE9:		return 'Z';	}	return ' ';}/* * Methods used to fetch LPAR data when running on an iSeries platform. */static int lparcfg_data(unsigned char *buf, unsigned long size){	unsigned long n = 0, pool_id, lp_index;	int shared, entitled_capacity, max_entitled_capacity;	int processors, max_processors;	struct paca_struct *lpaca = get_paca();	if((buf == NULL) || (size > LPARCFG_BUFF_SIZE)) {		return -EFAULT;	}	memset(buf, 0, size);	shared = (int)(lpaca->xLpPacaPtr->xSharedProc);	n += snprintf(buf, LPARCFG_BUFF_SIZE - n,		      "serial_number=%c%c%c%c%c%c%c\n",		      e2a(xItExtVpdPanel.mfgID[2]),		      e2a(xItExtVpdPanel.mfgID[3]),		      e2a(xItExtVpdPanel.systemSerial[1]),		      e2a(xItExtVpdPanel.systemSerial[2]),		      e2a(xItExtVpdPanel.systemSerial[3]),		      e2a(xItExtVpdPanel.systemSerial[4]),		      e2a(xItExtVpdPanel.systemSerial[5]));	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "system_type=%c%c%c%c\n",		      e2a(xItExtVpdPanel.machineType[0]),		      e2a(xItExtVpdPanel.machineType[1]),		      e2a(xItExtVpdPanel.machineType[2]),		      e2a(xItExtVpdPanel.machineType[3]));	lp_index = HvLpConfig_getLpIndex();	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_id=%d\n", (int)lp_index);	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "system_active_processors=%d\n",		      (int)HvLpConfig_getSystemPhysicalProcessors());	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "system_potential_processors=%d\n",		      (int)HvLpConfig_getSystemPhysicalProcessors());	processors = (int)HvLpConfig_getPhysicalProcessors();	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_active_processors=%d\n", processors);	max_processors = (int)HvLpConfig_getMaxPhysicalProcessors();	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_potential_processors=%d\n", max_processors);	if(shared) {		entitled_capacity = HvLpConfig_getSharedProcUnits();		max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits();	} else {		entitled_capacity = processors * 100;		max_entitled_capacity = max_processors * 100;	}	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_entitled_capacity=%d\n", entitled_capacity);	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_max_entitled_capacity=%d\n",		      max_entitled_capacity);	if(shared) {		pool_id = HvLpConfig_getSharedPoolIndex();		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n",			      (int)pool_id);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "pool_capacity=%d\n", (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100));	}	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "shared_processor_mode=%d\n", shared);	return 0;}#endif /* CONFIG_PPC_ISERIES */#ifdef CONFIG_PPC_PSERIES/* * Methods used to fetch LPAR data when running on a pSeries platform. *//* * H_GET_PPP hcall returns info in 4 parms. *  entitled_capacity,unallocated_capacity, *  aggregation, resource_capability). * *  R4 = Entitled Processor Capacity Percentage. *  R5 = Unallocated Processor Capacity Percentage. *  R6 (AABBCCDDEEFFGGHH). *      XXXX - reserved (0) *          XXXX - reserved (0) *              XXXX - Group Number *                  XXXX - Pool Number. *  R7 (PPOONNMMLLKKJJII) *      XX - reserved. (0) *        XX - bit 0-6 reserved (0).   bit 7 is Capped indicator. *          XX - variable processor Capacity Weight *            XX - Unallocated Variable Processor Capacity Weight. *              XXXX - Active processors in Physical Processor Pool. *                  XXXX  - Processors active on platform. */unsigned int h_get_ppp(unsigned long *entitled,unsigned long  *unallocated,unsigned long *aggregation,unsigned long *resource){	unsigned long rc;	rc = plpar_hcall_4out(H_GET_PPP,0,0,0,0,entitled,unallocated,aggregation,resource);	return 0;}/* * get_splpar_potential_characteristics(). * Retrieve the potential_processors and max_entitled_capacity values * through the get-system-parameter rtas call. */#define SPLPAR_CHARACTERISTICS_TOKEN 20#define SPLPAR_MAXLENGTH 1026*(sizeof(char))unsigned int get_splpar_potential_characteristics(){	/* return 0 for now.  Underlying rtas functionality is not yet complete. 12/01/2003*/	return 0;#if 0	long call_status;	unsigned long ret[2];	char * buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);	printk("token for ibm,get-system-parameter (0x%x)\n",rtas_token("ibm,get-system-parameter"));	call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,				NULL,				SPLPAR_CHARACTERISTICS_TOKEN,				&buffer,				SPLPAR_MAXLENGTH,				(void *)&ret);	if (call_status!=0) {		printk("Error calling get-system-parameter (0x%lx)\n",call_status);		kfree(buffer);		return -1;	} else {		printk("get-system-parameter (%s)\n",buffer);		kfree(buffer);		/* TODO: Add code here to parse out value for system_potential_processors and partition_max_entitled_capacity */		return 1;	}#endif}static int lparcfg_data(unsigned char *buf, unsigned long size){	unsigned long n = 0;	int shared, max_entitled_capacity;	int processors, system_active_processors, system_potential_processors;	struct device_node *root;	const char *model = "";	const char *system_id = "";	unsigned int *lp_index_ptr, lp_index = 0;	struct device_node *rtas_node;	int *ip;	unsigned long h_entitled,h_unallocated,h_aggregation,h_resource;	if((buf == NULL) || (size > LPARCFG_BUFF_SIZE)) {		return -EFAULT;	}	memset(buf, 0, size);	root = find_path_device("/");	if (root) {		model = get_property(root, "model", NULL);		system_id = get_property(root, "system-id", NULL);		lp_index_ptr = (unsigned int *)get_property(root, "ibm,partition-no", NULL);		if(lp_index_ptr) lp_index = *lp_index_ptr;	}	n  = snprintf(buf, LPARCFG_BUFF_SIZE - n,		      "serial_number=%s\n", system_id);	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "system_type=%s\n", model);	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_id=%d\n", (int)lp_index);	rtas_node = find_path_device("/rtas");	ip = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);	if (ip == NULL) {		system_active_processors = systemcfg->processorCount;	} else {		system_active_processors = *(ip + 4);	}	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {		h_get_ppp(&h_entitled,&h_unallocated,&h_aggregation,&h_resource);#ifdef DEBUG		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "R4=0x%lx\n", h_entitled);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "R5=0x%lx\n", h_unallocated);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "R6=0x%lx\n", h_aggregation);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "R7=0x%lx\n", h_resource);#endif /* DEBUG */	}	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {		system_potential_processors =  get_splpar_potential_characteristics();		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "system_active_processors=%d\n",			      (h_resource >> 2*8) & 0xffff);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "system_potential_processors=%d\n",			      system_potential_processors);	} else {		system_potential_processors = system_active_processors;		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "system_active_processors=%d\n",			      system_active_processors);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "system_potential_processors=%d\n",			      system_potential_processors);	}	processors = systemcfg->processorCount;	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_active_processors=%d\n", processors);	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_potential_processors=%d\n",		      system_active_processors);	max_entitled_capacity = system_active_processors * 100;	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "partition_entitled_capacity=%ld\n", h_entitled);	} else {		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "partition_entitled_capacity=%d\n", system_active_processors*100);	}	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "partition_max_entitled_capacity=%d\n",		      max_entitled_capacity);	shared = 0;	n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,		      "shared_processor_mode=%d\n", shared);	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "pool=%d\n", (h_aggregation >> 0*8)&0xffff);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "pool_capacity=%d\n", (h_resource >> 3*8) &0xffff);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "group=%d\n", (h_aggregation >> 2*8)&0xffff);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "capped=%d\n", (h_resource >> 6*8)&0x40);		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,			      "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF);	}	return 0;}#endif /* CONFIG_PPC_PSERIES */static ssize_t lparcfg_read(struct file *file, char *buf,			    size_t count, loff_t *ppos){	struct proc_dir_entry *dp = file->f_dentry->d_inode->u.generic_ip;	unsigned long *data = (unsigned long *)dp->data;	unsigned long p;	ssize_t read;	char * pnt;	if (!data) {		printk(KERN_ERR "lparcfg: read failed no data\n");		return -EIO;	}	if(ppos) {		p = *ppos;	} else {		return -EFAULT;	}	if (p >= LPARCFG_BUFF_SIZE) return 0;	lparcfg_data((unsigned char *)data, LPARCFG_BUFF_SIZE);	if (count > (strlen((char *)data) - p))		count = (strlen((char *)data)) - p;	read = 0;	pnt = (char *)(data) + p;	copy_to_user(buf, (void *)pnt, count);	read += count;	*ppos = p + read;	return read;}static int lparcfg_open(struct inode * inode, struct file * file){	struct proc_dir_entry *dp = file->f_dentry->d_inode->u.generic_ip;	unsigned int *data = (unsigned int *)dp->data;	if (!data) {		printk(KERN_ERR "lparcfg: open failed no data\n");		return -EIO;	}	return 0;}struct file_operations lparcfg_fops = {	owner:		THIS_MODULE,	read:		lparcfg_read,	open:		lparcfg_open,};int __init lparcfg_init(void){	struct proc_dir_entry *ent;	ent = create_proc_entry("ppc64/lparcfg", S_IRUSR, NULL);	if (ent) {		ent->proc_fops = &lparcfg_fops;		ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL);		if (!ent->data) {			printk(KERN_ERR "Failed to allocate buffer for lparcfg\n");			remove_proc_entry("lparcfg", ent->parent);			return -ENOMEM;		}	} else {		printk(KERN_ERR "Failed to create ppc64/lparcfg\n");		return -EIO;	}	proc_ppc64_lparcfg = ent;	return 0;}void __exit lparcfg_cleanup(void){	if (proc_ppc64_lparcfg) {		if (proc_ppc64_lparcfg->data) {		    kfree(proc_ppc64_lparcfg->data);		}		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);	}}module_init(lparcfg_init);module_exit(lparcfg_cleanup);MODULE_DESCRIPTION("Interface for LPAR configuration data");MODULE_AUTHOR("Dave Engebretsen");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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