[ppc64] add rtas syscall, from John Rose Added RTAS syscall. Reserved lowmem rtas_rmo_buf for userspace use. Created "rmo_buffer" proc file to export bounds of rtas_rmo_buf. --- arch/ppc/kernel/misc.S | 1 + arch/ppc64/kernel/misc.S | 2 ++ arch/ppc64/kernel/prom.c | 3 +++ arch/ppc64/kernel/rtas-proc.c | 34 ++++++++++++++++++++++++++++++++++ arch/ppc64/kernel/rtas.c | 39 +++++++++++++++++++++++++++++++++++++++ arch/ppc64/kernel/syscalls.c | 4 ++++ include/asm-ppc/unistd.h | 3 ++- include/asm-ppc64/rtas.h | 6 ++++++ include/asm-ppc64/unistd.h | 4 +++- 9 files changed, 94 insertions(+), 2 deletions(-) diff -puN arch/ppc/kernel/misc.S~ppc64-sys_rtas arch/ppc/kernel/misc.S --- 25/arch/ppc/kernel/misc.S~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/arch/ppc/kernel/misc.S 2004-01-13 23:22:43.000000000 -0800 @@ -1385,3 +1385,4 @@ _GLOBAL(sys_call_table) .long sys_statfs64 .long sys_fstatfs64 .long ppc_fadvise64_64 + .long sys_ni_syscall /* 255 - rtas (used on ppc64) */ diff -puN arch/ppc64/kernel/misc.S~ppc64-sys_rtas arch/ppc64/kernel/misc.S --- 25/arch/ppc64/kernel/misc.S~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/misc.S 2004-01-13 23:22:43.000000000 -0800 @@ -853,6 +853,7 @@ _GLOBAL(sys_call_table32) .llong .compat_statfs64 .llong .compat_fstatfs64 .llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */ + .llong .ppc_rtas /* 255 */ .balign 8 _GLOBAL(sys_call_table) @@ -1111,3 +1112,4 @@ _GLOBAL(sys_call_table) .llong .sys_statfs64 .llong .sys_fstatfs64 .llong .sys_ni_syscall /* 32bit only fadvise64_64 */ + .llong .ppc_rtas /* 255 */ diff -puN arch/ppc64/kernel/prom.c~ppc64-sys_rtas arch/ppc64/kernel/prom.c --- 25/arch/ppc64/kernel/prom.c~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/prom.c 2004-01-13 23:22:43.000000000 -0800 @@ -613,6 +613,9 @@ prom_instantiate_rtas(void) _rtas->base) >= 0) { _rtas->entry = (long)_prom->args.rets[1]; } + RELOC(rtas_rmo_buf) + = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, + rtas_region); } if (_rtas->entry <= 0) { diff -puN arch/ppc64/kernel/rtas-proc.c~ppc64-sys_rtas arch/ppc64/kernel/rtas-proc.c --- 25/arch/ppc64/kernel/rtas-proc.c~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtas-proc.c 2004-01-13 23:22:43.000000000 -0800 @@ -161,6 +161,8 @@ static ssize_t ppc_rtas_tone_volume_writ 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 @@ struct file_operations ppc_rtas_tone_vol .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 @@ void proc_rtas_init(void) 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; } /* ****************************************************************** */ @@ -919,3 +928,28 @@ static ssize_t ppc_rtas_tone_volume_read *ppos += n; return n; } + +#define RMO_READ_BUF_MAX 30 + +/* RTAS Userspace access */ +static ssize_t ppc_rtas_rmo_buf_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + char kbuf[RMO_READ_BUF_MAX]; + int n; + + n = sprintf(kbuf, "%016lx %x\n", rtas_rmo_buf, RTAS_RMOBUF_MAX); + if (n > count) + n = count; + + if (ppos && *ppos != 0) + return 0; + + if (copy_to_user(buf, kbuf, n)) + return -EFAULT; + + if (ppos) + *ppos = n; + + return n; +} diff -puN arch/ppc64/kernel/rtas.c~ppc64-sys_rtas arch/ppc64/kernel/rtas.c --- 25/arch/ppc64/kernel/rtas.c~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtas.c 2004-01-13 23:22:43.000000000 -0800 @@ -29,6 +29,7 @@ #include #include #include +#include struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; @@ -383,6 +384,44 @@ rtas_halt(void) rtas_power_off(); } +unsigned long rtas_rmo_buf = 0; + +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); EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_token); diff -puN arch/ppc64/kernel/syscalls.c~ppc64-sys_rtas arch/ppc64/kernel/syscalls.c --- 25/arch/ppc64/kernel/syscalls.c~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/syscalls.c 2004-01-13 23:22:43.000000000 -0800 @@ -41,6 +41,7 @@ #include #include #include +#include extern unsigned long wall_jiffies; @@ -234,3 +235,6 @@ asmlinkage time_t sys64_time(time_t* tlo return secs; } + +/* Only exists on P-series. */ +cond_syscall(ppc_rtas); diff -puN include/asm-ppc/unistd.h~ppc64-sys_rtas include/asm-ppc/unistd.h --- 25/include/asm-ppc/unistd.h~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/include/asm-ppc/unistd.h 2004-01-13 23:22:43.000000000 -0800 @@ -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 -puN include/asm-ppc64/rtas.h~ppc64-sys_rtas include/asm-ppc64/rtas.h --- 25/include/asm-ppc64/rtas.h~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/include/asm-ppc64/rtas.h 2004-01-13 23:22:43.000000000 -0800 @@ -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_RMOBUF_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"). @@ -189,4 +192,7 @@ static inline int rtas_is_extended_busy( extern spinlock_t rtas_data_buf_lock; extern char rtas_data_buf[RTAS_DATA_BUF_SIZE]; +/* RMO buffer reserved for user-space RTAS use */ +extern unsigned long rtas_rmo_buf; + #endif /* _PPC64_RTAS_H */ diff -puN include/asm-ppc64/unistd.h~ppc64-sys_rtas include/asm-ppc64/unistd.h --- 25/include/asm-ppc64/unistd.h~ppc64-sys_rtas 2004-01-13 23:22:43.000000000 -0800 +++ 25-akpm/include/asm-ppc64/unistd.h 2004-01-13 23:22:43.000000000 -0800 @@ -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 _