@@ -20,7 +20,7 @@
#define RTAS_UNKNOWN_SERVICE (-1)
#define RTAS_INSTANTIATE_MAX (1ULL<<30) /* Don't instantiate rtas at/above this value */
-/* Buffer size for ppc_rtas system call. */
+/* Buffer size for ppc_firmware system call. */
#define RTAS_RMOBUF_MAX (64 * 1024)
/* RTAS return status codes */
@@ -427,9 +427,17 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
/* Not the best place to put pSeries_coalesce_init, will be fixed when we
* move some of the rtas suspend-me stuff to pseries */
extern void pSeries_coalesce_init(void);
+extern int ppc_call_rtas(struct rtas_args *args);
#else
static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
static inline void pSeries_coalesce_init(void) { }
+static inline int ppc_call_rtas(struct rtas_args *args) { return -ENXIO; }
+#endif
+
+#ifdef CONFIG_PPC_POWERNV
+extern int ppc_call_opal(struct rtas_args *args);
+#else
+static inline int ppc_call_opal(struct rtas_arts *args) { return -ENXIO; }
#endif
extern int call_rtas(const char *, int, int, unsigned long *, ...);
@@ -15,7 +15,7 @@ asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
asmlinkage long ppc64_personality(unsigned long personality);
-asmlinkage int ppc_rtas(struct rtas_args __user *uargs);
+asmlinkage int ppc_firmware(struct rtas_args __user *uargs);
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_SYSCALLS_H */
@@ -259,7 +259,7 @@ COMPAT_SYS_SPU(utimes)
COMPAT_SYS_SPU(statfs64)
COMPAT_SYS_SPU(fstatfs64)
SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
-PPC_SYS_SPU(rtas)
+PPC_SYS_SPU(firmware)
OLDSYS(debug_setcontext)
SYSCALL(ni_syscall)
COMPAT_SYS(migrate_pages)
@@ -273,7 +273,7 @@
#ifndef __powerpc64__
#define __NR_fadvise64_64 254
#endif
-#define __NR_rtas 255
+#define __NR_firmware 255
#define __NR_sys_debug_setcontext 256
/* Number 257 is reserved for vserver */
#define __NR_migrate_pages 258
@@ -1017,59 +1017,32 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
}
/* We assume to be passed big endian arguments */
-asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
+int ppc_call_rtas(struct rtas_args *args)
{
- struct rtas_args args;
unsigned long flags;
char *buff_copy, *errbuf = NULL;
- int nargs, nret, token;
int rc;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
- return -EFAULT;
-
- nargs = be32_to_cpu(args.nargs);
- nret = be32_to_cpu(args.nret);
- token = be32_to_cpu(args.token);
-
- if (nargs > ARRAY_SIZE(args.args)
- || nret > ARRAY_SIZE(args.args)
- || nargs + nret > ARRAY_SIZE(args.args))
- return -EINVAL;
-
- /* Copy in args. */
- if (copy_from_user(args.args, uargs->args,
- nargs * sizeof(rtas_arg_t)) != 0)
- return -EFAULT;
-
- if (token == RTAS_UNKNOWN_SERVICE)
- return -EINVAL;
-
- args.rets = &args.args[nargs];
- memset(args.rets, 0, nret * sizeof(rtas_arg_t));
-
/* Need to handle ibm,suspend_me call specially */
- if (token == ibm_suspend_me_token) {
- rc = rtas_ibm_suspend_me(&args);
+ if (args->token == ibm_suspend_me_token) {
+ rc = rtas_ibm_suspend_me(args);
if (rc)
return rc;
- goto copy_return;
+ goto out;
}
buff_copy = get_errorlog_buffer();
flags = lock_rtas();
-
- rtas.args = args;
+ rtas.args = *args;
enter_rtas(__pa(&rtas.args));
- args = rtas.args;
+ *args = rtas.args;
- /* A -1 return code indicates that the last command couldn't
- be completed due to a hardware error. */
- if (be32_to_cpu(args.rets[0]) == -1)
+ /*
+ * A -1 return code indicates that the last command couldn't
+ * be completed due to a hardware error.
+ */
+ if (be32_to_cpu(args->rets[0]) == -1)
errbuf = __fetch_rtas_last_error(buff_copy);
unlock_rtas(flags);
@@ -1080,13 +1053,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
kfree(buff_copy);
}
- copy_return:
- /* Copy out args. */
- if (copy_to_user(uargs->args + nargs,
- args.args + nargs,
- nret * sizeof(rtas_arg_t)) != 0)
- return -EFAULT;
-
+out:
return 0;
}
@@ -40,6 +40,56 @@
#include <asm/syscalls.h>
#include <asm/time.h>
#include <asm/unistd.h>
+#include <asm/machdep.h>
+#include <asm/rtas.h>
+
+asmlinkage int ppc_firmware(struct rtas_args __user *uargs)
+{
+ int rc;
+ int nargs, nret, token;
+ struct rtas_args args;
+
+ /* Copy over common header */
+ if (copy_from_user(&args, uargs, 3 * sizeof(u32)))
+ return -EFAULT;
+ nargs = be32_to_cpu(args.nargs);
+ nret = be32_to_cpu(args.nret);
+ token = be32_to_cpu(args.token);
+
+ /* Parameter overflow ? */
+ if (nargs > ARRAY_SIZE(args.args)
+ || nret > ARRAY_SIZE(args.args)
+ || nargs + nret > ARRAY_SIZE(args.args))
+ return -EINVAL;
+
+ /* Copy over all arguments */
+ if (copy_from_user(args.args, uargs->args,
+ nargs * sizeof(rtas_arg_t)))
+ return -EFAULT;
+
+ /* Invalid token ? */
+ if (token == RTAS_UNKNOWN_SERVICE)
+ return -EINVAL;
+
+ /* Clean out return values */
+ args.rets = &args.args[nargs];
+ memset(args.rets, 0, nret * sizeof(rtas_arg_t));
+
+ /* Route to correct platform */
+ if (machine_is(pseries))
+ rc = ppc_call_rtas(&args);
+ else if (machine_is(powernv))
+ rc = ppc_call_opal(&args);
+ else
+ return -ENXIO;
+
+ /* Copy result to user space */
+ if (copy_to_user(uargs->args + nargs, args.args + nargs,
+ nret * sizeof(rtas_arg_t)))
+ return -EFAULT;
+
+ return rc;
+}
static inline unsigned long do_mmap2(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
@@ -25,6 +25,7 @@
#include <asm/opal.h>
#include <asm/firmware.h>
#include <asm/mce.h>
+#include <asm/rtas.h>
#include "powernv.h"
@@ -701,3 +702,9 @@ void opal_free_sg_list(struct opal_sg_list *sg)
sg = NULL;
}
}
+
+/* Extend it later */
+int ppc_call_opal(struct rtas_args *args)
+{
+ return 0;
+}
@@ -159,7 +159,7 @@ cond_syscall(sys_pciconfig_read);
cond_syscall(sys_pciconfig_write);
cond_syscall(sys_pciconfig_iobase);
cond_syscall(compat_sys_s390_ipc);
-cond_syscall(ppc_rtas);
+cond_syscall(ppc_firmware);
cond_syscall(sys_spu_run);
cond_syscall(sys_spu_create);
cond_syscall(sys_subpage_prot);