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

📄 appldata_base.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * arch/s390/appldata/appldata_base.c * * Base infrastructure for Linux-z/VM Monitor Stream, Stage 1. * Exports appldata_register_ops() and appldata_unregister_ops() for the * data gathering modules. * * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. * * Author: Gerald Schaefer <geraldsc@de.ibm.com> */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/errno.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/smp.h>#include <linux/interrupt.h>#include <linux/proc_fs.h>#include <linux/page-flags.h>#include <linux/swap.h>#include <linux/pagemap.h>#include <linux/sysctl.h>#include <asm/timer.h>//#include <linux/kernel_stat.h>#include <linux/notifier.h>#include <linux/cpu.h>#include <linux/workqueue.h>#include "appldata.h"#define MY_PRINT_NAME	"appldata"		/* for debug messages, etc. */#define APPLDATA_CPU_INTERVAL	10000		/* default (CPU) time for						   sampling interval in						   milliseconds */#define TOD_MICRO	0x01000			/* nr. of TOD clock units						   for 1 microsecond */#ifndef CONFIG_ARCH_S390X#define APPLDATA_START_INTERVAL_REC 0x00   	/* Function codes for */#define APPLDATA_STOP_REC	    0x01	/* DIAG 0xDC	  */#define APPLDATA_GEN_EVENT_RECORD   0x02#define APPLDATA_START_CONFIG_REC   0x03#else#define APPLDATA_START_INTERVAL_REC 0x80#define APPLDATA_STOP_REC   	    0x81#define APPLDATA_GEN_EVENT_RECORD   0x82#define APPLDATA_START_CONFIG_REC   0x83#endif /* CONFIG_ARCH_S390X *//* * Parameter list for DIAGNOSE X'DC' */#ifndef CONFIG_ARCH_S390Xstruct appldata_parameter_list {	u16 diag;		/* The DIAGNOSE code X'00DC'          */	u8  function;		/* The function code for the DIAGNOSE */	u8  parlist_length;	/* Length of the parameter list       */	u32 product_id_addr;	/* Address of the 16-byte product ID  */	u16 reserved;	u16 buffer_length;	/* Length of the application data buffer  */	u32 buffer_addr;	/* Address of the application data buffer */};#elsestruct appldata_parameter_list {	u16 diag;	u8  function;	u8  parlist_length;	u32 unused01;	u16 reserved;	u16 buffer_length;	u32 unused02;	u64 product_id_addr;	u64 buffer_addr;};#endif /* CONFIG_ARCH_S390X *//* * /proc entries (sysctl) */static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata";static int appldata_timer_handler(ctl_table *ctl, int write, struct file *filp,				  void __user *buffer, size_t *lenp, loff_t *ppos);static int appldata_interval_handler(ctl_table *ctl, int write,					 struct file *filp,					 void __user *buffer,					 size_t *lenp, loff_t *ppos);static struct ctl_table_header *appldata_sysctl_header;static struct ctl_table appldata_table[] = {	{		.ctl_name	= CTL_APPLDATA_TIMER,		.procname	= "timer",		.mode		= S_IRUGO | S_IWUSR,		.proc_handler	= &appldata_timer_handler,	},	{		.ctl_name	= CTL_APPLDATA_INTERVAL,		.procname	= "interval",		.mode		= S_IRUGO | S_IWUSR,		.proc_handler	= &appldata_interval_handler,	},	{ .ctl_name = 0 }};static struct ctl_table appldata_dir_table[] = {	{		.ctl_name	= CTL_APPLDATA,		.procname	= appldata_proc_name,		.maxlen		= 0,		.mode		= S_IRUGO | S_IXUGO,		.child		= appldata_table,	},	{ .ctl_name = 0 }};/* * Timer */DEFINE_PER_CPU(struct vtimer_list, appldata_timer);static atomic_t appldata_expire_count = ATOMIC_INIT(0);static DEFINE_SPINLOCK(appldata_timer_lock);static int appldata_interval = APPLDATA_CPU_INTERVAL;static int appldata_timer_active;/* * Work queue */static struct workqueue_struct *appldata_wq;static void appldata_work_fn(void *data);static DECLARE_WORK(appldata_work, appldata_work_fn, NULL);/* * Ops list */static DEFINE_SPINLOCK(appldata_ops_lock);static LIST_HEAD(appldata_ops_list);/*************************** timer, work, DIAG *******************************//* * appldata_timer_function() * * schedule work and reschedule timer */static void appldata_timer_function(unsigned long data, struct pt_regs *regs){	P_DEBUG("   -= Timer =-\n");	P_DEBUG("CPU: %i, expire_count: %i\n", smp_processor_id(),		atomic_read(&appldata_expire_count));	if (atomic_dec_and_test(&appldata_expire_count)) {		atomic_set(&appldata_expire_count, num_online_cpus());		queue_work(appldata_wq, (struct work_struct *) data);	}}/* * appldata_work_fn() * * call data gathering function for each (active) module */static void appldata_work_fn(void *data){	struct list_head *lh;	struct appldata_ops *ops;	int i;	P_DEBUG("  -= Work Queue =-\n");	i = 0;	spin_lock(&appldata_ops_lock);	list_for_each(lh, &appldata_ops_list) {		ops = list_entry(lh, struct appldata_ops, list);		P_DEBUG("list_for_each loop: %i) active = %u, name = %s\n",			++i, ops->active, ops->name);		if (ops->active == 1) {			ops->callback(ops->data);		}	}	spin_unlock(&appldata_ops_lock);}/* * appldata_diag() * * prepare parameter list, issue DIAG 0xDC */static int appldata_diag(char record_nr, u16 function, unsigned long buffer,			u16 length){	unsigned long ry;	struct appldata_product_id {		char prod_nr[7];			/* product nr. */		char prod_fn[2];			/* product function */		char record_nr;				/* record nr. */		char version_nr[2];			/* version */		char release_nr[2];			/* release */		char mod_lvl[2];			/* modification lvl. */	} appldata_product_id = {	/* all strings are EBCDIC, record_nr is byte */		.prod_nr    = {0xD3, 0xC9, 0xD5, 0xE4,				0xE7, 0xD2, 0xD9},	/* "LINUXKR" */		.prod_fn    = {0xD5, 0xD3},		/* "NL" */		.record_nr  = record_nr,		.version_nr = {0xF2, 0xF6},		/* "26" */		.release_nr = {0xF0, 0xF1},		/* "01" */		.mod_lvl    = {0xF0, 0xF0},		/* "00" */	};	struct appldata_parameter_list appldata_parameter_list = {				.diag = 0xDC,				.function = function,				.parlist_length =					sizeof(appldata_parameter_list),				.buffer_length = length,				.product_id_addr =					(unsigned long) &appldata_product_id,				.buffer_addr = virt_to_phys((void *) buffer)	};	if (!MACHINE_IS_VM)		return -ENOSYS;	ry = -1;	asm volatile(			"diag %1,%0,0xDC\n\t"			: "=d" (ry)			: "d" (&appldata_parameter_list),			  "m" (appldata_parameter_list),			  "m" (appldata_product_id)			: "cc");	return (int) ry;}/************************ timer, work, DIAG <END> ****************************//****************************** /proc stuff **********************************//* * appldata_mod_vtimer_wrap() * * wrapper function for mod_virt_timer(), because smp_call_function_on() * accepts only one parameter. */static void __appldata_mod_vtimer_wrap(void *p) {	struct {		struct vtimer_list *timer;		u64    expires;	} *args = p;	mod_virt_timer(args->timer, args->expires);}#define APPLDATA_ADD_TIMER	0#define APPLDATA_DEL_TIMER	1#define APPLDATA_MOD_TIMER	2/* * __appldata_vtimer_setup() * * Add, delete or modify virtual timers on all online cpus. * The caller needs to get the appldata_timer_lock spinlock. */static void__appldata_vtimer_setup(int cmd){	u64 per_cpu_interval;	int i;	switch (cmd) {	case APPLDATA_ADD_TIMER:		if (appldata_timer_active)			break;		per_cpu_interval = (u64) (appldata_interval*1000 /					  num_online_cpus()) * TOD_MICRO;		for_each_online_cpu(i) {			per_cpu(appldata_timer, i).expires = per_cpu_interval;			smp_call_function_on(add_virt_timer_periodic,					     &per_cpu(appldata_timer, i),					     0, 1, i);		}		appldata_timer_active = 1;		P_INFO("Monitoring timer started.\n");		break;	case APPLDATA_DEL_TIMER:		for_each_online_cpu(i)			del_virt_timer(&per_cpu(appldata_timer, i));		if (!appldata_timer_active)			break;		appldata_timer_active = 0;		atomic_set(&appldata_expire_count, num_online_cpus());		P_INFO("Monitoring timer stopped.\n");		break;	case APPLDATA_MOD_TIMER:		per_cpu_interval = (u64) (appldata_interval*1000 /					  num_online_cpus()) * TOD_MICRO;		if (!appldata_timer_active)			break;		for_each_online_cpu(i) {			struct {				struct vtimer_list *timer;				u64    expires;			} args;			args.timer = &per_cpu(appldata_timer, i);			args.expires = per_cpu_interval;			smp_call_function_on(__appldata_mod_vtimer_wrap,					     &args, 0, 1, i);		}	}}/* * appldata_timer_handler() * * Start/Stop timer, show status of timer (0 = not active, 1 = active) */static intappldata_timer_handler(ctl_table *ctl, int write, struct file *filp,			   void __user *buffer, size_t *lenp, loff_t *ppos){	int len;	char buf[2];	if (!*lenp || *ppos) {		*lenp = 0;		return 0;	}	if (!write) {		len = sprintf(buf, appldata_timer_active ? "1\n" : "0\n");		if (len > *lenp)			len = *lenp;		if (copy_to_user(buffer, buf, len))			return -EFAULT;		goto out;	}	len = *lenp;	if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))		return -EFAULT;	spin_lock(&appldata_timer_lock);	if (buf[0] == '1')		__appldata_vtimer_setup(APPLDATA_ADD_TIMER);	else if (buf[0] == '0')		__appldata_vtimer_setup(APPLDATA_DEL_TIMER);	spin_unlock(&appldata_timer_lock);out:	*lenp = len;	*ppos += len;	return 0;}/* * appldata_interval_handler() * * Set (CPU) timer interval for collection of data (in milliseconds), show * current timer interval. */static intappldata_interval_handler(ctl_table *ctl, int write, struct file *filp,			   void __user *buffer, size_t *lenp, loff_t *ppos){	int len, interval;	char buf[16];	if (!*lenp || *ppos) {		*lenp = 0;		return 0;	}	if (!write) {		len = sprintf(buf, "%i\n", appldata_interval);		if (len > *lenp)			len = *lenp;		if (copy_to_user(buffer, buf, len))			return -EFAULT;		goto out;	}	len = *lenp;	if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) {		return -EFAULT;	}	sscanf(buf, "%i", &interval);	if (interval <= 0) {		P_ERROR("Timer CPU interval has to be > 0!\n");		return -EINVAL;	}	spin_lock(&appldata_timer_lock);	appldata_interval = interval;

⌨️ 快捷键说明

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