From patchwork Tue Feb 20 13:26:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hugo Landau X-Patchwork-Id: 875539 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=devever.net header.i=@devever.net header.b="U+EadEuM"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zm1tK5h6dz9s01 for ; Wed, 21 Feb 2018 00:39:04 +1100 (AEDT) Received: from localhost ([::1]:55580 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eo88M-0002ek-9W for incoming@patchwork.ozlabs.org; Tue, 20 Feb 2018 08:39:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42556) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eo7wt-00081i-8R for qemu-devel@nongnu.org; Tue, 20 Feb 2018 08:27:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eo7wp-0006on-WB for qemu-devel@nongnu.org; Tue, 20 Feb 2018 08:27:11 -0500 Received: from umbriel.devever.net ([149.202.51.241]:34574) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eo7wp-0006nD-KH for qemu-devel@nongnu.org; Tue, 20 Feb 2018 08:27:07 -0500 Received: from localhost (localhost [127.0.0.1]) by umbriel.devever.net (Postfix) with ESMTP id ECEFE1C585; Tue, 20 Feb 2018 14:27:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=devever.net; h= x-mailer:message-id:date:date:subject:subject:from:from:received :received; s=mimas; t=1519133224; x=1537322585; bh=OiKzn9Zl2M4fY qQqYHf9ghSDsSv1/dbC8f3EImQm8hA=; b=U+EadEuMDJgBSpeH6W65YltK3CGkF 4OJ/+A/BU9Q1hGVRC32ys6NAZEtZFFy/l+FTwo+X5QQ+uiwA/9goMpOMJVqtWef0 MKDyVemBurHJuwVDKUzwMBw877mw0gRkbg8urjwgjgwN1tRgSVsIJiFwS9R5k2a5 aIihpqojk1Wva7hpSVbFCDTeOy6HxP/50mEQKkahpAM1nUrAl8SYqLj5D7K2IRHN IAWUQ4xzmum0VnXRVDK2NrVK4nJ+MKcQIRAlUQvuTXsOhj5c6JQPJVMUVGiBsbZy dIIo24KNabaEK2IKCbg0PFQHYtUSQAvC14TkPK85yIK0heeMb1kJhwGrw== Received: from umbriel.devever.net ([127.0.0.1]) by localhost (umbriel.devever.net [127.0.0.1]) (amavisd-new, port 10026) with LMTP id 4Ydb5WqpyrjI; Tue, 20 Feb 2018 14:27:04 +0100 (CET) Received: from localhost.localdomain (localhost [127.0.0.1]) by umbriel.devever.net (Postfix) with ESMTP id A5B931C386; Tue, 20 Feb 2018 14:27:04 +0100 (CET) From: Hugo Landau To: qemu-devel@nongnu.org, clg@kaod.org Date: Tue, 20 Feb 2018 13:26:27 +0000 Message-Id: <20180220132627.4163-1-hlandau@devever.net> X-Mailer: git-send-email 2.15.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 149.202.51.241 X-Mailman-Approved-At: Tue, 20 Feb 2018 08:38:29 -0500 Subject: [Qemu-devel] [PATCH] Fix ast2500 protection register emulation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hugo Landau Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Some register blocks of the ast2500 are protected by protection key registers which require the right magic value to be written to those registers to allow those registers to be mutated. Register manuals indicate that writing the correct magic value to these registers should cause subsequent reads from those values to return 1, and writing any other value should cause subsequent reads to return 0. Previously, qemu implemented these registers incorrectly: the registers were handled as simple memory, meaning that writing some value x to a protection key register would result in subsequent reads from that register returning the same value x. The protection was implemented by ensuring that the current value of that register equaled the magic value. This modifies qemu to have the correct behaviour: attempts to write to a ast2500 protection register results in a transition to 1 or 0 depending on whether the written value is the correct magic. The protection logic is updated to ensure that the value of the register is nonzero. This bug caused deadlocks with u-boot HEAD: when u-boot is done with a protectable register block, it attempts to lock it by writing the bitwise inverse of the correct magic value, and then spinning forever until the register reads as zero. Since qemu implemented writes to these registers as ordinary memory writes, writing the inverse of the magic value resulted in subsequent reads returning that value, leading to u-boot spinning forever. Signed-off-by: Hugo Landau Reviewed-by: Cédric Le Goater Acked-by: Andrew Jeffery --- hw/misc/aspeed_scu.c | 6 +++++- hw/misc/aspeed_sdmc.c | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 74537ce975..5e6d5744ee 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -191,7 +191,7 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, } if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 && - s->regs[PROT_KEY] != ASPEED_SCU_PROT_KEY) { + !s->regs[PROT_KEY]) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__); return; } @@ -199,6 +199,10 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, trace_aspeed_scu_write(offset, size, data); switch (reg) { + case PROT_KEY: + s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0; + return; + case FREQ_CNTR_EVAL: case VGA_SCRATCH1 ... VGA_SCRATCH8: case RNG_DATA: diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index f0b3053fae..265171ee42 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -110,7 +110,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, return; } - if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) { + if (addr == R_PROT) { + s->regs[addr] = (data == PROT_KEY_UNLOCK) ? 1 : 0; + return; + } + + if (!s->regs[R_PROT]) { qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__); return; } @@ -123,6 +128,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data, data &= ~ASPEED_SDMC_READONLY_MASK; break; case AST2500_A0_SILICON_REV: + case AST2500_A1_SILICON_REV: data &= ~ASPEED_SDMC_AST2500_READONLY_MASK; break; default: