From 5a843935ec1193f3c5db38e9227567ca9dae45f2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 18 Jan 2004 18:17:30 -0800 Subject: [PATCH] [PATCH] ppc64: add rtas syscall, from John Rose From: Anton Blanchard 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 --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index cf52e28f93102..4f96a08a635eb 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -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 --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 358d2b54a6cab..338fe76cc8bdc 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -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 --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index d1625b92190bd..0d6d237b66d2a 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -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 --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c index a8c15b61309eb..54641cc6a568e 100644 --- a/arch/ppc64/kernel/rtas-proc.c +++ b/arch/ppc64/kernel/rtas-proc.c @@ -161,6 +161,8 @@ static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, 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_volume_operations = { .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(struct file * file, char * buf, *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 --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c index ed2196cb47093..6746b6ce62130 100644 --- a/arch/ppc64/kernel/rtas.c +++ b/arch/ppc64/kernel/rtas.c @@ -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 --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c index b3b093b4cb37b..deb4b65467116 100644 --- a/arch/ppc64/kernel/syscalls.c +++ b/arch/ppc64/kernel/syscalls.c @@ -41,6 +41,7 @@ #include #include #include +#include extern unsigned long wall_jiffies; @@ -234,3 +235,6 @@ asmlinkage time_t sys64_time(time_t* tloc) return secs; } + +/* Only exists on P-series. */ +cond_syscall(ppc_rtas); diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h index bf1df39dfcecc..9ee8b2e99b509 100644 --- a/include/asm-ppc/unistd.h +++ b/include/asm-ppc/unistd.h @@ -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 --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h index 42a0b484077c8..d9e426161044c 100644 --- a/include/asm-ppc64/rtas.h +++ b/include/asm-ppc64/rtas.h @@ -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(int status) 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 --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h index e856411c64a9f..fe852008db81f 100644 --- a/include/asm-ppc64/unistd.h +++ b/include/asm-ppc64/unistd.h @@ -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 -- 2.53.0