Commit 5a843935 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: add rtas syscall, from John Rose

From: Anton Blanchard <anton@samba.org>

Added RTAS syscall.  Reserved lowmem rtas_rmo_buf for userspace use.  Created
"rmo_buffer" proc file to export bounds of rtas_rmo_buf.
parent f408553c
...@@ -1385,3 +1385,4 @@ _GLOBAL(sys_call_table) ...@@ -1385,3 +1385,4 @@ _GLOBAL(sys_call_table)
.long sys_statfs64 .long sys_statfs64
.long sys_fstatfs64 .long sys_fstatfs64
.long ppc_fadvise64_64 .long ppc_fadvise64_64
.long sys_ni_syscall /* 255 - rtas (used on ppc64) */
...@@ -853,6 +853,7 @@ _GLOBAL(sys_call_table32) ...@@ -853,6 +853,7 @@ _GLOBAL(sys_call_table32)
.llong .compat_statfs64 .llong .compat_statfs64
.llong .compat_fstatfs64 .llong .compat_fstatfs64
.llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */ .llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */
.llong .ppc_rtas /* 255 */
.balign 8 .balign 8
_GLOBAL(sys_call_table) _GLOBAL(sys_call_table)
...@@ -1111,3 +1112,4 @@ _GLOBAL(sys_call_table) ...@@ -1111,3 +1112,4 @@ _GLOBAL(sys_call_table)
.llong .sys_statfs64 .llong .sys_statfs64
.llong .sys_fstatfs64 .llong .sys_fstatfs64
.llong .sys_ni_syscall /* 32bit only fadvise64_64 */ .llong .sys_ni_syscall /* 32bit only fadvise64_64 */
.llong .ppc_rtas /* 255 */
...@@ -613,6 +613,9 @@ prom_instantiate_rtas(void) ...@@ -613,6 +613,9 @@ prom_instantiate_rtas(void)
_rtas->base) >= 0) { _rtas->base) >= 0) {
_rtas->entry = (long)_prom->args.rets[1]; _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) { if (_rtas->entry <= 0) {
......
...@@ -161,6 +161,8 @@ static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, ...@@ -161,6 +161,8 @@ static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
size_t count, loff_t *ppos); size_t count, loff_t *ppos);
static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
size_t count, loff_t *ppos); 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 = { struct file_operations ppc_rtas_poweron_operations = {
.read = ppc_rtas_poweron_read, .read = ppc_rtas_poweron_read,
...@@ -185,6 +187,10 @@ struct file_operations ppc_rtas_tone_volume_operations = { ...@@ -185,6 +187,10 @@ struct file_operations ppc_rtas_tone_volume_operations = {
.write = ppc_rtas_tone_volume_write .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_find_all_sensors (void);
int ppc_rtas_process_sensor(struct individual_sensor s, int state, int ppc_rtas_process_sensor(struct individual_sensor s, int state,
int error, char * buf); int error, char * buf);
...@@ -233,6 +239,9 @@ void proc_rtas_init(void) ...@@ -233,6 +239,9 @@ void proc_rtas_init(void)
entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas);
if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations; 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, ...@@ -919,3 +928,28 @@ static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
*ppos += n; *ppos += n;
return 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;
}
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/udbg.h> #include <asm/udbg.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/uaccess.h>
struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; struct flash_block_list_header rtas_firmware_flash_list = {0, 0};
...@@ -383,6 +384,44 @@ rtas_halt(void) ...@@ -383,6 +384,44 @@ rtas_halt(void)
rtas_power_off(); 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(proc_ppc64);
EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_firmware_flash_list);
EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_token);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <asm/ipc.h> #include <asm/ipc.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/unistd.h>
extern unsigned long wall_jiffies; extern unsigned long wall_jiffies;
...@@ -234,3 +235,6 @@ asmlinkage time_t sys64_time(time_t* tloc) ...@@ -234,3 +235,6 @@ asmlinkage time_t sys64_time(time_t* tloc)
return secs; return secs;
} }
/* Only exists on P-series. */
cond_syscall(ppc_rtas);
...@@ -259,8 +259,9 @@ ...@@ -259,8 +259,9 @@
#define __NR_statfs64 252 #define __NR_statfs64 252
#define __NR_fstatfs64 253 #define __NR_fstatfs64 253
#define __NR_fadvise64_64 254 #define __NR_fadvise64_64 254
#define __NR_rtas 255
#define __NR_syscalls 255 #define __NR_syscalls 256
#define __NR(n) #n #define __NR(n) #n
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#define RTAS_UNKNOWN_SERVICE (-1) #define RTAS_UNKNOWN_SERVICE (-1)
#define RTAS_INSTANTIATE_MAX (1UL<<30) /* Don't instantiate rtas at/above this value */ #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 * In general to call RTAS use rtas_token("string") to lookup
* an RTAS token for the given string (e.g. "event-scan"). * an RTAS token for the given string (e.g. "event-scan").
...@@ -189,4 +192,7 @@ static inline int rtas_is_extended_busy(int status) ...@@ -189,4 +192,7 @@ static inline int rtas_is_extended_busy(int status)
extern spinlock_t rtas_data_buf_lock; extern spinlock_t rtas_data_buf_lock;
extern char rtas_data_buf[RTAS_DATA_BUF_SIZE]; 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 */ #endif /* _PPC64_RTAS_H */
...@@ -264,8 +264,10 @@ ...@@ -264,8 +264,10 @@
#define __NR_utimes 251 #define __NR_utimes 251
#define __NR_statfs64 252 #define __NR_statfs64 252
#define __NR_fstatfs64 253 #define __NR_fstatfs64 253
#define __NR_fadvise64_64 254
#define __NR_rtas 255
#define __NR_syscalls 254 #define __NR_syscalls 256
#ifdef __KERNEL__ #ifdef __KERNEL__
#define NR_syscalls __NR_syscalls #define NR_syscalls __NR_syscalls
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment