From patchwork Tue Mar 18 09:19:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alvise Rigo X-Patchwork-Id: 331361 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 2DA0C2C00CB for ; Tue, 18 Mar 2014 20:22:43 +1100 (EST) Received: from localhost ([::1]:34150 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WPqEK-00025P-LM for incoming@patchwork.ozlabs.org; Tue, 18 Mar 2014 05:22:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34475) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WPqBt-0005Uj-8A for qemu-devel@nongnu.org; Tue, 18 Mar 2014 05:20:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WPqBm-0001Ot-4n for qemu-devel@nongnu.org; Tue, 18 Mar 2014 05:20:09 -0400 Received: from mail-wi0-f178.google.com ([209.85.212.178]:37470) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WPqBl-0001M9-U6 for qemu-devel@nongnu.org; Tue, 18 Mar 2014 05:20:02 -0400 Received: by mail-wi0-f178.google.com with SMTP id bs8so2480692wib.5 for ; Tue, 18 Mar 2014 02:20:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vPTJGVrMHCJYrz45EZTd9Ln4MKWs8FwTNumZTzu+80o=; b=LSAN0VIBHwyX0JbBlkx4mNx4vd3jGubaHOlBjdpS7ugjX3lphJToWCGQbOBPO8bLF0 h3VTcQ9UJirVmzVG75508b5VaM/+8gIT/DAxD3PT7Pky9K5LD8tfmPYXaqmBOwipcYwJ inCtUBHMzdc2WQirHQXvJUw6u32C9wL/X9Ap2wy+jJ/LCRAdkYRGyHmUMgbzZgPFmfY2 TB2kpr4Gji0CTL+VhEQJkcUseXOG5VAdn9lK4F3O3SKhS9zoN7A3zt7l5sXmzufLUp98 pI8y2pfqgPPDfO+6+Hqk3WV9f2izAK6XPegc70H9g+B0D8nQBGoN/PAV761ItZlWjvaJ lb2A== X-Gm-Message-State: ALoCoQkucPTuEqsJEqDKB5zx0nKZY2eO2jddqGiNAnls8fiFLhEEXHcu9io2I9oGlY1Okf67ug65 X-Received: by 10.180.210.171 with SMTP id mv11mr13386623wic.44.1395134401120; Tue, 18 Mar 2014 02:20:01 -0700 (PDT) Received: from localhost.localdomain (AGrenoble-651-1-406-154.w90-52.abo.wanadoo.fr. [90.52.42.154]) by mx.google.com with ESMTPSA id ee5sm32853410wib.8.2014.03.18.02.19.59 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Mar 2014 02:20:00 -0700 (PDT) From: Alvise Rigo To: qemu-devel@nongnu.org Date: Tue, 18 Mar 2014 10:19:45 +0100 Message-Id: <1395134389-25778-4-git-send-email-a.rigo@virtualopensystems.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1395134389-25778-1-git-send-email-a.rigo@virtualopensystems.com> References: <1395134389-25778-1-git-send-email-a.rigo@virtualopensystems.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.212.178 Cc: Peter Maydell , tech@virtualopensystems.com, Alvise Rigo Subject: [Qemu-devel] [PATCH v2 3/7] target-arm: Add a way to mask some X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org One of the issues blocking the migration from KVM to TCG is that the former processor reads the coprocessors values directly from the underlying hardware. TCG however, for the way it emulates some registers, is not able to verify the incoming values, failing the migration. Add a mask to the ARMCPRegInfo structure to exclude the bits not supported of the incoming registers values. In case of an outgoing migration, the unsupported data is retrieved from the cpreg_vmstate array. Signed-off-by: Alvise Rigo --- target-arm/cpu.h | 1 + target-arm/helper.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 0a7edfe..adcfa42 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -955,6 +955,7 @@ struct ARMCPRegInfo { * fieldoffset is 0 then no reset will be done. */ CPResetFn *resetfn; + uint64_t attr_mask; }; /* Macros which are lvalues for the field in CPUARMState for the diff --git a/target-arm/helper.c b/target-arm/helper.c index 2791dac..30973cc 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -166,6 +166,50 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, } } +static bool cpreg_find_vmstate_val(ARMCPU *cpu, uint64_t id, + const uint64_t *val) +{ + int i; + + for (i = 0; i < cpu->cpreg_vmstate_array_len; i++) { + if (cpu->cpreg_vmstate_indexes[i] == id) { + val = &cpu->cpreg_vmstate_values[i]; + return true; + } + } + + return false; +} + +static uint64_t read_incoming_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *ri, + uint64_t reg_id) +{ + CPUARMState *env = &cpu->env; + uint64_t val = read_raw_cp_reg(env, ri); + const uint64_t *inc_val = NULL; + + if (cpreg_find_vmstate_val(cpu, reg_id, inc_val) && ri->attr_mask) { + val &= ri->attr_mask; + val |= (*inc_val & ~ri->attr_mask); + } + + return val; +} + +static void write_incoming_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t *v) +{ + if (ri->attr_mask) { + *v &= ri->attr_mask; + if (ri->type & ARM_CP_CONST) { + /* verify equality only of the supported values */ + *v |= ri->resetvalue & ~ri->attr_mask; + } + } + + write_raw_cp_reg(env, ri, *v); +} + bool write_cpustate_to_list(ARMCPU *cpu) { /* Write the coprocessor state from cpu->env to the (index,value) list. */ @@ -184,7 +228,8 @@ bool write_cpustate_to_list(ARMCPU *cpu) if (ri->type & ARM_CP_NO_MIGRATE) { continue; } - cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri); + cpu->cpreg_values[i] = read_incoming_cp_reg(cpu, ri, + cpu->cpreg_indexes[i]); } return ok; } @@ -211,7 +256,7 @@ bool write_list_to_cpustate(ARMCPU *cpu) * (to catch read-only registers and partially read-only * registers where the incoming migration value doesn't match) */ - write_raw_cp_reg(&cpu->env, ri, v); + write_incoming_cp_reg(&cpu->env, ri, &v); if (read_raw_cp_reg(&cpu->env, ri) != v) { ok = false; }