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)
.long sys_statfs64
.long sys_fstatfs64
.long ppc_fadvise64_64
.long sys_ni_syscall /* 255 - rtas (used on ppc64) */
......@@ -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 */
......@@ -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) {
......
......@@ -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;
}
......@@ -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};
......@@ -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);
......
......@@ -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 @@ asmlinkage time_t sys64_time(time_t* tloc)
return secs;
}
/* Only exists on P-series. */
cond_syscall(ppc_rtas);
......@@ -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
......
......@@ -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 */
......@@ -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
......
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