[PATCH] RTAS syscall - review request

John Rose johnrose at austin.ibm.com
Tue Nov 11 04:51:21 EST 2003


This patch implements a generic RTAS interface to userspace through a
system call.  It was originally written by Rusty Russel and modified by
myself.  There are two main parts:

- A new "rtas" syscall, which allows a user app to make any RTAS call
  available to the system.

- A special RMO buffer is reserved at boot time for user-space apps that
  require low memory.  Some RTAS calls require such "workarea" buffers,
  so the kernel needs to somehow export low memory regions for
  user-space use.  This implementation exports the physical address
  and size of the reserved region through a simple /proc file.  The user
  app is then free to mmap() /dev/mem at the address specified.

Please respond with any comments by EOB Thursday, Nov 13th.

Thanks-
John

diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Mon Nov 10 11:34:58 2003
+++ b/arch/ppc/kernel/misc.S	Mon Nov 10 11:34:58 2003
@@ -1385,3 +1385,4 @@
 	.long sys_statfs64
 	.long sys_fstatfs64
 	.long ppc_fadvise64_64
+	.long sys_ni_syscall	/* 255 - rtas (used on ppc64) */
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Mon Nov 10 11:34:58 2003
+++ b/arch/ppc64/kernel/misc.S	Mon Nov 10 11:34:58 2003
@@ -852,6 +852,8 @@
 	.llong .sys32_utimes
 	.llong .sys_statfs64
 	.llong .sys_fstatfs64
+	.llong .sys_ni_syscall		/* 32bit only fadvise64 */
+	.llong .ppc_rtas		/* 255 */

 	.balign 8
 _GLOBAL(sys_call_table)
@@ -1109,3 +1111,5 @@
 	.llong .sys_utimes
 	.llong .sys_statfs64
 	.llong .sys_fstatfs64
+	.llong .sys_ni_syscall		/* 32bit only fadvise64 */
+	.llong .ppc_rtas		/* 255 */
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Mon Nov 10 11:34:58 2003
+++ b/arch/ppc64/kernel/prom.c	Mon Nov 10 11:34:58 2003
@@ -611,6 +611,10 @@
 						      _rtas->base) >= 0) {
 				_rtas->entry = (long)_prom->args.rets[1];
 			}
+			RELOC(rtas_rmo_buf)
+				= (void *)lmb_alloc_base(RTAS_SYSCALL_MAX,
+							 PAGE_SIZE,
+							 rtas_region);
 		}

 		if (_rtas->entry <= 0) {
diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
--- a/arch/ppc64/kernel/rtas-proc.c	Mon Nov 10 11:34:58 2003
+++ b/arch/ppc64/kernel/rtas-proc.c	Mon Nov 10 11:34:58 2003
@@ -161,6 +161,8 @@
 		size_t count, loff_t *ppos);
 static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
 		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_rmo_buf_read(struct file *file, char *buf,
+				    size_t count, loff_t *ppos);

 struct file_operations ppc_rtas_poweron_operations = {
 	.read =		ppc_rtas_poweron_read,
@@ -185,6 +187,10 @@
 	.write =	ppc_rtas_tone_volume_write
 };

+static struct file_operations ppc_rtas_rmo_buf_ops = {
+	.read =		ppc_rtas_rmo_buf_read,
+};
+
 int ppc_rtas_find_all_sensors (void);
 int ppc_rtas_process_sensor(struct individual_sensor s, int state,
 		int error, char * buf);
@@ -233,6 +239,9 @@

 	entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas);
 	if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
+
+	entry = create_proc_entry("rmo_buffer", S_IRUSR, proc_rtas);
+	if (entry) entry->proc_fops = &ppc_rtas_rmo_buf_ops;
 }

 /* ****************************************************************** */
@@ -842,6 +851,23 @@
 	int n;
 	n = sprintf(buf, "%lu\n", rtas_tone_volume);

+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* RTAS Userspace access */
+static ssize_t ppc_rtas_rmo_buf_read(struct file *file, char *buf,
+				    size_t count, loff_t *ppos)
+{
+	int n;
+
+	n = sprintf(buf, "%p %x\n", rtas_rmo_buf, RTAS_SYSCALL_MAX);
 	if (*ppos >= strlen(buf))
 		return 0;
 	if (n > strlen(buf) - *ppos)
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	Mon Nov 10 11:34:58 2003
+++ b/arch/ppc64/kernel/rtas.c	Mon Nov 10 11:34:58 2003
@@ -29,6 +29,7 @@
 #include <asm/abs_addr.h>
 #include <asm/udbg.h>
 #include <asm/delay.h>
+#include <asm/uaccess.h>

 struct flash_block_list_header rtas_firmware_flash_list = {0, 0};

@@ -381,6 +382,44 @@
 	if (rtas_firmware_flash_list.next)
 		rtas_flash_bypass_warning();
         rtas_power_off();
+}
+
+void *rtas_rmo_buf = NULL;
+
+asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
+{
+	struct rtas_args args;
+	unsigned long flags;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
+		return -EFAULT;
+
+	if (args.nargs > ARRAY_SIZE(args.args)
+	    || args.nret > ARRAY_SIZE(args.args)
+	    || args.nargs + args.nret > ARRAY_SIZE(args.args))
+		return -EINVAL;
+
+	/* Copy in args. */
+	if (copy_from_user(args.args, uargs->args,
+			   args.nargs * sizeof(rtas_arg_t)) != 0)
+		return -EFAULT;
+
+	spin_lock_irqsave(&rtas.lock, flags);
+	get_paca()->xRtas = args;
+	enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas));
+	args = get_paca()->xRtas;
+	spin_unlock_irqrestore(&rtas.lock, flags);
+
+	/* Copy out args. */
+	if (copy_to_user(uargs->args + args.nargs,
+			 args.args + args.nargs,
+			 args.nret * sizeof(rtas_arg_t)) != 0)
+		return -EFAULT;
+
+	return 0;
 }

 EXPORT_SYMBOL(proc_ppc64);
diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
--- a/arch/ppc64/kernel/syscalls.c	Mon Nov 10 11:34:58 2003
+++ b/arch/ppc64/kernel/syscalls.c	Mon Nov 10 11:34:58 2003
@@ -41,6 +41,7 @@
 #include <asm/ipc.h>
 #include <asm/semaphore.h>
 #include <asm/time.h>
+#include <asm/unistd.h>

 extern unsigned long wall_jiffies;

@@ -234,3 +235,6 @@

 	return secs;
 }
+
+/* Only exists on P-series. */
+cond_syscall(ppc_rtas);
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Mon Nov 10 11:34:58 2003
+++ b/include/asm-ppc/unistd.h	Mon Nov 10 11:34:58 2003
@@ -259,8 +259,9 @@
 #define __NR_statfs64		252
 #define __NR_fstatfs64		253
 #define __NR_fadvise64_64	254
+#define __NR_rtas		255

-#define __NR_syscalls		255
+#define __NR_syscalls		256

 #define __NR(n)	#n

diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h	Mon Nov 10 11:34:58 2003
+++ b/include/asm-ppc64/rtas.h	Mon Nov 10 11:34:58 2003
@@ -19,6 +19,9 @@
 #define RTAS_UNKNOWN_SERVICE (-1)
 #define RTAS_INSTANTIATE_MAX (1UL<<30) /* Don't instantiate rtas at/above this value */

+/* Buffer size for ppc_rtas system call. */
+#define RTAS_SYSCALL_MAX (64 * 1024)
+
 /*
  * In general to call RTAS use rtas_token("string") to lookup
  * an RTAS token for the given string (e.g. "event-scan").
@@ -188,5 +191,8 @@

 extern spinlock_t rtas_data_buf_lock;
 extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
+
+/* Buffer used for ppc_rtas system call */
+extern void *rtas_rmo_buf;

 #endif /* _PPC64_RTAS_H */
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	Mon Nov 10 11:34:58 2003
+++ b/include/asm-ppc64/unistd.h	Mon Nov 10 11:34:58 2003
@@ -264,8 +264,10 @@
 #define __NR_utimes		251
 #define __NR_statfs64		252
 #define __NR_fstatfs64		253
+#define __NR_fadvise64_64	254
+#define __NR_rtas		255

-#define __NR_syscalls		254
+#define __NR_syscalls		256
 #ifdef __KERNEL__
 #define NR_syscalls	__NR_syscalls
 #endif


** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc64-dev mailing list