Commit 2565dce1 authored by Thomas Huth's avatar Thomas Huth Committed by Paolo Bonzini
Browse files

powerpc: Rework the rtas_token() function



RTAS tokens can have any value, also 0xffffffff is theoretically
allowed (which is currently used for the RTAS_UNKNOWN_SERVICE error
code). Thus we should not mix error codes and tokens in the return
value here and return the token value via a pointer parameter
instead.

This patch also adds a check to rtas_token() to test whether the device
tree is available at all. This fixes a possible endless loop that
happens without device tree, spamming the console with "rtas_node:
/rtas: FDT_ERR_BADMAGIC" messages: Somewhere the code calls abort()
due to the missing device tree, and abort() calls exit() which in
turn tries to shut down the VM with rtas_power_off(). rtas_power_off()
needs the device tree again to look up the right RTAS token, where we
then end up in the next iteration.
Signed-off-by: default avatarThomas Huth <thuth@redhat.com>
Message-Id: <1496229338-7113-1-git-send-email-thuth@redhat.com>
Reviewed-by: Andrew Jones's avatarAndrew Jones <drjones@redhat.com>
Reviewed-by: default avatarLaurent Vivier <lvivier@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 499e63ff
......@@ -21,7 +21,7 @@ struct rtas_args {
};
extern void rtas_init(void);
extern int rtas_token(const char *service);
extern int rtas_token(const char *service, uint32_t *token);
extern int rtas_call(int token, int nargs, int nret, int *outputs, ...);
extern void rtas_power_off(void);
......
......@@ -69,17 +69,22 @@ void rtas_init(void)
}
}
int rtas_token(const char *service)
int rtas_token(const char *service, uint32_t *token)
{
const struct fdt_property *prop;
u32 *token;
u32 *data;
if (!dt_available())
return RTAS_UNKNOWN_SERVICE;
prop = fdt_get_property(dt_fdt(), rtas_node(), service, NULL);
if (prop) {
token = (u32 *)prop->data;
return fdt32_to_cpu(*token);
}
return RTAS_UNKNOWN_SERVICE;
if (!prop)
return RTAS_UNKNOWN_SERVICE;
data = (u32 *)prop->data;
*token = fdt32_to_cpu(*data);
return 0;
}
int rtas_call(int token, int nargs, int nret, int *outputs, ...)
......@@ -116,6 +121,15 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
void rtas_power_off(void)
{
int ret = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
uint32_t token;
int ret;
ret = rtas_token("power-off", &token);
if (ret) {
puts("RTAS power-off not available\n");
return;
}
ret = rtas_call(token, 2, 1, NULL, -1, -1);
printf("RTAS power-off returned %d\n", ret);
}
......@@ -27,12 +27,13 @@ struct secondary_entry_data {
*/
int start_thread(int cpu_id, secondary_entry_fn entry, uint32_t r3)
{
int query_token, start_token, outputs[1], ret;
uint32_t query_token, start_token;
int outputs[1], ret;
query_token = rtas_token("query-cpu-stopped-state");
start_token = rtas_token("start-cpu");
assert(query_token != RTAS_UNKNOWN_SERVICE &&
start_token != RTAS_UNKNOWN_SERVICE);
ret = rtas_token("query-cpu-stopped-state", &query_token);
assert(ret == 0);
ret = rtas_token("start-cpu", &start_token);
assert(ret == 0);
ret = rtas_call(query_token, 1, 2, outputs, cpu_id);
if (ret) {
......
......@@ -39,14 +39,14 @@ static unsigned long mktime(int year, int month, int day,
static void check_get_time_of_day(unsigned long start)
{
int token;
uint32_t token;
int ret;
int now[8];
unsigned long t1, t2, count;
token = rtas_token("get-time-of-day");
report("token available", token != RTAS_UNKNOWN_SERVICE);
if (token == RTAS_UNKNOWN_SERVICE)
ret = rtas_token("get-time-of-day", &token);
report("token available", ret == 0);
if (ret)
return;
ret = rtas_call(token, 0, 8, now);
......@@ -74,23 +74,25 @@ static void check_get_time_of_day(unsigned long start)
static void check_set_time_of_day(void)
{
int token;
uint32_t stod_token, gtod_token;
int ret;
int date[8];
unsigned long t1, t2, count;
token = rtas_token("set-time-of-day");
report("token available", token != RTAS_UNKNOWN_SERVICE);
if (token == RTAS_UNKNOWN_SERVICE)
ret = rtas_token("set-time-of-day", &stod_token);
report("token available", ret == 0);
if (ret)
return;
/* 23:59:59 28/2/2000 */
ret = rtas_call(token, 7, 1, NULL, 2000, 2, 28, 23, 59, 59);
ret = rtas_call(stod_token, 7, 1, NULL, 2000, 2, 28, 23, 59, 59);
report("execution", ret == 0);
/* check it has worked */
ret = rtas_call(rtas_token("get-time-of-day"), 0, 8, date);
ret = rtas_token("get-time-of-day", &gtod_token);
assert(ret == 0);
ret = rtas_call(gtod_token, 0, 8, date);
report("re-read", ret == 0);
t1 = mktime(2000, 2, 28, 23, 59, 59);
t2 = mktime(date[0], date[1], date[2],
......@@ -100,7 +102,7 @@ static void check_set_time_of_day(void)
/* check it is running */
count = 0;
do {
ret = rtas_call(rtas_token("get-time-of-day"), 0, 8, date);
ret = rtas_call(gtod_token, 0, 8, date);
t2 = mktime(date[0], date[1], date[2],
date[3], date[4], date[5]);
count++;
......
Supports Markdown
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