All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][2.6.11-mm3] perfctr API update 9/9: domain-based read/write syscalls
@ 2005-03-12 23:24 Mikael Pettersson
  0 siblings, 0 replies; only message in thread
From: Mikael Pettersson @ 2005-03-12 23:24 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel

- Convert sys_vperfctr_write() to accept <domain,data,datalen> triples.
  Have it interpret codes for the common domains, and pass unknown
  domains to perfctr_cpu_control_write().
- In sys_vperfctr_read(), replace "cmd" by "domain" and complete conversion
  to fine-grained domains for control data.
- Remove _reserved and cpu_control fields from struct vperfctr_control.

This depends on the cpu_control header and the cpu_control access patches.

Signed-off-by: Mikael Pettersson <mikpe@csd.uu.se>

/Mikael

 drivers/perfctr/virtual.c |  144 ++++++++++++++++++++++++++++------------------
 include/linux/perfctr.h   |   25 +++----
 2 files changed, 100 insertions(+), 69 deletions(-)

diff -rupN linux-2.6.11-mm3.perfctr-cpu_control-access/drivers/perfctr/virtual.c linux-2.6.11-mm3.perfctr-read-write-domains/drivers/perfctr/virtual.c
--- linux-2.6.11-mm3.perfctr-cpu_control-access/drivers/perfctr/virtual.c	2005-03-12 20:01:35.000000000 +0100
+++ linux-2.6.11-mm3.perfctr-read-write-domains/drivers/perfctr/virtual.c	2005-03-12 20:03:52.000000000 +0100
@@ -537,34 +537,25 @@ void __vperfctr_set_cpus_allowed(struct 
  ****************************************************************/
 
 static int do_vperfctr_write(struct vperfctr *perfctr,
-			     const struct vperfctr_control __user *argp,
-			     unsigned int argbytes,
+			     unsigned int domain,
+			     const void __user *srcp,
+			     unsigned int srcbytes,
 			     struct task_struct *tsk)
 {
-	struct vperfctr_control *control;
+	void *tmp;
 	int err;
 
 	if (!tsk)
 		return -ESRCH;	/* attempt to update unlinked perfctr */
 
-	/* The control object can be large (over 300 bytes on i386),
-	   so kmalloc() it instead of storing it on the stack.
-	   We must use task-private storage to prevent racing with a
-	   monitor process attaching to us before the non-preemptible
-	   perfctr update step. Therefore we cannot store the copy
-	   in the perfctr object itself. */
-	control = kmalloc(sizeof(*control), GFP_USER);
-	if (!control)
+	if (srcbytes > PAGE_SIZE) /* primitive sanity check */
+		return -EINVAL;
+	tmp = kmalloc(srcbytes, GFP_USER);
+	if (!tmp)
 		return -ENOMEM;
-
-	err = -EINVAL;
-	if (argbytes > sizeof *control)
-		goto out_kfree;
 	err = -EFAULT;
-	if (copy_from_user(control, argp, argbytes))
+	if (copy_from_user(tmp, srcp, srcbytes))
 		goto out_kfree;
-	if (argbytes < sizeof *control)
-		memset((char*)control + argbytes, 0, sizeof *control - argbytes);
 
 	/* PREEMPT note: preemption is disabled over the entire
 	   region since we're updating an active perfctr. */
@@ -575,16 +566,45 @@ static int do_vperfctr_write(struct vper
 		perfctr->cpu_state.cstatus = 0;
 		perfctr->resume_cstatus = 0;
 	}
-	perfctr->cpu_state.control = control->cpu_control;
-	/* XXX: validate si_signo? */
-	perfctr->si_signo = control->si_signo;
-	perfctr->preserve = control->preserve;
 
-	preempt_enable();
-	err = 0;
+	switch (domain) {
+	case VPERFCTR_DOMAIN_CONTROL: {
+		struct vperfctr_control control;
 
+		err = -EINVAL;
+		if (srcbytes > sizeof(control))
+			break;
+		control.si_signo = perfctr->si_signo;
+		control.preserve = perfctr->preserve;
+		memcpy(&control, tmp, srcbytes);
+		/* XXX: validate si_signo? */
+		perfctr->si_signo = control.si_signo;
+		perfctr->preserve = control.preserve;
+		err = 0;
+		break;
+	}
+	case PERFCTR_DOMAIN_CPU_CONTROL:
+		err = -EINVAL;
+		if (srcbytes > sizeof(perfctr->cpu_state.control.header))
+			break;
+		memcpy(&perfctr->cpu_state.control.header, tmp, srcbytes);
+		err = 0;
+		break;
+	case PERFCTR_DOMAIN_CPU_MAP:
+		err = -EINVAL;
+		if (srcbytes > sizeof(perfctr->cpu_state.control.pmc_map))
+			break;
+		memcpy(perfctr->cpu_state.control.pmc_map, tmp, srcbytes);
+		err = 0;
+		break;
+	default:
+		err = perfctr_cpu_control_write(&perfctr->cpu_state.control,
+						domain, tmp, srcbytes);
+	}
+
+	preempt_enable();
  out_kfree:
-	kfree(control);
+	kfree(tmp);
 	return err;
 }
 
@@ -751,9 +771,9 @@ static int do_vperfctr_control(struct vp
 }
 
 static int do_vperfctr_read(struct vperfctr *perfctr,
-			    unsigned int cmd,
-			    void __user *argp,
-			    unsigned int argbytes,
+			    unsigned int domain,
+			    void __user *dstp,
+			    unsigned int dstbytes,
 			    struct task_struct *tsk)
 {
 	union {
@@ -764,13 +784,12 @@ static int do_vperfctr_read(struct vperf
 	unsigned int tmpbytes;
 	int ret;
 
-	/* The state snapshot can be large (348 bytes on i386/x86_64),
-	   so kmalloc() it instead of storing it on the stack.
-	   We must use task-private storage to prevent racing with a
-	   monitor process attaching to us during the preemptible
-	   copy_to_user() step. Therefore we cannot store the snapshot
-	   in the perfctr object itself. */
-	tmp = kmalloc(sizeof(*tmp), GFP_USER);
+	tmpbytes = dstbytes;
+	if (tmpbytes > PAGE_SIZE) /* primitive sanity check */
+		return -EINVAL;
+	if (tmpbytes < sizeof(*tmp))
+		tmpbytes = sizeof(*tmp);
+	tmp = kmalloc(tmpbytes, GFP_USER);
 	if (!tmp)
 		return -ENOMEM;
 
@@ -782,44 +801,56 @@ static int do_vperfctr_read(struct vperf
 	if (tsk == current)
 		preempt_disable();
 
-	switch (cmd) {
-	case VPERFCTR_READ_SUM: {
+	switch (domain) {
+	case VPERFCTR_DOMAIN_SUM: {
 		int j;
 
 		vperfctr_sample(perfctr);
 		tmp->sum.tsc = perfctr->cpu_state.tsc_sum;
 		for(j = 0; j < ARRAY_SIZE(tmp->sum.pmc); ++j)
 			tmp->sum.pmc[j] = perfctr->cpu_state.pmc[j].sum;
-		tmpbytes = sizeof(tmp->sum);
+		ret = sizeof(tmp->sum);
 		break;
 	}
-	case VPERFCTR_READ_CONTROL:
+	case VPERFCTR_DOMAIN_CONTROL:
 		tmp->control.si_signo = perfctr->si_signo;
-		tmp->control.cpu_control = perfctr->cpu_state.control;
-		tmp->control.preserve = 0;
-		tmpbytes = sizeof(tmp->control);
+		tmp->control.preserve = perfctr->preserve;
+		ret = sizeof(tmp->control);
 		break;
-	case VPERFCTR_READ_CHILDREN:
+	case VPERFCTR_DOMAIN_CHILDREN:
 		if (tsk)
 			spin_lock(&perfctr->children_lock);
 		tmp->children = perfctr->children;
 		if (tsk)
 			spin_unlock(&perfctr->children_lock);
-		tmpbytes = sizeof(tmp->children);
+		ret = sizeof(tmp->children);
+		break;
+	case PERFCTR_DOMAIN_CPU_CONTROL:
+		if (tmpbytes > sizeof(perfctr->cpu_state.control.header))
+			tmpbytes = sizeof(perfctr->cpu_state.control.header);
+		memcpy(tmp, &perfctr->cpu_state.control.header, tmpbytes);
+		ret = tmpbytes;
+		break;
+	case PERFCTR_DOMAIN_CPU_MAP:
+		if (tmpbytes > sizeof(perfctr->cpu_state.control.pmc_map))
+			tmpbytes = sizeof(perfctr->cpu_state.control.pmc_map);
+		memcpy(tmp, perfctr->cpu_state.control.pmc_map, tmpbytes);
+		ret = tmpbytes;
 		break;
 	default:
-		tmpbytes = 0;
+		ret = -EFAULT;
+		if (copy_from_user(tmp, dstp, dstbytes) == 0)
+			ret = perfctr_cpu_control_read(&perfctr->cpu_state.control,
+						       domain, tmp, dstbytes);
 	}
 
 	if (tsk == current)
 		preempt_enable();
 
-	ret = -EINVAL;
-	if (tmpbytes > argbytes)
-		tmpbytes = argbytes;
-	if (tmpbytes > 0) {
-		ret = tmpbytes;
-		if (copy_to_user(argp, tmp, tmpbytes))
+	if (ret > 0) {
+		if (ret > dstbytes)
+			ret = dstbytes;
+		if (ret > 0 && copy_to_user(dstp, tmp, ret))
 			ret = -EFAULT;
 	}
 	kfree(tmp);
@@ -1130,8 +1161,8 @@ static void vperfctr_put_tsk(struct task
 		put_task_struct(tsk);
 }
 
-asmlinkage long sys_vperfctr_write(int fd,
-				   const struct vperfctr_control __user *argp,
+asmlinkage long sys_vperfctr_write(int fd, unsigned int domain,
+				   const void __user *argp,
 				   unsigned int argbytes)
 {
 	struct vperfctr *perfctr;
@@ -1146,7 +1177,7 @@ asmlinkage long sys_vperfctr_write(int f
 		ret = PTR_ERR(tsk);
 		goto out;
 	}
-	ret = do_vperfctr_write(perfctr, argp, argbytes, tsk);
+	ret = do_vperfctr_write(perfctr, domain, argp, argbytes, tsk);
 	vperfctr_put_tsk(tsk);
  out:
 	put_vperfctr(perfctr);
@@ -1174,7 +1205,8 @@ asmlinkage long sys_vperfctr_control(int
 	return ret;
 }
 
-asmlinkage long sys_vperfctr_read(int fd, unsigned int cmd, void __user *argp, unsigned int argbytes)
+asmlinkage long sys_vperfctr_read(int fd, unsigned int domain,
+				  void __user *argp, unsigned int argbytes)
 {
 	struct vperfctr *perfctr;
 	struct task_struct *tsk;
@@ -1188,7 +1220,7 @@ asmlinkage long sys_vperfctr_read(int fd
 		ret = PTR_ERR(tsk);
 		goto out;
 	}
-	ret = do_vperfctr_read(perfctr, cmd, argp, argbytes, tsk);
+	ret = do_vperfctr_read(perfctr, domain, argp, argbytes, tsk);
 	vperfctr_put_tsk(tsk);
  out:
 	put_vperfctr(perfctr);
diff -rupN linux-2.6.11-mm3.perfctr-cpu_control-access/include/linux/perfctr.h linux-2.6.11-mm3.perfctr-read-write-domains/include/linux/perfctr.h
--- linux-2.6.11-mm3.perfctr-cpu_control-access/include/linux/perfctr.h	2005-03-12 20:01:39.000000000 +0100
+++ linux-2.6.11-mm3.perfctr-read-write-domains/include/linux/perfctr.h	2005-03-12 20:03:52.000000000 +0100
@@ -47,11 +47,6 @@ struct vperfctr_state {
 struct vperfctr_control {
 	int si_signo;
 	unsigned int preserve;
-	unsigned int _reserved1;
-	unsigned int _reserved2;
-	unsigned int _reserved3;
-	unsigned int _reserved4;
-	struct perfctr_cpu_control cpu_control;
 };
 
 /* commands for sys_vperfctr_control() */
@@ -66,16 +61,18 @@ struct perfctr_cpu_reg {
 	unsigned int value;
 };
 
+/* state and control domain numbers
+   0-127 are for architecture-neutral domains
+   128-255 are for architecture-specific domains */
+#define VPERFCTR_DOMAIN_SUM		1	/* struct perfctr_sum_ctrs */
+#define VPERFCTR_DOMAIN_CONTROL		2	/* struct vperfctr_control */
+#define VPERFCTR_DOMAIN_CHILDREN	3	/* struct perfctr_sum_ctrs */
+
 /* domain numbers for common arch-specific control data */
 #define PERFCTR_DOMAIN_CPU_CONTROL	128	/* struct perfctr_cpu_control_header */
 #define PERFCTR_DOMAIN_CPU_MAP		129	/* unsigned int[] */
 #define PERFCTR_DOMAIN_CPU_REGS		130	/* struct perfctr_cpu_reg[] */
 
-/* commands for sys_vperfctr_read() */
-#define VPERFCTR_READ_SUM	0x01
-#define VPERFCTR_READ_CONTROL	0x02
-#define VPERFCTR_READ_CHILDREN	0x03
-
 #else
 struct perfctr_info;
 struct perfctr_cpu_mask;
@@ -90,10 +87,12 @@ struct vperfctr_control;
  */
 asmlinkage long sys_vperfctr_open(int tid, int creat);
 asmlinkage long sys_vperfctr_control(int fd, unsigned int cmd);
-asmlinkage long sys_vperfctr_write(int fd,
-				   const struct vperfctr_control __user *argp,
+asmlinkage long sys_vperfctr_write(int fd, unsigned int domain,
+				   const void __user *argp,
 				   unsigned int argbytes);
-asmlinkage long sys_vperfctr_read(int fd, unsigned int cmd, void __user *argp, unsigned int argbytes);
+asmlinkage long sys_vperfctr_read(int fd, unsigned int domain,
+				  void __user *argp,
+				  unsigned int argbytes);
 
 extern struct perfctr_info perfctr_info;
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-03-12 23:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-12 23:24 [PATCH][2.6.11-mm3] perfctr API update 9/9: domain-based read/write syscalls Mikael Pettersson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.