From patchwork Wed May 31 11:15:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 769071 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3wd7FC0Tjfz9s8H for ; Wed, 31 May 2017 21:15:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751067AbdEaLPl (ORCPT ); Wed, 31 May 2017 07:15:41 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59242 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751025AbdEaLPl (ORCPT ); Wed, 31 May 2017 07:15:41 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A604661BAA; Wed, 31 May 2017 11:15:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A604661BAA Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com A604661BAA Received: from thh440s.str.redhat.com (dhcp-192-189.str.redhat.com [10.33.192.189]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7E32B7D953; Wed, 31 May 2017 11:15:39 +0000 (UTC) From: Thomas Huth To: kvm@vger.kernel.org Cc: kvm-ppc@vger.kernel.org, Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= Subject: [kvm-unit-tests PATCH] powerpc: Rework the rtas_token() function Date: Wed, 31 May 2017 13:15:38 +0200 Message-Id: <1496229338-7113-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 31 May 2017 11:15:40 +0000 (UTC) Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org 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: Thomas Huth Reviewed-by: Andrew Jones Reviewed-by: Laurent Vivier --- lib/powerpc/asm/rtas.h | 2 +- lib/powerpc/rtas.c | 30 ++++++++++++++++++++++-------- lib/powerpc/smp.c | 11 ++++++----- powerpc/rtas.c | 24 +++++++++++++----------- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/lib/powerpc/asm/rtas.h b/lib/powerpc/asm/rtas.h index 9012a1e..6fb407a 100644 --- a/lib/powerpc/asm/rtas.h +++ b/lib/powerpc/asm/rtas.h @@ -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); diff --git a/lib/powerpc/rtas.c b/lib/powerpc/rtas.c index 3407e25..2e7e0da 100644 --- a/lib/powerpc/rtas.c +++ b/lib/powerpc/rtas.c @@ -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); } diff --git a/lib/powerpc/smp.c b/lib/powerpc/smp.c index e18894b..afe4361 100644 --- a/lib/powerpc/smp.c +++ b/lib/powerpc/smp.c @@ -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) { diff --git a/powerpc/rtas.c b/powerpc/rtas.c index 1b1e9c7..5d43f33 100644 --- a/powerpc/rtas.c +++ b/powerpc/rtas.c @@ -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", >od_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++;