diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 3c1887351c71..60cd528806c1 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -59,6 +59,7 @@ struct rtas_t {
arch_spinlock_t lock;
struct rtas_args args;
struct device_node *dev; /* virtual address pointer */
+ bool hcall;
};
struct rtas_suspend_me_data {diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 5faf0a64c92b..0651291ab5ff 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -49,6 +49,14 @@ struct rtas_t rtas = {
};
EXPORT_SYMBOL(rtas);
+static void __enter_rtas(unsigned long pa)
+{
+ if (rtas.hcall)
+ plpar_hcall_norets(H_RTAS, pa);
+ else
+ enter_rtas(pa);
+}
+
DEFINE_SPINLOCK(rtas_data_buf_lock);
EXPORT_SYMBOL(rtas_data_buf_lock);
@@ -95,9 +103,6 @@ static void call_rtas_display_status(unsigned char c)
{
unsigned long s;
- if (!rtas.base)
- return;
-
s = lock_rtas();
rtas_call_unlocked(&rtas.args, 10, 1, 1, NULL, c);
unlock_rtas(s);@@ -145,9 +150,6 @@ static void udbg_rtascon_putc(char c)
{
int tries;
- if (!rtas.base)
- return;
-
/* Add CRs before LFs */
if (c == '\n')
udbg_rtascon_putc('\r');@@ -164,9 +166,6 @@ static int udbg_rtascon_getc_poll(void)
{
int c;
- if (!rtas.base)
- return -1;
-
if (rtas_call(rtas_getchar_token, 0, 2, &c))
return -1;
@@ -205,9 +204,6 @@ void rtas_progress(char *s, unsigned short hex)
static int current_line;
static int pending_newline = 0; /* did last write end with unprinted newline? */
- if (!rtas.base)
- return;
-
if (display_width == 0) {
display_width = 0x10;
if ((root = of_find_node_by_path("/rtas"))) {@@ -382,7 +378,7 @@ static char *__fetch_rtas_last_error(char *altbuf)
save_args = rtas.args;
rtas.args = err_args;
- enter_rtas(__pa(&rtas.args));
+ __enter_rtas(__pa(&rtas.args));
err_args = rtas.args;
rtas.args = save_args;
@@ -428,7 +424,7 @@ va_rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret,
for (i = 0; i < nret; ++i)
args->rets[i] = 0;
- enter_rtas(__pa(args));
+ __enter_rtas(__pa(args));
}
void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret, ...)
@@ -449,7 +445,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
char *buff_copy = NULL;
int ret;
- if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
+ if (token == RTAS_UNKNOWN_SERVICE)
return -1;
s = lock_rtas();
@@ -1064,9 +1060,6 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (!rtas.entry)
- return -EINVAL;
-
if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
return -EFAULT;
@@ -1115,7 +1108,7 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
flags = lock_rtas();
rtas.args = args;
- enter_rtas(__pa(&rtas.args));
+ __enter_rtas(__pa(&rtas.args));
args = rtas.args;
/* A -1 return code indicates that the last command couldn't
@@ -1149,8 +1142,8 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
void __init rtas_initialize(void)
{
unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
- u32 base, size, entry;
- int no_base, no_size, no_entry;
+ u32 base = 0, size = 0, entry = 0, do_h_rtas = 0;
+ int no_base, no_size, no_entry, ret;
/* Get RTAS dev node and fill up our "rtas" structure with infos
* about it.@@ -1161,17 +1154,15 @@ void __init rtas_initialize(void)
no_base = of_property_read_u32(rtas.dev, "linux,rtas-base", &base);
no_size = of_property_read_u32(rtas.dev, "rtas-size", &size);
- if (no_base || no_size) {
- of_node_put(rtas.dev);
- rtas.dev = NULL;
- return;
- }
rtas.base = base;
rtas.size = size;
no_entry = of_property_read_u32(rtas.dev, "linux,rtas-entry", &entry);
rtas.entry = no_entry ? rtas.base : entry;
+ ret = of_property_read_u32(of_chosen, "qemu,h_rtas", &do_h_rtas);
+ rtas.hcall = !ret && do_h_rtas;
+
/* If RTAS was found, allocate the RMO buffer for it and look for
* the stop-self token if any
*/@@ -1208,6 +1199,10 @@ int __init early_init_dt_scan_rtas(unsigned long node,
rtas.base = *basep;
rtas.entry = *entryp;
rtas.size = *sizep;
+ } else {
+ rtas.base = 0;
+ rtas.entry = 0;
+ rtas.size = 0;
}
#ifdef CONFIG_UDBG_RTAS_CONSOLE--
2.17.1