From patchwork Tue Dec 18 18:04:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 154173 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4015088ljp; Tue, 18 Dec 2018 10:06:29 -0800 (PST) X-Google-Smtp-Source: AFSGD/UKC2/3LH8xmgcYe/tPi94GWjPtf85L8PWeI8X1wvfppJi7hGwX9xngwX9QyTNggSll3Iyi X-Received: by 2002:a81:ac56:: with SMTP id z22mr19786269ywj.40.1545156389443; Tue, 18 Dec 2018 10:06:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545156389; cv=none; d=google.com; s=arc-20160816; b=tnJqcjp4PKYxPgQPClJRxBGWG9QWkY2au5nZJtn6or2jcFVQxo/ZZgRrsA5XN5nLjE f0Kzs3pMec1uGjlLxLmgM6x/p0hSQ+ob98I4AmGaFt6/pjJJdgurFTy6Voe0kFpO1Dt/ 7ZzlAprsgH/wQ2i6dHKwyZ9JcuUF2MX9qA74n2+H+h1+QvIg0/zefOV3KVrvfDDTZM4d MzuKVxFxsUWxzkNFbMKV4xpNKitMeI/mV4bryYxWvm0rLuwBlN+KvASbHGw+gDvTnqA7 JaQRgY+SvRoTJcariZ8WqGBzqrgDv0Wzn+kxw7c0eXTjAl9Zwb/7hif6I9FMs5hBb//J mRYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-unsubscribe:list-id :precedence:subject:references:in-reply-to:message-id:date:to:from; bh=1QaCdM9HmcZGKuPgaRPQTCc2fZakpKUrGXbtyarw0Rs=; b=U0Iaww/2WxfIzDWEm4pRObP0Fl4Op9fT9XZYt6SzNKtBZCzwa7KS31kCTeG+vYLV9x Ob2pZ/heyQ3IOS0qfoqOyJV448PgQHWODapS+mAO/4L/sf8/9vssMFVx0QwHsjrEEclq jlYdPiXWysJdETzEu1wZ9sylqJE9nFoIf4fVdpcfOlDqQz3CqdtCrhLwBb0SXrrAdZ+l gBYqZuFB2qaO1x/7o7zUkK1rRBLJ5jYQdR2I923MMMz466k+LB8/t4PIyo/AeaUNq5GS mBak9wvYsAjOHxEE7zG3O4uMjDPo8cKk4B6LmeqhIzyBRH1jIWPb1qkXw1b52PvRTxfz bOAw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id q128si10394705ybc.142.2018.12.18.10.06.29 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 10:06:29 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjH-0006aK-Ho; Tue, 18 Dec 2018 18:04:27 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjG-0006a9-Hb for xen-devel@lists.xenproject.org; Tue, 18 Dec 2018 18:04:26 +0000 X-Inumbo-ID: 5afc5553-02ef-11e9-8e1d-bc764e045a96 Received: from foss.arm.com (unknown [217.140.101.70]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTP id 5afc5553-02ef-11e9-8e1d-bc764e045a96; Tue, 18 Dec 2018 18:04:25 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A7B0715AB; Tue, 18 Dec 2018 10:04:25 -0800 (PST) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.196.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id AFD7F3F5C0; Tue, 18 Dec 2018 10:04:24 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 18 Dec 2018 18:04:14 +0000 Message-Id: <20181218180417.22134-2-julien.grall@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181218180417.22134-1-julien.grall@arm.com> References: <20181218180417.22134-1-julien.grall@arm.com> Subject: [Xen-devel] [PATCH for-4.12 v4 1/4] xen/arm: vcpreg: Add wrappers to handle co-proc access trapped by HCR_EL2.TVM X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Julien Grall , Stefano Stabellini MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" A follow-up patch will require to emulate some accesses to some co-processors registers trapped by HCR_EL2.TVM. When set, all NS EL1 writes to the virtual memory control registers will be trapped to the hypervisor. This patch adds the infrastructure to passthrough the access to host registers. For convenience a bunch of helpers have been added to generate the different helpers. Note that HCR_EL2.TVM will be set in a follow-up patch dynamically. Signed-off-by: Julien Grall Reviewed-by: Stefano Stabellini --- Changes in v3: - Add Stefano's reviewed-by Changes in v2: - Add missing include vreg.h - Fixup mask TMV_REG32_COMBINED - Update comments --- xen/arch/arm/vcpreg.c | 149 +++++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/cpregs.h | 1 + 2 files changed, 150 insertions(+) diff --git a/xen/arch/arm/vcpreg.c b/xen/arch/arm/vcpreg.c index 7b783e4bcc..550c25ec3f 100644 --- a/xen/arch/arm/vcpreg.c +++ b/xen/arch/arm/vcpreg.c @@ -23,8 +23,129 @@ #include #include #include +#include #include +/* + * Macros to help generating helpers for registers trapped when + * HCR_EL2.TVM is set. + * + * Note that it only traps NS write access from EL1. + * + * - TVM_REG() should not be used outside of the macros. It is there to + * help defining TVM_REG32() and TVM_REG64() + * - TVM_REG32(regname, xreg) and TVM_REG64(regname, xreg) are used to + * resp. generate helper accessing 32-bit and 64-bit register. "regname" + * is the Arm32 name and "xreg" the Arm64 name. + * - TVM_REG32_COMBINED(lowreg, hireg, xreg) are used to generate a + * pair of register sharing the same Arm64 register, but are 2 distinct + * Arm32 registers. "lowreg" and "hireg" contains the name for on Arm32 + * registers, "xreg" contains the name for the combined register on Arm64. + * The definition of "lowreg" and "higreg" match the Armv8 specification, + * this means "lowreg" is an alias to xreg[31:0] and "high" is an alias to + * xreg[63:32]. + * + */ + +/* The name is passed from the upper macro to workaround macro expansion. */ +#define TVM_REG(sz, func, reg...) \ +static bool func(struct cpu_user_regs *regs, uint##sz##_t *r, bool read) \ +{ \ + GUEST_BUG_ON(read); \ + WRITE_SYSREG##sz(*r, reg); \ + \ + return true; \ +} + +#define TVM_REG32(regname, xreg) TVM_REG(32, vreg_emulate_##regname, xreg) +#define TVM_REG64(regname, xreg) TVM_REG(64, vreg_emulate_##regname, xreg) + +#ifdef CONFIG_ARM_32 +#define TVM_REG32_COMBINED(lowreg, hireg, xreg) \ + /* Use TVM_REG directly to workaround macro expansion. */ \ + TVM_REG(32, vreg_emulate_##lowreg, lowreg) \ + TVM_REG(32, vreg_emulate_##hireg, hireg) + +#else /* CONFIG_ARM_64 */ +#define TVM_REG32_COMBINED(lowreg, hireg, xreg) \ +static bool vreg_emulate_##xreg(struct cpu_user_regs *regs, uint32_t *r, \ + bool read, bool hi) \ +{ \ + register_t reg = READ_SYSREG(xreg); \ + \ + GUEST_BUG_ON(read); \ + if ( hi ) /* reg[63:32] is AArch32 register hireg */ \ + { \ + reg &= GENMASK(31, 0); \ + reg |= ((uint64_t)*r) << 32; \ + } \ + else /* reg[31:0] is AArch32 register lowreg. */ \ + { \ + reg &= GENMASK(63, 32); \ + reg |= *r; \ + } \ + WRITE_SYSREG(reg, xreg); \ + \ + return true; \ +} \ + \ +static bool vreg_emulate_##lowreg(struct cpu_user_regs *regs, uint32_t *r, \ + bool read) \ +{ \ + return vreg_emulate_##xreg(regs, r, read, false); \ +} \ + \ +static bool vreg_emulate_##hireg(struct cpu_user_regs *regs, uint32_t *r, \ + bool read) \ +{ \ + return vreg_emulate_##xreg(regs, r, read, true); \ +} +#endif + +/* Defining helpers for emulating co-processor registers. */ +TVM_REG32(SCTLR, SCTLR_EL1) +/* + * AArch32 provides two way to access TTBR* depending on the access + * size, whilst AArch64 provides one way. + * + * When using AArch32, for simplicity, use the same access size as the + * guest. + */ +#ifdef CONFIG_ARM_32 +TVM_REG32(TTBR0_32, TTBR0_32) +TVM_REG32(TTBR1_32, TTBR1_32) +#else +TVM_REG32(TTBR0_32, TTBR0_EL1) +TVM_REG32(TTBR1_32, TTBR1_EL1) +#endif +TVM_REG64(TTBR0, TTBR0_EL1) +TVM_REG64(TTBR1, TTBR1_EL1) +/* AArch32 registers TTBCR and TTBCR2 share AArch64 register TCR_EL1. */ +TVM_REG32_COMBINED(TTBCR, TTBCR2, TCR_EL1) +TVM_REG32(DACR, DACR32_EL2) +TVM_REG32(DFSR, ESR_EL1) +TVM_REG32(IFSR, IFSR32_EL2) +/* AArch32 registers DFAR and IFAR shares AArch64 register FAR_EL1. */ +TVM_REG32_COMBINED(DFAR, IFAR, FAR_EL1) +TVM_REG32(ADFSR, AFSR0_EL1) +TVM_REG32(AIFSR, AFSR1_EL1) +/* AArch32 registers MAIR0 and MAIR1 share AArch64 register MAIR_EL1. */ +TVM_REG32_COMBINED(MAIR0, MAIR1, MAIR_EL1) +/* AArch32 registers AMAIR0 and AMAIR1 share AArch64 register AMAIR_EL1. */ +TVM_REG32_COMBINED(AMAIR0, AMAIR1, AMAIR_EL1) +TVM_REG32(CONTEXTIDR, CONTEXTIDR_EL1) + +/* Macro to generate easily case for co-processor emulation. */ +#define GENERATE_CASE(reg, sz) \ + case HSR_CPREG##sz(reg): \ + { \ + bool res; \ + \ + res = vreg_emulate_cp##sz(regs, hsr, vreg_emulate_##reg); \ + ASSERT(res); \ + break; \ + } + void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr) { const struct hsr_cp32 cp32 = hsr.cp32; @@ -65,6 +186,31 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr) break; /* + * HCR_EL2.TVM + * + * ARMv8 (DDI 0487D.a): Table D1-38 + */ + GENERATE_CASE(SCTLR, 32) + GENERATE_CASE(TTBR0_32, 32) + GENERATE_CASE(TTBR1_32, 32) + GENERATE_CASE(TTBCR, 32) + GENERATE_CASE(TTBCR2, 32) + GENERATE_CASE(DACR, 32) + GENERATE_CASE(DFSR, 32) + GENERATE_CASE(IFSR, 32) + GENERATE_CASE(DFAR, 32) + GENERATE_CASE(IFAR, 32) + GENERATE_CASE(ADFSR, 32) + GENERATE_CASE(AIFSR, 32) + /* AKA PRRR */ + GENERATE_CASE(MAIR0, 32) + /* AKA NMRR */ + GENERATE_CASE(MAIR1, 32) + GENERATE_CASE(AMAIR0, 32) + GENERATE_CASE(AMAIR1, 32) + GENERATE_CASE(CONTEXTIDR, 32) + + /* * MDCR_EL2.TPM * * ARMv7 (DDI 0406C.b): B1.14.17 @@ -193,6 +339,9 @@ void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr) return inject_undef_exception(regs, hsr); break; + GENERATE_CASE(TTBR0, 64) + GENERATE_CASE(TTBR1, 64) + /* * CPTR_EL2.T{0..9,12..13} * diff --git a/xen/include/asm-arm/cpregs.h b/xen/include/asm-arm/cpregs.h index 97a3c6f1c1..8fd344146e 100644 --- a/xen/include/asm-arm/cpregs.h +++ b/xen/include/asm-arm/cpregs.h @@ -140,6 +140,7 @@ /* CP15 CR2: Translation Table Base and Control Registers */ #define TTBCR p15,0,c2,c0,2 /* Translation Table Base Control Register */ +#define TTBCR2 p15,0,c2,c0,3 /* Translation Table Base Control Register 2 */ #define TTBR0 p15,0,c2 /* Translation Table Base Reg. 0 */ #define TTBR1 p15,1,c2 /* Translation Table Base Reg. 1 */ #define HTTBR p15,4,c2 /* Hyp. Translation Table Base Register */ From patchwork Tue Dec 18 18:04:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 154172 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4015000ljp; Tue, 18 Dec 2018 10:06:24 -0800 (PST) X-Google-Smtp-Source: AFSGD/WrMRgzkKqca3wwu9U21bqiQAx+Wc2K0PiieMqH34W6YMSZZleG0YTndaWjUUetDglSgeUd X-Received: by 2002:ac8:7094:: with SMTP id y20mr556929qto.380.1545156384362; Tue, 18 Dec 2018 10:06:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545156384; cv=none; d=google.com; s=arc-20160816; b=vVRv6A9c6i58d5jWl1ZAtOQPXq4/CSqK4ZoZ1dMe7i1CLyXVrfsX9vDPdykSYoOfY3 B3vcgTR9WgQVz6LikrgkP+9tra03Q8ofad3MmBbd63nfNjBfFL3E6E9zWN6rU6SmQY84 uMO+qnHrijBPKf6qhjBct8ekOg1ib0VG/N/Gh7ra9Z9f5zT7f+qc8iW+4U5EFN5fAa4b /F4EnB7QZ0uTN8jZ0UsULP/EtqtUgXv6Z+JU9mAkJ8G1U7mw6fh9iUbmFHWO5TZqUuTO bhamBkJ4VZu2ig2Nbsq5e+AR/exgoZ8U+kDxAs1UZKyCmyFGNQdC8kLelOq6zdpecf9f swfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-unsubscribe:list-id :precedence:subject:references:in-reply-to:message-id:date:to:from; bh=OmRC+QzqWUNOKjVSiqzE7yl8Kf4qC35nmjYIjz6E3Mw=; b=aV1kjRvpKzIQs43InaNBp5QS58wXFbj5BnI7o/mbF85Q/bW6WeG2Zj5k7QRAIYU1yG sTvw0EUlqncxUPh6/sApz7m1S10lOvgwQWrzOEB3e1yb2D/3aQzB/krHpd88/4Prtew8 5Ex/yLvT+pvN5Zf6Bu4Veefl5ioPesCOLwymaSW48rpMLBccMmzjTSS9+8ry0tVxmMpo ZizmQhRb3ps5NoDd+hd2v5zVibgTdNshRfzQ870Xuo5kn97oL562B1LX3WVVGIrX5mW6 +w9PDbsxqmvsbaBGhVf/oTgGQCB9yFmqCDfAZ5HrbbB0vaEH42nIWxAhFfXVbl3Lp6JD WfFQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id x3si401521qtd.345.2018.12.18.10.06.24 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 10:06:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjI-0006am-WF; Tue, 18 Dec 2018 18:04:29 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjI-0006ac-Iq for xen-devel@lists.xenproject.org; Tue, 18 Dec 2018 18:04:28 +0000 X-Inumbo-ID: 5bc696d8-02ef-11e9-9e66-b35f198798f0 Received: from foss.arm.com (unknown [217.140.101.70]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTP id 5bc696d8-02ef-11e9-9e66-b35f198798f0; Tue, 18 Dec 2018 18:04:27 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AE3331650; Tue, 18 Dec 2018 10:04:26 -0800 (PST) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.196.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E30183F5C0; Tue, 18 Dec 2018 10:04:25 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 18 Dec 2018 18:04:15 +0000 Message-Id: <20181218180417.22134-3-julien.grall@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181218180417.22134-1-julien.grall@arm.com> References: <20181218180417.22134-1-julien.grall@arm.com> Subject: [Xen-devel] [PATCH for-4.12 v4 2/4] xen/arm: vsysreg: Add wrapper to handle sysreg access trapped by HCR_EL2.TVM X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Julien Grall , Stefano Stabellini MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" A follow-up patch will require to emulate some accesses to system registers trapped by HCR_EL2.TVM. When set, all NS EL1 writes to the virtual memory control registers will be trapped to the hypervisor. This patch adds the infrastructure to passthrough the access to the host registers. Note that HCR_EL2.TVM will be set in a follow-up patch dynamically. Signed-off-by: Julien Grall Reviewed-by: Stefano Stabellini --- Changes in v4: - Add Stefano's reviewed by Changes in v2: - Add missing include vreg.h - Update documentation reference to the lastest one --- xen/arch/arm/arm64/vsysreg.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c index 6e60824572..16ac9c344a 100644 --- a/xen/arch/arm/arm64/vsysreg.c +++ b/xen/arch/arm/arm64/vsysreg.c @@ -21,8 +21,49 @@ #include #include #include +#include #include +/* + * Macro to help generating helpers for registers trapped when + * HCR_EL2.TVM is set. + * + * Note that it only traps NS write access from EL1. + */ +#define TVM_REG(reg) \ +static bool vreg_emulate_##reg(struct cpu_user_regs *regs, \ + uint64_t *r, bool read) \ +{ \ + GUEST_BUG_ON(read); \ + WRITE_SYSREG64(*r, reg); \ + \ + return true; \ +} + +/* Defining helpers for emulating sysreg registers. */ +TVM_REG(SCTLR_EL1) +TVM_REG(TTBR0_EL1) +TVM_REG(TTBR1_EL1) +TVM_REG(TCR_EL1) +TVM_REG(ESR_EL1) +TVM_REG(FAR_EL1) +TVM_REG(AFSR0_EL1) +TVM_REG(AFSR1_EL1) +TVM_REG(MAIR_EL1) +TVM_REG(AMAIR_EL1) +TVM_REG(CONTEXTIDR_EL1) + +/* Macro to generate easily case for co-processor emulation */ +#define GENERATE_CASE(reg) \ + case HSR_SYSREG_##reg: \ + { \ + bool res; \ + \ + res = vreg_emulate_sysreg64(regs, hsr, vreg_emulate_##reg); \ + ASSERT(res); \ + break; \ + } + void do_sysreg(struct cpu_user_regs *regs, const union hsr hsr) { @@ -44,6 +85,23 @@ void do_sysreg(struct cpu_user_regs *regs, break; /* + * HCR_EL2.TVM + * + * ARMv8 (DDI 0487D.a): Table D1-38 + */ + GENERATE_CASE(SCTLR_EL1) + GENERATE_CASE(TTBR0_EL1) + GENERATE_CASE(TTBR1_EL1) + GENERATE_CASE(TCR_EL1) + GENERATE_CASE(ESR_EL1) + GENERATE_CASE(FAR_EL1) + GENERATE_CASE(AFSR0_EL1) + GENERATE_CASE(AFSR1_EL1) + GENERATE_CASE(MAIR_EL1) + GENERATE_CASE(AMAIR_EL1) + GENERATE_CASE(CONTEXTIDR_EL1) + + /* * MDCR_EL2.TDRA * * ARMv8 (DDI 0487A.d): D1-1508 Table D1-57 From patchwork Tue Dec 18 18:04:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 154175 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4015166ljp; Tue, 18 Dec 2018 10:06:33 -0800 (PST) X-Google-Smtp-Source: AFSGD/XdVMZFo/jXqGH8T1MQAGgMFUF0JSCFfDdgLF4OM5BenxM7ofk0GxSdgrzwkuUkXS8EBOFu X-Received: by 2002:a37:8e41:: with SMTP id q62mr17792772qkd.290.1545156393219; Tue, 18 Dec 2018 10:06:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545156393; cv=none; d=google.com; s=arc-20160816; b=IKBgvty54wvfUTLZfuj6T8IQN7LpbaeXLicTmTUfc63LPh94YRWWYMfrXOAIeO82mU oLCGqZrqzse3IwiJYDh1Lx/sgJuHEYj6lc5HsFJJld3066d/05IFBit6z4fdaD5Y0bGD 95zdWWCFIpg9Pjf+Ycl+2xAQYP8y83/U+7Z/S3IjMKImRDA0QBCWxCVXcTNg1oODetHN EI8zrUGcVQuPWwhEJI6A1I32/x/EDZlXTJqb5FUksCROorCCeQRO7BK31j4WWAlertXd tC60GTyqPklI/9uoNrRtqYiEIsCciELYZp93p3qxnZTe1EjFYwP1fnPuRkq+UdedU5Rd +AUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-unsubscribe:list-id :precedence:subject:references:in-reply-to:message-id:date:to:from; bh=GigO7renqtQqhHzRjoq/oNyPQcTKD+LQahzrd5oKGdo=; b=ck7OezRCBm7ZNDE0IeSqtNjrPC8YwXT+qYjHEGuHZP9RDVdUqYeuTl46KXnzlOaPQA 8ag8upSRlZp3Po5yZYP6XBqdelABaissEM0vD7woHY91W/6Ppm1EmFbq+fMhbYmnBX5l vQElAZOCrfSXx1QEN6hNthiNVZWnsXg8IBJkwEMrcd6vJXqFPpAtep1WznTZb2FCRNXD q6+LqLA4BNp3vEFPH3iJ3GRfPDKtWWuD1uN7pQrSoejjL8INiMB96GjFiUD3CAAlQWvV 69g1LnIO6FoBMvYUA/yp5byR2Qe2hA2gdxrDKspcPmw0CoGtn/TG0OwSRLb+9DbdPYzi QCGg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id y63si389631qkb.69.2018.12.18.10.06.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 10:06:33 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjK-0006bF-9V; Tue, 18 Dec 2018 18:04:30 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjJ-0006ar-74 for xen-devel@lists.xenproject.org; Tue, 18 Dec 2018 18:04:29 +0000 X-Inumbo-ID: 5c48a3e7-02ef-11e9-8e1d-bc764e045a96 Received: from foss.arm.com (unknown [217.140.101.70]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTP id 5c48a3e7-02ef-11e9-8e1d-bc764e045a96; Tue, 18 Dec 2018 18:04:28 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D812B15AB; Tue, 18 Dec 2018 10:04:27 -0800 (PST) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.196.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E94EE3F5C0; Tue, 18 Dec 2018 10:04:26 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 18 Dec 2018 18:04:16 +0000 Message-Id: <20181218180417.22134-4-julien.grall@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181218180417.22134-1-julien.grall@arm.com> References: <20181218180417.22134-1-julien.grall@arm.com> Subject: [Xen-devel] [PATCH for-4.12 v4 3/4] xen/arm: Implement Set/Way operations X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Julien Grall , Stefano Stabellini MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Set/Way operations are used to perform maintenance on a given cache. At the moment, Set/Way operations are not trapped and therefore a guest OS will directly act on the local cache. However, a vCPU may migrate to another pCPU in the middle of the processor. This will result to have cache with stale data (Set/Way are not propagated) potentially causing crash. This may be the cause of heisenbug noticed in Osstest [1]. Furthermore, Set/Way operations are not available on system cache. This means that OS, such as Linux 32-bit, relying on those operations to fully clean the cache before disabling MMU may break because data may sits in system caches and not in RAM. For more details about Set/Way, see the talk "The Art of Virtualizing Cache Maintenance" given at Xen Summit 2018 [2]. In the context of Xen, we need to trap Set/Way operations and emulate them. From the Arm Arm (B1.14.4 in DDI 046C.c), Set/Way operations are difficult to virtualized. So we can assume that a guest OS using them will suffer the consequence (i.e slowness) until developer removes all the usage of Set/Way. As the software is not allowed to infer the Set/Way to Physical Address mapping, Xen will need to go through the guest P2M and clean & invalidate all the entries mapped. Because Set/Way happen in batch (a loop on all Set/Way of a cache), Xen would need to go through the P2M for every instructions. This is quite expensive and would severely impact the guest OS. The implementation is re-using the KVM policy to limit the number of flush: - If we trap a Set/Way operations, we enable VM trapping (i.e HVC_EL2.TVM) to detect cache being turned on/off, and do a full clean. - We clean the caches when turning on and off - Once the caches are enabled, we stop trapping VM instructions [1] https://lists.xenproject.org/archives/html/xen-devel/2017-09/msg03191.html [2] https://fr.slideshare.net/xen_com_mgr/virtualizing-cache Signed-off-by: Julien Grall Reviewed-by: Stefano Stabellini --- Changes in v4: - Fix typoes - Update comments - Remove unecessary {} Changes in v2: - Fix emulation for Set/Way cache flush arm64 sysreg - Add support for preemption - Check cache status on every VM traps in Arm64 - Remove spurious change --- xen/arch/arm/arm64/vsysreg.c | 17 +++++++++ xen/arch/arm/p2m.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/traps.c | 25 +++++++++++- xen/arch/arm/vcpreg.c | 22 +++++++++++ xen/include/asm-arm/domain.h | 9 +++++ xen/include/asm-arm/p2m.h | 20 ++++++++++ 6 files changed, 182 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c index 16ac9c344a..8a85507d9d 100644 --- a/xen/arch/arm/arm64/vsysreg.c +++ b/xen/arch/arm/arm64/vsysreg.c @@ -34,9 +34,14 @@ static bool vreg_emulate_##reg(struct cpu_user_regs *regs, \ uint64_t *r, bool read) \ { \ + struct vcpu *v = current; \ + bool cache_enabled = vcpu_has_cache_enabled(v); \ + \ GUEST_BUG_ON(read); \ WRITE_SYSREG64(*r, reg); \ \ + p2m_toggle_cache(v, cache_enabled); \ + \ return true; \ } @@ -85,6 +90,18 @@ void do_sysreg(struct cpu_user_regs *regs, break; /* + * HCR_EL2.TSW + * + * ARMv8 (DDI 0487B.b): Table D1-42 + */ + case HSR_SYSREG_DCISW: + case HSR_SYSREG_DCCSW: + case HSR_SYSREG_DCCISW: + if ( !hsr.sysreg.read ) + p2m_set_way_flush(current); + break; + + /* * HCR_EL2.TVM * * ARMv8 (DDI 0487D.a): Table D1-38 diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index ff52cb178f..22bec7390b 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -1615,6 +1616,95 @@ int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end) return rc; } +/* + * Clean & invalidate RAM associated to the guest vCPU. + * + * The function can only work with the current vCPU and should be called + * with IRQ enabled as the vCPU could get preempted. + */ +void p2m_flush_vm(struct vcpu *v) +{ + int rc; + gfn_t start = _gfn(0); + + ASSERT(v == current); + ASSERT(local_irq_is_enabled()); + ASSERT(v->arch.need_flush_to_ram); + + do + { + rc = p2m_cache_flush_range(v->domain, &start, _gfn(ULONG_MAX)); + if ( rc == -ERESTART ) + do_softirq(); + } while ( rc == -ERESTART ); + + if ( rc != 0 ) + gprintk(XENLOG_WARNING, + "P2M has not been correctly cleaned (rc = %d)\n", + rc); + + v->arch.need_flush_to_ram = false; +} + +/* + * See note at ARMv7 ARM B1.14.4 (DDI 0406C.c) (TL;DR: S/W ops are not + * easily virtualized). + * + * Main problems: + * - S/W ops are local to a CPU (not broadcast) + * - We have line migration behind our back (speculation) + * - System caches don't support S/W at all (damn!) + * + * In the face of the above, the best we can do is to try and convert + * S/W ops to VA ops. Because the guest is not allowed to infer the S/W + * to PA mapping, it can only use S/W to nuke the whole cache, which is + * rather a good thing for us. + * + * Also, it is only used when turning caches on/off ("The expected + * usage of the cache maintenance instructions that operate by set/way + * is associated with the powerdown and powerup of caches, if this is + * required by the implementation."). + * + * We use the following policy: + * - If we trap a S/W operation, we enabled VM trapping to detect + * caches being turned on/off, and do a full clean. + * + * - We flush the caches on both caches being turned on and off. + * + * - Once the caches are enabled, we stop trapping VM ops. + */ +void p2m_set_way_flush(struct vcpu *v) +{ + /* This function can only work with the current vCPU. */ + ASSERT(v == current); + + if ( !(v->arch.hcr_el2 & HCR_TVM) ) + { + v->arch.need_flush_to_ram = true; + vcpu_hcr_set_flags(v, HCR_TVM); + } +} + +void p2m_toggle_cache(struct vcpu *v, bool was_enabled) +{ + bool now_enabled = vcpu_has_cache_enabled(v); + + /* This function can only work with the current vCPU. */ + ASSERT(v == current); + + /* + * If switching the MMU+caches on, need to invalidate the caches. + * If switching it off, need to clean the caches. + * Clean + invalidate does the trick always. + */ + if ( was_enabled != now_enabled ) + v->arch.need_flush_to_ram = true; + + /* Caches are now on, stop trapping VM ops (until a S/W op) */ + if ( now_enabled ) + vcpu_hcr_clear_flags(v, HCR_TVM); +} + mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn) { return p2m_lookup(d, gfn, NULL); diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 02665cc7b4..221c762ada 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -97,7 +97,7 @@ register_t get_default_hcr_flags(void) { return (HCR_PTW|HCR_BSU_INNER|HCR_AMO|HCR_IMO|HCR_FMO|HCR_VM| (vwfi != NATIVE ? (HCR_TWI|HCR_TWE) : 0) | - HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP|HCR_FB); + HCR_TSC|HCR_TAC|HCR_SWIO|HCR_TIDCP|HCR_FB|HCR_TSW); } static enum { @@ -2258,10 +2258,33 @@ static void check_for_pcpu_work(void) } } +/* + * Process pending work for the vCPU. Any call should be fast or + * implement preemption. + */ +static void check_for_vcpu_work(void) +{ + struct vcpu *v = current; + + if ( likely(!v->arch.need_flush_to_ram) ) + return; + + /* + * Give a chance for the pCPU to process work before handling the vCPU + * pending work. + */ + check_for_pcpu_work(); + + local_irq_enable(); + p2m_flush_vm(v); + local_irq_disable(); +} + void leave_hypervisor_tail(void) { local_irq_disable(); + check_for_vcpu_work(); check_for_pcpu_work(); vgic_sync_to_lrs(); diff --git a/xen/arch/arm/vcpreg.c b/xen/arch/arm/vcpreg.c index 550c25ec3f..cdc91cdf5b 100644 --- a/xen/arch/arm/vcpreg.c +++ b/xen/arch/arm/vcpreg.c @@ -51,9 +51,14 @@ #define TVM_REG(sz, func, reg...) \ static bool func(struct cpu_user_regs *regs, uint##sz##_t *r, bool read) \ { \ + struct vcpu *v = current; \ + bool cache_enabled = vcpu_has_cache_enabled(v); \ + \ GUEST_BUG_ON(read); \ WRITE_SYSREG##sz(*r, reg); \ \ + p2m_toggle_cache(v, cache_enabled); \ + \ return true; \ } @@ -71,6 +76,8 @@ static bool func(struct cpu_user_regs *regs, uint##sz##_t *r, bool read) \ static bool vreg_emulate_##xreg(struct cpu_user_regs *regs, uint32_t *r, \ bool read, bool hi) \ { \ + struct vcpu *v = current; \ + bool cache_enabled = vcpu_has_cache_enabled(v); \ register_t reg = READ_SYSREG(xreg); \ \ GUEST_BUG_ON(read); \ @@ -86,6 +93,8 @@ static bool vreg_emulate_##xreg(struct cpu_user_regs *regs, uint32_t *r, \ } \ WRITE_SYSREG(reg, xreg); \ \ + p2m_toggle_cache(v, cache_enabled); \ + \ return true; \ } \ \ @@ -186,6 +195,19 @@ void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr) break; /* + * HCR_EL2.TSW + * + * ARMv7 (DDI 0406C.b): B1.14.6 + * ARMv8 (DDI 0487B.b): Table D1-42 + */ + case HSR_CPREG32(DCISW): + case HSR_CPREG32(DCCSW): + case HSR_CPREG32(DCCISW): + if ( !cp32.read ) + p2m_set_way_flush(current); + break; + + /* * HCR_EL2.TVM * * ARMv8 (DDI 0487D.a): Table D1-38 diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 175de44927..312fec8932 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -202,6 +202,15 @@ struct arch_vcpu struct vtimer phys_timer; struct vtimer virt_timer; bool vtimer_initialized; + + /* + * The full P2M may require some cleaning (e.g when emulation + * set/way). As the action can take a long time, it requires + * preemption. It is deferred until we return to guest, where we can + * more easily check for softirqs and preempt the vCPU safely. + */ + bool need_flush_to_ram; + } __cacheline_aligned; void vcpu_show_execution_state(struct vcpu *); diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index a633e27cc9..79abcb5a63 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -6,6 +6,8 @@ #include #include +#include + #define paddr_bits PADDR_BITS /* Holds the bit size of IPAs in p2m tables. */ @@ -237,6 +239,12 @@ bool p2m_resolve_translation_fault(struct domain *d, gfn_t gfn); */ int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end); +void p2m_set_way_flush(struct vcpu *v); + +void p2m_toggle_cache(struct vcpu *v, bool was_enabled); + +void p2m_flush_vm(struct vcpu *v); + /* * Map a region in the guest p2m with a specific p2m type. * The memory attributes will be derived from the p2m type. @@ -364,6 +372,18 @@ static inline int set_foreign_p2m_entry(struct domain *d, unsigned long gfn, return -EOPNOTSUPP; } +/* + * A vCPU has cache enabled only when the MMU is enabled and data cache + * is enabled. + */ +static inline bool vcpu_has_cache_enabled(struct vcpu *v) +{ + /* Only works with the current vCPU */ + ASSERT(current == v); + + return (READ_SYSREG32(SCTLR_EL1) & (SCTLR_C|SCTLR_M)) == (SCTLR_C|SCTLR_M); +} + #endif /* _XEN_P2M_H */ /* From patchwork Tue Dec 18 18:04:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 154174 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4015143ljp; Tue, 18 Dec 2018 10:06:31 -0800 (PST) X-Google-Smtp-Source: AFSGD/Uc2EZtJ1JthG9VF0kkFWILQmPnERtPPhi6uyZwlnRWZF1yQOuvMuiW5iKOPeu5tioYv5kF X-Received: by 2002:a0d:dcc5:: with SMTP id f188mr18163340ywe.210.1545156391722; Tue, 18 Dec 2018 10:06:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545156391; cv=none; d=google.com; s=arc-20160816; b=O8POF32zsCGgbq15Z7KFIYytlpWOqsaKjQN5aib/w084cLUnngnMsq63PXTvdZsc7S hcCoX9fTx8gZSr8aJV+zxM1+kRS2SB5DGVd2nYWZpgkC1KSMTlkJoAOCJHGX3Q8mcMgr nTCgyyWWnGJWOdlLutUC8uRK8hGBw4cJx1YyIY20eoUSGu7mx7KyFcGZYphGtoDHfkOZ RNBSQ7ybwNhcX6Xs3FI2x1VtCVb4aMsMSTg+MTyY/ZV6aOiBO3C84icar9YS67560w6j SZ1vtODNXBQ1N3+DL/rZR7UNtIgb2KdDIx6pT8Ik2AObF6ltWyoXDdxHH+D4MoD4oNKp Hd8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-unsubscribe:list-id :precedence:subject:references:in-reply-to:message-id:date:to:from; bh=uRLZhLPSQaw/sQ1eHc1SR3phMS+9c/QNNtSxb0UtR6w=; b=x3XtIMHnxaY6QBI0CGBL+NjS9lNmjEt8lHj/QNpyCj3Apwh7Un5LQLza4pVs9E7b6b Yd2BY4RYlSoSSxskWzQr+CEv1Oq3cE6vJf97SCav9C/8hWn7P6kemW3PXlT9WLiNsjAo tpT9WJC8Osb56KrevX0CTnRmfHwZ/81vZR/mPQT5Hd6MpHOT8XUxFrP1rhwe+T+c3iVP +lVwjyj7eB4R0e1y8deS6VQGcLt5FwK92p+n1+jvYWY7YM13oxgHDRbzTKHjKfFC7pSf c4I+eNO2hrf0PzqUu0P8w4ShUAQAIzKPasZPlYrJl7FWDurZjBdyr5bLKeEPfglpE7fQ WPSw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id g189si9647875ywg.331.2018.12.18.10.06.31 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 18 Dec 2018 10:06:31 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjM-0006cs-OZ; Tue, 18 Dec 2018 18:04:32 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1gZJjL-0006bo-0J for xen-devel@lists.xenproject.org; Tue, 18 Dec 2018 18:04:31 +0000 X-Inumbo-ID: 5d9c7489-02ef-11e9-8e1d-bc764e045a96 Received: from foss.arm.com (unknown [217.140.101.70]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTP id 5d9c7489-02ef-11e9-8e1d-bc764e045a96; Tue, 18 Dec 2018 18:04:30 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 13590A78; Tue, 18 Dec 2018 10:04:30 -0800 (PST) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.196.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 211A83F5C0; Tue, 18 Dec 2018 10:04:27 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 18 Dec 2018 18:04:17 +0000 Message-Id: <20181218180417.22134-5-julien.grall@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181218180417.22134-1-julien.grall@arm.com> References: <20181218180417.22134-1-julien.grall@arm.com> Subject: [Xen-devel] [PATCH for-4.12 v4 4/4] xen/arm: Track page accessed between batch of Set/Way operations X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" At the moment, the implementation of Set/Way operations will go through all the entries of the guest P2M and flush them. However, this is very expensive and may render unusable a guest OS using them. For instance, Linux 32-bit will use Set/Way operations during secondary CPU bring-up. As the implementation is really expensive, it may be possible to hit the CPU bring-up timeout. To limit the Set/Way impact, we track what pages has been of the guest has been accessed between batch of Set/Way operations. This is done using bit[0] (aka valid bit) of the P2M entry. This patch adds a new per-arch helper is introduced to perform actions just before the guest is first unpaused. This will be used to invalidate the P2M to track access from the start of the guest. Signed-off-by: Julien Grall Reviewed-by: Jan Beulich Reviewed-by: Stefano Stabellini --- While we can spread d->creation_finished all over the code, the per-arch helper to perform actions just before the guest is first unpaused can bring a lot of benefit for both architecture. For instance, on Arm, the flush to the instruction cache could be delayed until the domain is first run. This would improve greatly the performance of creating guest. Changes in v4: - Add Stefano's reviewed-by Changes in v3: - Add Jan reviewed-by for non-ARM pieces Cc: Stefano Stabellini Cc: Julien Grall Cc: Andrew Cooper Cc: George Dunlap Cc: Ian Jackson Cc: Jan Beulich Cc: Konrad Rzeszutek Wilk Cc: Tim Deegan Cc: Wei Liu --- xen/arch/arm/domain.c | 14 ++++++++++++++ xen/arch/arm/p2m.c | 29 +++++++++++++++++++++++++++-- xen/arch/x86/domain.c | 4 ++++ xen/common/domain.c | 5 ++++- xen/include/asm-arm/p2m.h | 2 ++ xen/include/xen/domain.h | 2 ++ 6 files changed, 53 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 1d926dcb29..41f101746e 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -767,6 +767,20 @@ int arch_domain_soft_reset(struct domain *d) return -ENOSYS; } +void arch_domain_creation_finished(struct domain *d) +{ + /* + * To avoid flushing the whole guest RAM on the first Set/Way, we + * invalidate the P2M to track what has been accessed. + * + * This is only turned when IOMMU is not used or the page-table are + * not shared because bit[0] (e.g valid bit) unset will result + * IOMMU fault that could be not fixed-up. + */ + if ( !iommu_use_hap_pt(d) ) + p2m_invalidate_root(p2m_get_hostp2m(d)); +} + static int is_guest_pv32_psr(uint32_t psr) { switch (psr & PSR_MODE_MASK) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 22bec7390b..2b5e43f50a 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -1079,6 +1079,22 @@ static void p2m_invalidate_table(struct p2m_domain *p2m, mfn_t mfn) } /* + * Invalidate all entries in the root page-tables. This is + * useful to get fault on entry and do an action. + */ +void p2m_invalidate_root(struct p2m_domain *p2m) +{ + unsigned int i; + + p2m_write_lock(p2m); + + for ( i = 0; i < P2M_ROOT_LEVEL; i++ ) + p2m_invalidate_table(p2m, page_to_mfn(p2m->root + i)); + + p2m_write_unlock(p2m); +} + +/* * Resolve any translation fault due to change in the p2m. This * includes break-before-make and valid bit cleared. */ @@ -1587,10 +1603,12 @@ int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end) */ if ( gfn_eq(start, next_block_gfn) ) { - mfn = p2m_get_entry(p2m, start, &t, NULL, &order, NULL); + bool valid; + + mfn = p2m_get_entry(p2m, start, &t, NULL, &order, &valid); next_block_gfn = gfn_next_boundary(start, order); - if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_any_ram(t) ) + if ( mfn_eq(mfn, INVALID_MFN) || !p2m_is_any_ram(t) || !valid ) { count++; start = next_block_gfn; @@ -1624,6 +1642,7 @@ int p2m_cache_flush_range(struct domain *d, gfn_t *pstart, gfn_t end) */ void p2m_flush_vm(struct vcpu *v) { + struct p2m_domain *p2m = p2m_get_hostp2m(v->domain); int rc; gfn_t start = _gfn(0); @@ -1643,6 +1662,12 @@ void p2m_flush_vm(struct vcpu *v) "P2M has not been correctly cleaned (rc = %d)\n", rc); + /* + * Invalidate the p2m to track which page was modified by the guest + * between call of p2m_flush_vm(). + */ + p2m_invalidate_root(p2m); + v->arch.need_flush_to_ram = false; } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index f5a1f325aa..32dc4253ff 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -765,6 +765,10 @@ int arch_domain_soft_reset(struct domain *d) return ret; } +void arch_domain_creation_finished(struct domain *d) +{ +} + /* * These are the masks of CR4 bits (subject to hardware availability) which a * PV guest may not legitimiately attempt to modify. diff --git a/xen/common/domain.c b/xen/common/domain.c index 78cc5249e8..c623daec56 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -1116,8 +1116,11 @@ int domain_unpause_by_systemcontroller(struct domain *d) * Creation is considered finished when the controller reference count * first drops to 0. */ - if ( new == 0 ) + if ( new == 0 && !d->creation_finished ) + { d->creation_finished = true; + arch_domain_creation_finished(d); + } domain_unpause(d); diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 79abcb5a63..01cd3ee4b5 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -231,6 +231,8 @@ int p2m_set_entry(struct p2m_domain *p2m, bool p2m_resolve_translation_fault(struct domain *d, gfn_t gfn); +void p2m_invalidate_root(struct p2m_domain *p2m); + /* * Clean & invalidate caches corresponding to a region [start,end) of guest * address space. diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 33e41486cb..d1bfc82f57 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -70,6 +70,8 @@ void arch_domain_unpause(struct domain *d); int arch_domain_soft_reset(struct domain *d); +void arch_domain_creation_finished(struct domain *d); + void arch_p2m_set_access_required(struct domain *d, bool access_required); int arch_set_info_guest(struct vcpu *, vcpu_guest_context_u);