From patchwork Wed Aug 2 16:43:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 109255 Delivered-To: patches@linaro.org Received: by 10.140.101.6 with SMTP id t6csp3003389qge; Wed, 2 Aug 2017 09:44:07 -0700 (PDT) X-Received: by 10.28.87.193 with SMTP id l184mr4035748wmb.121.1501692247868; Wed, 02 Aug 2017 09:44:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501692247; cv=none; d=google.com; s=arc-20160816; b=DjrBKg6ydAZI84X7KnHyLHQa3YvZM48sNNNGz8a5FC+ri9ibdEVypokC6hcrnqfGHa fOJPVRyflFjCgwJY/5QQV5cLk6t/N0Na8DTCSLxpecXMVW+pFWWuh5G8GNVXvQ0qyuun C7Z1aF/F6RvfWBUm4s9qViBMhriac83Wk43dRTimKg1Dd2hweJgFL/XvAW5R7Gr9on48 dW7MFA629Wv88TOXuWA7H05skfCFWdIVXEf5T4VXfJCI0RWzRjmhIt3fHtmuQPPPM1n0 DdlGtM3JyZM1ZuIRrU1THl+BX2s0UUtl8Zm60uDrEC/pB4OCBi0iolBiW73XZPBK3TBY ffBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=bDtLgHuN1uARvu8/XUeKUmQoJ3+0PqDF3HbngR8y97A=; b=0rfVINjUnuWrEHIUQ5pebB+ohNGda5GeJCRNcdt6F4G9CiEpt0IH/3umZD7pGNbbFt K3oARvYtXFknu2E+DJxCidPOCTs/3dfV7SOop4lfrVsVPupFnBS3hZD46NF0bl4t2arA fHNrTla+Lq8SCHkXD2NwxtLzouGaMGhW19R3edHyezH30RPafpMhFnffnUA0XNpTcnkA 1hfM5dXlNDBoLfMHzV9nzad/bhQ9fHFdHsQbJJXslXBUhEnCqRnJUkd4yZu7FRFj39h3 AoyeNf6QLkhB2uBSnJYmNNhwTFrcSTuaGgOm2XC3njcaQlQFcZb2yUTd82Uma76v82US odtg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id 199si3647411wmy.108.2017.08.02.09.44.07 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 09:44:07 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1dcwkh-0003zO-EN; Wed, 02 Aug 2017 17:44:07 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org Subject: [PATCH 10/15] target/arm: Don't use cpsr_write/cpsr_read to transfer M profile XPSR Date: Wed, 2 Aug 2017 17:43:56 +0100 Message-Id: <1501692241-23310-11-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1501692241-23310-1-git-send-email-peter.maydell@linaro.org> References: <1501692241-23310-1-git-send-email-peter.maydell@linaro.org> For M profile the XPSR is a similar but not identical format to the A profile CPSR/SPSR. (For instance the Thumb bit is in a different place.) For guest accesses we make the M profile code go through xpsr_read() and xpsr_write() which handle the different layout. However for migration we use cpsr_read() and cpsr_write() to marshal state into and out of the migration data stream. This is pretty confusing and works more by luck than anything else. Make M profile migration use xpsr_read() and xpsr_write() instead. The most complicated part of this is handling the possibility that the migration source is an older QEMU which hands us a CPSR format value; helpfully we can always tell the two apart. Signed-off-by: Peter Maydell --- target/arm/machine.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) -- 2.7.4 Reviewed-by: Richard Henderson diff --git a/target/arm/machine.c b/target/arm/machine.c index 2fb4b76..3193b00 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -217,21 +217,37 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size, uint32_t val = qemu_get_be32(f); if (arm_feature(env, ARM_FEATURE_M)) { - /* If the I or F bits are set then this is a migration from - * an old QEMU which still stored the M profile FAULTMASK - * and PRIMASK in env->daif. Set v7m.faultmask and v7m.primask - * accordingly, and then clear the bits so they don't confuse - * cpsr_write(). For a new QEMU, the bits here will always be - * clear, and the data is transferred using the - * vmstate_m_faultmask_primask subsection. - */ - if (val & CPSR_F) { - env->v7m.faultmask = 1; - } - if (val & CPSR_I) { - env->v7m.primask = 1; + if (val & XPSR_EXCP) { + /* This is a CPSR format value from an older QEMU. (We can tell + * because values transferred in XPSR format always have zero + * for the EXCP field, and CPSR format will always have bit 4 + * set in CPSR_M.) Rearrange it into XPSR format. The significant + * differences are that the T bit is not in the same place, the + * primask/faultmask info may be in the CPSR I and F bits, and + * we do not want the mode bits. + */ + uint32_t newval = val; + + newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE); + if (val & CPSR_T) { + newval |= XPSR_T; + } + /* If the I or F bits are set then this is a migration from + * an old QEMU which still stored the M profile FAULTMASK + * and PRIMASK in env->daif. For a new QEMU, the data is + * transferred using the vmstate_m_faultmask_primask subsection. + */ + if (val & CPSR_F) { + env->v7m.faultmask = 1; + } + if (val & CPSR_I) { + env->v7m.primask = 1; + } + val = newval; } - val &= ~(CPSR_F | CPSR_I); + /* Ignore the low bits, they are handled by vmstate_m. */ + xpsr_write(env, val, ~XPSR_EXCP); + return 0; } env->aarch64 = ((val & PSTATE_nRW) == 0); @@ -252,7 +268,10 @@ static int put_cpsr(QEMUFile *f, void *opaque, size_t size, CPUARMState *env = &cpu->env; uint32_t val; - if (is_a64(env)) { + if (arm_feature(env, ARM_FEATURE_M)) { + /* The low 9 bits are v7m.exception, which is handled by vmstate_m. */ + val = xpsr_read(env) & ~XPSR_EXCP; + } else if (is_a64(env)) { val = pstate_read(env); } else { val = cpsr_read(env);