From patchwork Tue Oct 1 10:23:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168399 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CA6AD16B1 for ; Tue, 1 Oct 2019 10:23:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A81D921A4A for ; Tue, 1 Oct 2019 10:23:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729675AbfJAKXj (ORCPT ); Tue, 1 Oct 2019 06:23:39 -0400 Received: from foss.arm.com ([217.140.110.172]:45848 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726190AbfJAKXj (ORCPT ); Tue, 1 Oct 2019 06:23:39 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5EC651570; Tue, 1 Oct 2019 03:23:39 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 191BD3F739; Tue, 1 Oct 2019 03:23:37 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 01/19] lib: arm/arm64: Remove unused CPU_OFF parameter Date: Tue, 1 Oct 2019 11:23:05 +0100 Message-Id: <20191001102323.27628-2-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The first version of PSCI required an argument for CPU_OFF, the power_state argument, which was removed in version 0.2 of the specification [1]. kvm-unit-tests supports PSCI 0.2, and KVM ignores any CPU_OFF parameters, so let's remove the PSCI_POWER_STATE_TYPE_POWER_DOWN parameter. [1] ARM DEN 0022D, section 7.3. Signed-off-by: Alexandru Elisei --- lib/arm/psci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/arm/psci.c b/lib/arm/psci.c index c3d399064ae3..936c83948b6a 100644 --- a/lib/arm/psci.c +++ b/lib/arm/psci.c @@ -40,11 +40,9 @@ int cpu_psci_cpu_boot(unsigned int cpu) return err; } -#define PSCI_POWER_STATE_TYPE_POWER_DOWN (1U << 16) void cpu_psci_cpu_die(void) { - int err = psci_invoke(PSCI_0_2_FN_CPU_OFF, - PSCI_POWER_STATE_TYPE_POWER_DOWN, 0, 0); + int err = psci_invoke(PSCI_0_2_FN_CPU_OFF, 0, 0, 0); printf("CPU%d unable to power off (error = %d)\n", smp_processor_id(), err); } From patchwork Tue Oct 1 10:23:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168401 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A9CCD13B1 for ; Tue, 1 Oct 2019 10:23:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9268D21D56 for ; Tue, 1 Oct 2019 10:23:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730021AbfJAKXl (ORCPT ); Tue, 1 Oct 2019 06:23:41 -0400 Received: from foss.arm.com ([217.140.110.172]:45862 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729798AbfJAKXl (ORCPT ); Tue, 1 Oct 2019 06:23:41 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D1DFE1000; Tue, 1 Oct 2019 03:23:40 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 966CB3F739; Tue, 1 Oct 2019 03:23:39 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 02/19] arm/arm64: psci: Don't run C code without stack or vectors Date: Tue, 1 Oct 2019 11:23:06 +0100 Message-Id: <20191001102323.27628-3-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The psci test performs a series of CPU_ON/CPU_OFF cycles for CPU 1. This is done by setting the entry point for the CPU_ON call to the physical address of the C function cpu_psci_cpu_die. The compiler is well within its rights to use the stack when generating code for cpu_psci_cpu_die. However, because no stack initialization has been done, the stack pointer is zero, as set by KVM when creating the VCPU. This causes a data abort without a change in exception level. The VBAR_EL1 register is also zero (the KVM reset value for VBAR_EL1), the MMU is off, and we end up trying to fetch instructions from address 0x200. At this point, a stage 2 instruction abort is generated which is taken to KVM. KVM interprets this as an instruction fetch from an I/O region, and injects a prefetch abort into the guest. Prefetch abort is a synchronous exception, and on guest return the VCPU PC will be set to VBAR_EL1 + 0x200, which is... 0x200. The VCPU ends up in an infinite loop causing a prefetch abort while fetching the instruction to service the said abort. cpu_psci_cpu_die is basically a wrapper over the HVC instruction, so provide an assembly implementation for the function which will serve as the entry point for CPU_ON. Signed-off-by: Alexandru Elisei --- Changes: * replaced 'b halt' with 'b .' in asm_cpu_psci_cpu_die arm/cstart.S | 7 +++++++ arm/cstart64.S | 7 +++++++ arm/psci.c | 5 +++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arm/cstart.S b/arm/cstart.S index 114726feab82..112124f222cb 100644 --- a/arm/cstart.S +++ b/arm/cstart.S @@ -7,6 +7,7 @@ */ #define __ASSEMBLY__ #include +#include #include #include #include @@ -138,6 +139,12 @@ secondary_entry: blx r0 b do_idle +.global asm_cpu_psci_cpu_die +asm_cpu_psci_cpu_die: + ldr r0, =PSCI_0_2_FN_CPU_OFF + hvc #0 + b . + .globl halt halt: 1: wfi diff --git a/arm/cstart64.S b/arm/cstart64.S index b0e8baa1a23a..c98842f11e90 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -7,6 +7,7 @@ */ #define __ASSEMBLY__ #include +#include #include #include #include @@ -128,6 +129,12 @@ secondary_entry: blr x0 b do_idle +.globl asm_cpu_psci_cpu_die +asm_cpu_psci_cpu_die: + ldr x0, =PSCI_0_2_FN_CPU_OFF + hvc #0 + b . + .globl halt halt: 1: wfi diff --git a/arm/psci.c b/arm/psci.c index 5cb4d5c7c233..0440c4cdbc59 100644 --- a/arm/psci.c +++ b/arm/psci.c @@ -72,6 +72,7 @@ static int cpu_on_ret[NR_CPUS]; static cpumask_t cpu_on_ready, cpu_on_done; static volatile int cpu_on_start; +extern void asm_cpu_psci_cpu_die(void); static void cpu_on_secondary_entry(void) { int cpu = smp_processor_id(); @@ -79,7 +80,7 @@ static void cpu_on_secondary_entry(void) cpumask_set_cpu(cpu, &cpu_on_ready); while (!cpu_on_start) cpu_relax(); - cpu_on_ret[cpu] = psci_cpu_on(cpus[1], __pa(cpu_psci_cpu_die)); + cpu_on_ret[cpu] = psci_cpu_on(cpus[1], __pa(asm_cpu_psci_cpu_die)); cpumask_set_cpu(cpu, &cpu_on_done); } @@ -104,7 +105,7 @@ static bool psci_cpu_on_test(void) cpu_on_start = 1; smp_mb(); - cpu_on_ret[0] = psci_cpu_on(cpus[1], __pa(cpu_psci_cpu_die)); + cpu_on_ret[0] = psci_cpu_on(cpus[1], __pa(asm_cpu_psci_cpu_die)); cpumask_set_cpu(0, &cpu_on_done); while (!cpumask_full(&cpu_on_done)) From patchwork Tue Oct 1 10:23:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168403 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9444B16B1 for ; Tue, 1 Oct 2019 10:23:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7074E21D7B for ; Tue, 1 Oct 2019 10:23:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730281AbfJAKXn (ORCPT ); Tue, 1 Oct 2019 06:23:43 -0400 Received: from foss.arm.com ([217.140.110.172]:45870 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730082AbfJAKXm (ORCPT ); Tue, 1 Oct 2019 06:23:42 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 578F715A2; Tue, 1 Oct 2019 03:23:42 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 15AFA3F739; Tue, 1 Oct 2019 03:23:40 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 03/19] lib: arm/arm64: Add missing include for alloc_page.h in pgtable.h Date: Tue, 1 Oct 2019 11:23:07 +0100 Message-Id: <20191001102323.27628-4-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org pgtable.h is used only by mmu.c, where it is included after alloc_page.h. Reviewed-by: Andrew Jones Signed-off-by: Alexandru Elisei --- lib/arm/asm/pgtable.h | 1 + lib/arm64/asm/pgtable.h | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/arm/asm/pgtable.h b/lib/arm/asm/pgtable.h index 241dff69b38a..b01c34348321 100644 --- a/lib/arm/asm/pgtable.h +++ b/lib/arm/asm/pgtable.h @@ -13,6 +13,7 @@ * * This work is licensed under the terms of the GNU GPL, version 2. */ +#include /* * We can convert va <=> pa page table addresses with simple casts diff --git a/lib/arm64/asm/pgtable.h b/lib/arm64/asm/pgtable.h index ee0a2c88cc18..e9dd49155564 100644 --- a/lib/arm64/asm/pgtable.h +++ b/lib/arm64/asm/pgtable.h @@ -14,6 +14,7 @@ * This work is licensed under the terms of the GNU GPL, version 2. */ #include +#include #include #include #include From patchwork Tue Oct 1 10:23:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168405 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6B5F416B1 for ; Tue, 1 Oct 2019 10:23:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4AE6921D56 for ; Tue, 1 Oct 2019 10:23:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730098AbfJAKXo (ORCPT ); Tue, 1 Oct 2019 06:23:44 -0400 Received: from foss.arm.com ([217.140.110.172]:45884 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730018AbfJAKXo (ORCPT ); Tue, 1 Oct 2019 06:23:44 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D19A91000; Tue, 1 Oct 2019 03:23:43 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8CF943F739; Tue, 1 Oct 2019 03:23:42 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 04/19] lib: arm: Implement flush_tlb_all Date: Tue, 1 Oct 2019 11:23:08 +0100 Message-Id: <20191001102323.27628-5-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org flush_tlb_all performs a TLBIALL, which affects only the executing PE; fix that by executing a TLBIALLIS. Note that virtualization extensions imply the multiprocessing extensions, so we're safe to use that instruction. While we're at it, let's add a comment to flush_dcache_addr stating what instruction is uses (unsurprisingly, it's a dcache clean and invalidate to PoC). Signed-off-by: Alexandru Elisei --- lib/arm/asm/mmu.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/arm/asm/mmu.h b/lib/arm/asm/mmu.h index 915c2b07dead..e64a900a45a6 100644 --- a/lib/arm/asm/mmu.h +++ b/lib/arm/asm/mmu.h @@ -25,8 +25,10 @@ static inline void local_flush_tlb_all(void) static inline void flush_tlb_all(void) { - //TODO - local_flush_tlb_all(); + /* TLBIALLIS */ + asm volatile("mcr p15, 0, %0, c8, c3, 0" :: "r" (0)); + dsb(); + isb(); } static inline void flush_tlb_page(unsigned long vaddr) @@ -39,6 +41,7 @@ static inline void flush_tlb_page(unsigned long vaddr) static inline void flush_dcache_addr(unsigned long vaddr) { + /* DCCIMVAC */ asm volatile("mcr p15, 0, %0, c7, c14, 1" :: "r" (vaddr)); } From patchwork Tue Oct 1 10:23:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168407 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 39A2A13B1 for ; Tue, 1 Oct 2019 10:23:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2399221D79 for ; Tue, 1 Oct 2019 10:23:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730246AbfJAKXq (ORCPT ); Tue, 1 Oct 2019 06:23:46 -0400 Received: from foss.arm.com ([217.140.110.172]:45898 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730389AbfJAKXp (ORCPT ); Tue, 1 Oct 2019 06:23:45 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4CFE81570; Tue, 1 Oct 2019 03:23:45 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 1282C3F739; Tue, 1 Oct 2019 03:23:43 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 05/19] arm/arm64: selftest: Add prefetch abort test Date: Tue, 1 Oct 2019 11:23:09 +0100 Message-Id: <20191001102323.27628-6-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When a guest tries to execute code from MMIO memory, KVM injects an external abort into that guest. We have now fixed the psci test to not fetch instructions from the I/O region, and it's not that often that a guest misbehaves in such a way. Let's expand our coverage by adding a proper test targetting this corner case. Signed-off-by: Alexandru Elisei --- Changes: * Folded prep_io_exec into check_pabt because the code paths for arm and arm64 had nothing in common anymore. * Took a closer look at the ARM ARM (for both architectures) and it turns out that a full TLB invalidation is required when changing SCTLR.WXN. And user writable pages implies PXN only on arm64. * Kept the flush_dcache_addr after changing the tables in check_pabt because removing the dcache maintenance when updating the tables is a bit more involved; working on a patch series to fix that and other things, will update this once it gets merged. lib/arm64/asm/esr.h | 3 ++ arm/selftest.c | 102 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/lib/arm64/asm/esr.h b/lib/arm64/asm/esr.h index 8e5af4d90767..8c351631b0a0 100644 --- a/lib/arm64/asm/esr.h +++ b/lib/arm64/asm/esr.h @@ -44,4 +44,7 @@ #define ESR_EL1_EC_BKPT32 (0x38) #define ESR_EL1_EC_BRK64 (0x3C) +#define ESR_EL1_FSC_MASK (0x3F) +#define ESR_EL1_FSC_EXTABT (0x10) + #endif /* _ASMARM64_ESR_H_ */ diff --git a/arm/selftest.c b/arm/selftest.c index 28a17f7a7531..cdf2d1f2badb 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include static void __user_psci_system_off(void) { @@ -60,9 +62,11 @@ static void check_setup(int argc, char **argv) report_abort("missing input"); } + static struct pt_regs expected_regs; static bool und_works; static bool svc_works; +static bool pabt_works; #if defined(__arm__) /* * Capture the current register state and execute an instruction @@ -86,7 +90,7 @@ static bool svc_works; "str r1, [r0, #" xstr(S_PC) "]\n" \ excptn_insn "\n" \ post_insns "\n" \ - :: "r" (&expected_regs) : "r0", "r1") + :: "r" (&expected_regs) : "r0", "r1", "r2") static bool check_regs(struct pt_regs *regs) { @@ -166,6 +170,45 @@ static void user_psci_system_off(struct pt_regs *regs) { __user_psci_system_off(); } + +static void check_pabt_exit(void) +{ + install_exception_handler(EXCPTN_PABT, NULL); + + report("pabt", pabt_works); + exit(report_summary()); +} + +static void pabt_handler(struct pt_regs *regs) +{ + expected_regs.ARM_pc = 0; + pabt_works = check_regs(regs); + + regs->ARM_pc = (unsigned long)&check_pabt_exit; +} + +static void check_pabt(void) +{ + unsigned long sctlr; + + /* Make sure we can actually execute from a writable region */ + asm volatile("mrc p15, 0, %0, c1, c0, 0": "=r" (sctlr)); + if (sctlr & CR_ST) { + sctlr &= ~CR_ST; + asm volatile("mcr p15, 0, %0, c1, c0, 0" :: "r" (sctlr)); + isb(); + /* + * Required according to the sequence in ARM DDI 0406C.d, page + * B3-1358. + */ + flush_tlb_all(); + } + + install_exception_handler(EXCPTN_PABT, pabt_handler); + + test_exception("mov r2, #0x0", "bx r2", ""); + __builtin_unreachable(); +} #elif defined(__aarch64__) /* @@ -207,7 +250,7 @@ static void user_psci_system_off(struct pt_regs *regs) "stp x0, x1, [x1]\n" \ "1:" excptn_insn "\n" \ post_insns "\n" \ - :: "r" (&expected_regs) : "x0", "x1") + :: "r" (&expected_regs) : "x0", "x1", "x2") static bool check_regs(struct pt_regs *regs) { @@ -283,6 +326,57 @@ static bool check_svc(void) return svc_works; } +static void check_pabt_exit(void) +{ + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_IABT_EL1, NULL); + + report("pabt", pabt_works); + exit(report_summary()); +} + +static void pabt_handler(struct pt_regs *regs, unsigned int esr) +{ + bool is_extabt; + + expected_regs.pc = 0; + is_extabt = (esr & ESR_EL1_FSC_MASK) == ESR_EL1_FSC_EXTABT; + pabt_works = check_regs(regs) && is_extabt; + + regs->pc = (u64)&check_pabt_exit; +} + +extern pgd_t *mmu_idmap; +static void check_pabt(void) +{ + pgd_t *pgd = pgd_offset(mmu_idmap, 0); + enum vector v = check_vector_prep(); + unsigned long sctlr; + + /* + * According to ARM DDI 0487E.a, table D5-33, footnote c, all regions + * writable at EL0 are treated as PXN. Clear the user bit so we can + * execute code from the bottom I/O space (0G-1G) to simulate a + * misbehaved guest. + */ + pgd_val(*pgd) &= ~PMD_SECT_USER; + flush_dcache_addr(0); + flush_tlb_page(0); + + /* Make sure we can actually execute from a writable region */ + sctlr = read_sysreg(sctlr_el1); + if (sctlr & SCTLR_EL1_WXN) { + write_sysreg(sctlr & ~SCTLR_EL1_WXN, sctlr_el1); + isb(); + /* SCTLR_EL1.WXN is permitted to be cached in a TLB. */ + flush_tlb_all(); + } + + install_exception_handler(v, ESR_EL1_EC_IABT_EL1, pabt_handler); + + test_exception("mov x2, xzr", "br x2", ""); + __builtin_unreachable(); +} + static void user_psci_system_off(struct pt_regs *regs, unsigned int esr) { __user_psci_system_off(); @@ -293,7 +387,9 @@ static void check_vectors(void *arg __unused) { report("und", check_und()); report("svc", check_svc()); - if (is_user()) { + if (!is_user()) { + check_pabt(); + } else { #ifdef __arm__ install_exception_handler(EXCPTN_UND, user_psci_system_off); #else From patchwork Tue Oct 1 10:23:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168409 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A1AE516B1 for ; Tue, 1 Oct 2019 10:23:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8B03121D82 for ; Tue, 1 Oct 2019 10:23:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730291AbfJAKXr (ORCPT ); Tue, 1 Oct 2019 06:23:47 -0400 Received: from foss.arm.com ([217.140.110.172]:45912 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730153AbfJAKXr (ORCPT ); Tue, 1 Oct 2019 06:23:47 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C0A9A1000; Tue, 1 Oct 2019 03:23:46 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8609C3F739; Tue, 1 Oct 2019 03:23:45 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 06/19] arm64: timer: Write to ICENABLER to disable timer IRQ Date: Tue, 1 Oct 2019 11:23:10 +0100 Message-Id: <20191001102323.27628-7-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org According the Generic Interrupt Controller versions 2, 3 and 4 architecture specifications, a write of 0 to the GIC{D,R}_ISENABLER{,0} registers is ignored; this is also how KVM emulates the corresponding register. Write instead to the ICENABLER register when disabling the timer interrupt. Note that fortunately for us, the timer test was still working as intended because KVM does the sensible thing and all interrupts are disabled by default when creating a VM. Signed-off-by: Alexandru Elisei --- lib/arm/asm/gic-v3.h | 1 + lib/arm/asm/gic.h | 1 + arm/timer.c | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index 347be2f9da17..0dc838b3ab2d 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -31,6 +31,7 @@ /* Re-Distributor registers, offsets from SGI_base */ #define GICR_IGROUPR0 GICD_IGROUPR #define GICR_ISENABLER0 GICD_ISENABLER +#define GICR_ICENABLER0 GICD_ICENABLER #define GICR_IPRIORITYR0 GICD_IPRIORITYR #define ICC_SGI1R_AFFINITY_1_SHIFT 16 diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index f6dfb907a7d5..a67111607bcf 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -15,6 +15,7 @@ #define GICD_IIDR 0x0008 #define GICD_IGROUPR 0x0080 #define GICD_ISENABLER 0x0100 +#define GICD_ICENABLER 0x0180 #define GICD_ISPENDR 0x0200 #define GICD_ICPENDR 0x0280 #define GICD_ISACTIVER 0x0300 diff --git a/arm/timer.c b/arm/timer.c index f2f60192ba62..78f0dd870993 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -17,6 +17,9 @@ #define ARCH_TIMER_CTL_ISTATUS (1 << 2) static void *gic_ispendr; +static void *gic_isenabler; +static void *gic_icenabler; + static bool ptimer_unsupported; static void ptimer_unsupported_handler(struct pt_regs *regs, unsigned int esr) @@ -132,19 +135,12 @@ static struct timer_info ptimer_info = { static void set_timer_irq_enabled(struct timer_info *info, bool enabled) { - u32 val = 0; + u32 val = 1 << PPI(info->irq); if (enabled) - val = 1 << PPI(info->irq); - - switch (gic_version()) { - case 2: - writel(val, gicv2_dist_base() + GICD_ISENABLER + 0); - break; - case 3: - writel(val, gicv3_sgi_base() + GICR_ISENABLER0); - break; - } + writel(val, gic_isenabler); + else + writel(val, gic_icenabler); } static void irq_handler(struct pt_regs *regs) @@ -305,9 +301,13 @@ static void test_init(void) switch (gic_version()) { case 2: gic_ispendr = gicv2_dist_base() + GICD_ISPENDR; + gic_isenabler = gicv2_dist_base() + GICD_ISENABLER; + gic_icenabler = gicv2_dist_base() + GICD_ICENABLER; break; case 3: gic_ispendr = gicv3_sgi_base() + GICD_ISPENDR; + gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0; + gic_icenabler = gicv3_sgi_base() + GICR_ICENABLER0; break; } From patchwork Tue Oct 1 10:23:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168411 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E4CB216B1 for ; Tue, 1 Oct 2019 10:23:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C1FF921D82 for ; Tue, 1 Oct 2019 10:23:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730402AbfJAKXt (ORCPT ); Tue, 1 Oct 2019 06:23:49 -0400 Received: from foss.arm.com ([217.140.110.172]:45922 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730401AbfJAKXs (ORCPT ); Tue, 1 Oct 2019 06:23:48 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4072F1570; Tue, 1 Oct 2019 03:23:48 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 03A303F739; Tue, 1 Oct 2019 03:23:46 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 07/19] arm64: timer: EOIR the interrupt after masking the timer Date: Tue, 1 Oct 2019 11:23:11 +0100 Message-Id: <20191001102323.27628-8-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Writing to the EOIR register before masking the HW mapped timer interrupt can cause taking another timer interrupt immediatly after exception return. This doesn't happen all the time, because KVM reevaluates the state of pending HW mapped level sensitive interrupts on each guest exit. If a guest exit occurs after masking the timer interrupt, but before the ERET, when the extra interrupt is pending, then KVM will remove it. Move the write after the IMASK bit has been set to prevent this from happening. Signed-off-by: Alexandru Elisei --- arm/timer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arm/timer.c b/arm/timer.c index 78f0dd870993..7ae169bd687e 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -149,8 +149,8 @@ static void irq_handler(struct pt_regs *regs) u32 irqstat = gic_read_iar(); u32 irqnr = gic_iar_irqnr(irqstat); - if (irqnr != GICC_INT_SPURIOUS) - gic_write_eoir(irqstat); + if (irqnr == GICC_INT_SPURIOUS) + return; if (irqnr == PPI(vtimer_info.irq)) { info = &vtimer_info; @@ -162,7 +162,11 @@ static void irq_handler(struct pt_regs *regs) } info->write_ctl(ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE); + isb(); + info->irq_received = true; + + gic_write_eoir(irqstat); } static bool gic_timer_pending(struct timer_info *info) From patchwork Tue Oct 1 10:23:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168413 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5C2B613B1 for ; Tue, 1 Oct 2019 10:23:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3A6CC21D82 for ; Tue, 1 Oct 2019 10:23:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730463AbfJAKXu (ORCPT ); Tue, 1 Oct 2019 06:23:50 -0400 Received: from foss.arm.com ([217.140.110.172]:45936 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730153AbfJAKXu (ORCPT ); Tue, 1 Oct 2019 06:23:50 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B85D71596; Tue, 1 Oct 2019 03:23:49 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 75F883F739; Tue, 1 Oct 2019 03:23:48 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 08/19] arm64: timer: Test behavior when timer disabled or masked Date: Tue, 1 Oct 2019 11:23:12 +0100 Message-Id: <20191001102323.27628-9-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When the timer is disabled (the ENABLE bit is clear) or the timer interrupt is masked at the timer level (the IMASK bit is set), timer interrupts must not be pending or asserted by the VGIC. However, when the timer interrupt is masked, we can still check that the timer condition is met by reading the ISTATUS bit. Signed-off-by: Alexandru Elisei --- arm/timer.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arm/timer.c b/arm/timer.c index 7ae169bd687e..125b9f30ad3c 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -230,9 +230,17 @@ static void test_timer(struct timer_info *info) /* Disable the timer again and prepare to take interrupts */ info->write_ctl(0); + isb(); + info->irq_received = false; set_timer_irq_enabled(info, true); + report("no interrupt when timer is disabled", !info->irq_received); report("interrupt signal no longer pending", !gic_timer_pending(info)); + info->write_ctl(ARCH_TIMER_CTL_ENABLE | ARCH_TIMER_CTL_IMASK); + isb(); + report("interrupt signal not pending", !gic_timer_pending(info)); + report("timer condition met", info->read_ctl() & ARCH_TIMER_CTL_ISTATUS); + report("latency within 10 ms", test_cval_10msec(info)); report("interrupt received", info->irq_received); From patchwork Tue Oct 1 10:23:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168415 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 880FF13B1 for ; Tue, 1 Oct 2019 10:23:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 67F52222BE for ; Tue, 1 Oct 2019 10:23:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730415AbfJAKXw (ORCPT ); Tue, 1 Oct 2019 06:23:52 -0400 Received: from foss.arm.com ([217.140.110.172]:45950 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730406AbfJAKXv (ORCPT ); Tue, 1 Oct 2019 06:23:51 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3E4591000; Tue, 1 Oct 2019 03:23:51 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id F099F3F739; Tue, 1 Oct 2019 03:23:49 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 09/19] lib: arm/arm64: Refuse to disable the MMU with non-identity stack pointer Date: Tue, 1 Oct 2019 11:23:13 +0100 Message-Id: <20191001102323.27628-10-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When the MMU is off, all addresses are physical addresses. If the stack pointer is not an identity mapped address (the virtual address is not the same as the physical address), then we end up trying to access an invalid memory region. This can happen if we call mmu_disable from a secondary CPU, which has its stack allocated from the vmalloc region. Reviewed-by: Andrew Jones Signed-off-by: Alexandru Elisei --- lib/arm/mmu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 3d38c8397f5a..161f7a8e607c 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -66,8 +66,12 @@ void mmu_enable(pgd_t *pgtable) extern void asm_mmu_disable(void); void mmu_disable(void) { + unsigned long sp = current_stack_pointer; int cpu = current_thread_info()->cpu; + assert_msg(__virt_to_phys(sp) == sp, + "Attempting to disable MMU with non-identity mapped stack"); + mmu_mark_disabled(cpu); asm_mmu_disable(); From patchwork Tue Oct 1 10:23:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168417 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E90F91902 for ; Tue, 1 Oct 2019 10:23:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CA16E222BE for ; Tue, 1 Oct 2019 10:23:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730469AbfJAKXy (ORCPT ); Tue, 1 Oct 2019 06:23:54 -0400 Received: from foss.arm.com ([217.140.110.172]:45962 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730442AbfJAKXx (ORCPT ); Tue, 1 Oct 2019 06:23:53 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B555C1570; Tue, 1 Oct 2019 03:23:52 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 779F73F739; Tue, 1 Oct 2019 03:23:51 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 10/19] arm/arm64: Perform dcache clean + invalidate after turning MMU off Date: Tue, 1 Oct 2019 11:23:14 +0100 Message-Id: <20191001102323.27628-11-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When the MMU is off, data accesses are to Device nGnRnE memory on arm64 [1] or to Strongly-Ordered memory on arm [2]. This means that the accesses are non-cacheable. Perform a dcache clean to PoC so we can read the newer values from the cache, instead of the stale values from memory. Perform an invalidation so when we turn the MMU on, we can access the data written to memory while the MMU was off, instead of potentially stale values from the cache. Data caches are PIPT and the VAs are translated using the current translation tables, or an identity mapping (what Arm calls a "flat mapping") when the MMU is off [1][2]. Do the clean + invalidate when the MMU is off so we don't depend on the current translation tables and we can make sure that the operation applies to the entire physical memory. [1] ARM DDI 0487E.a, section D5.2.9 [2] ARM DDI 0406C.d, section B3.2.1 Signed-off-by: Alexandru Elisei --- lib/arm/asm/processor.h | 6 ++++++ lib/arm64/asm/processor.h | 6 ++++++ lib/arm/processor.c | 10 ++++++++++ lib/arm/setup.c | 2 ++ lib/arm64/processor.c | 11 +++++++++++ arm/cstart.S | 22 ++++++++++++++++++++++ arm/cstart64.S | 23 +++++++++++++++++++++++ 7 files changed, 80 insertions(+) diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h index a8c4628da818..4684fb4755b3 100644 --- a/lib/arm/asm/processor.h +++ b/lib/arm/asm/processor.h @@ -9,6 +9,11 @@ #include #include +#define CTR_DMINLINE_SHIFT 16 +#define CTR_DMINLINE_MASK (0xf << 16) +#define CTR_DMINLINE(x) \ + (((x) & CTR_DMINLINE_MASK) >> CTR_DMINLINE_SHIFT) + enum vector { EXCPTN_RST, EXCPTN_UND, @@ -25,6 +30,7 @@ typedef void (*exception_fn)(struct pt_regs *); extern void install_exception_handler(enum vector v, exception_fn fn); extern void show_regs(struct pt_regs *regs); +extern void init_dcache_line_size(void); static inline unsigned long current_cpsr(void) { diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 1d9223f728a5..fd508c02f30d 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -16,6 +16,11 @@ #define SCTLR_EL1_A (1 << 1) #define SCTLR_EL1_M (1 << 0) +#define CTR_EL0_DMINLINE_SHIFT 16 +#define CTR_EL0_DMINLINE_MASK (0xf << 16) +#define CTR_EL0_DMINLINE(x) \ + (((x) & CTR_EL0_DMINLINE_MASK) >> CTR_EL0_DMINLINE_SHIFT) + #ifndef __ASSEMBLY__ #include #include @@ -60,6 +65,7 @@ extern void vector_handlers_default_init(vector_fn *handlers); extern void show_regs(struct pt_regs *regs); extern bool get_far(unsigned int esr, unsigned long *far); +extern void init_dcache_line_size(void); static inline unsigned long current_level(void) { diff --git a/lib/arm/processor.c b/lib/arm/processor.c index 773337e6d3b7..c57657c5ea53 100644 --- a/lib/arm/processor.c +++ b/lib/arm/processor.c @@ -25,6 +25,8 @@ static const char *vector_names[] = { "rst", "und", "svc", "pabt", "dabt", "addrexcptn", "irq", "fiq" }; +unsigned int dcache_line_size; + void show_regs(struct pt_regs *regs) { unsigned long flags; @@ -145,3 +147,11 @@ bool is_user(void) { return current_thread_info()->flags & TIF_USER_MODE; } +void init_dcache_line_size(void) +{ + u32 ctr; + + asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); + /* DminLine is log2 of the number of words in the smallest cache line */ + dcache_line_size = 1 << (CTR_DMINLINE(ctr) + 2); +} diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 4f02fca85607..54fc19a20942 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "io.h" @@ -63,6 +64,7 @@ static void cpu_init(void) ret = dt_for_each_cpu_node(cpu_set, NULL); assert(ret == 0); set_cpu_online(0, true); + init_dcache_line_size(); } static void mem_init(phys_addr_t freemem_start) diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c index 2a024e3f4e9d..f28066d40145 100644 --- a/lib/arm64/processor.c +++ b/lib/arm64/processor.c @@ -62,6 +62,8 @@ static const char *ec_names[EC_MAX] = { [ESR_EL1_EC_BRK64] = "BRK64", }; +unsigned int dcache_line_size; + void show_regs(struct pt_regs *regs) { int i; @@ -257,3 +259,12 @@ bool is_user(void) { return current_thread_info()->flags & TIF_USER_MODE; } + +void init_dcache_line_size(void) +{ + u64 ctr; + + ctr = read_sysreg(ctr_el0); + /* DminLine is log2 of the number of words in the smallest cache line */ + dcache_line_size = 1 << (CTR_EL0_DMINLINE(ctr) + 2); +} diff --git a/arm/cstart.S b/arm/cstart.S index 112124f222cb..c8bbb4f0a2a2 100644 --- a/arm/cstart.S +++ b/arm/cstart.S @@ -185,6 +185,20 @@ asm_mmu_enable: mov pc, lr +.macro dcache_clean_inval domain, start, end, tmp1, tmp2 + ldr \tmp1, =dcache_line_size + ldr \tmp1, [\tmp1] + sub \tmp2, \tmp1, #1 + bic \start, \start, \tmp2 +9998: + /* DCCIMVAC */ + mcr p15, 0, \start, c7, c14, 1 + add \start, \start, \tmp1 + cmp \start, \end + blo 9998b + dsb \domain +.endm + .globl asm_mmu_disable asm_mmu_disable: /* SCTLR */ @@ -192,6 +206,14 @@ asm_mmu_disable: bic r0, #CR_M mcr p15, 0, r0, c1, c0, 0 isb + + ldr r0, =__phys_offset + ldr r0, [r0] + ldr r1, =__phys_end + ldr r1, [r1] + dcache_clean_inval sy, r0, r1, r2, r3 + isb + mov pc, lr /* diff --git a/arm/cstart64.S b/arm/cstart64.S index c98842f11e90..f41ffa3bc6c2 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -201,12 +201,35 @@ asm_mmu_enable: ret +/* Taken with small changes from arch/arm64/incluse/asm/assembler.h */ +.macro dcache_by_line_op op, domain, start, end, tmp1, tmp2 + adrp \tmp1, dcache_line_size + ldr \tmp1, [\tmp1, :lo12:dcache_line_size] + sub \tmp2, \tmp1, #1 + bic \start, \start, \tmp2 +9998: + dc \op , \start + add \start, \start, \tmp1 + cmp \start, \end + b.lo 9998b + dsb \domain +.endm + .globl asm_mmu_disable asm_mmu_disable: mrs x0, sctlr_el1 bic x0, x0, SCTLR_EL1_M msr sctlr_el1, x0 isb + + /* Clean + invalidate the entire memory */ + adrp x0, __phys_offset + ldr x0, [x0, :lo12:__phys_offset] + adrp x1, __phys_end + ldr x1, [x1, :lo12:__phys_end] + dcache_by_line_op civac, sy, x0, x1, x2, x3 + isb + ret /* From patchwork Tue Oct 1 10:23:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168419 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3081F16B1 for ; Tue, 1 Oct 2019 10:23:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 18D77222C3 for ; Tue, 1 Oct 2019 10:23:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730464AbfJAKXy (ORCPT ); Tue, 1 Oct 2019 06:23:54 -0400 Received: from foss.arm.com ([217.140.110.172]:45970 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730474AbfJAKXy (ORCPT ); Tue, 1 Oct 2019 06:23:54 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 385DD15A2; Tue, 1 Oct 2019 03:23:54 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EA30A3F739; Tue, 1 Oct 2019 03:23:52 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 11/19] arm/cstart64.S: Downgrade TLBI to non-shareable in asm_mmu_enable Date: Tue, 1 Oct 2019 11:23:15 +0100 Message-Id: <20191001102323.27628-12-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org There's really no need to invalidate the TLB entries for all CPUs when enabling the MMU for the current CPU, so use the non-shareable version of the TLBI operation (and downgrade the DSB accordingly). Signed-off-by: Alexandru Elisei --- arm/cstart64.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arm/cstart64.S b/arm/cstart64.S index f41ffa3bc6c2..87bf873795a1 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -167,8 +167,8 @@ halt: .globl asm_mmu_enable asm_mmu_enable: ic iallu // I+BTB cache invalidate - tlbi vmalle1is // invalidate I + D TLBs - dsb ish + tlbi vmalle1 // invalidate I + D TLBs + dsb nsh /* TCR */ ldr x1, =TCR_TxSZ(VA_BITS) | \ From patchwork Tue Oct 1 10:23:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168421 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9F72D13B1 for ; Tue, 1 Oct 2019 10:23:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7E6F2222C3 for ; Tue, 1 Oct 2019 10:23:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730447AbfJAKX4 (ORCPT ); Tue, 1 Oct 2019 06:23:56 -0400 Received: from foss.arm.com ([217.140.110.172]:45988 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726655AbfJAKX4 (ORCPT ); Tue, 1 Oct 2019 06:23:56 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AA7DD1000; Tue, 1 Oct 2019 03:23:55 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6F62D3F739; Tue, 1 Oct 2019 03:23:54 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 12/19] arm/arm64: Invalidate TLB before enabling MMU Date: Tue, 1 Oct 2019 11:23:16 +0100 Message-Id: <20191001102323.27628-13-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Let's invalidate the TLB before enabling the MMU, not after, so we don't accidently use a stale TLB mapping. For arm, we add a TLBIALL operation, which applies only to the PE that executed the instruction [1]. For arm64, we already do that in asm_mmu_enable. We now find ourselves in a situation where we issue an extra invalidation after asm_mmu_enable returns. Remove this redundant call to tlb_flush_all. [1] ARM DDI 0406C.d, section B3.10.6 Reviewed-by: Andrew Jones Signed-off-by: Alexandru Elisei --- Changes: * Reworded the commit message a bit, but I figured the changes are small and so I kept the Reviewed-by. lib/arm/mmu.c | 1 - arm/cstart.S | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 161f7a8e607c..66a05d789386 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -57,7 +57,6 @@ void mmu_enable(pgd_t *pgtable) struct thread_info *info = current_thread_info(); asm_mmu_enable(__pa(pgtable)); - flush_tlb_all(); info->pgtable = pgtable; mmu_mark_enabled(info->cpu); diff --git a/arm/cstart.S b/arm/cstart.S index c8bbb4f0a2a2..748548c3b516 100644 --- a/arm/cstart.S +++ b/arm/cstart.S @@ -160,6 +160,10 @@ halt: .equ NMRR, 0xff000004 @ MAIR1 (from Linux kernel) .globl asm_mmu_enable asm_mmu_enable: + /* TLBIALL */ + mcr p15, 0, r2, c8, c7, 0 + dsb ish + /* TTBCR */ mrc p15, 0, r2, c2, c0, 2 orr r2, #(1 << 31) @ TTB_EAE From patchwork Tue Oct 1 10:23:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168423 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 81D4716B1 for ; Tue, 1 Oct 2019 10:23:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6AB5B222C2 for ; Tue, 1 Oct 2019 10:23:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730515AbfJAKX6 (ORCPT ); Tue, 1 Oct 2019 06:23:58 -0400 Received: from foss.arm.com ([217.140.110.172]:45998 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730401AbfJAKX5 (ORCPT ); Tue, 1 Oct 2019 06:23:57 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 26F761570; Tue, 1 Oct 2019 03:23:57 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id E1BC23F739; Tue, 1 Oct 2019 03:23:55 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 13/19] lib: Add _UL and _ULL definitions to linux/const.h Date: Tue, 1 Oct 2019 11:23:17 +0100 Message-Id: <20191001102323.27628-14-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org There is an UL macro defined in lib/arm64/asm/pgtable-hwdef.h. Replace it with the _UL macro and put it in lib/linux/const.h, where it can be used in other files. To keep things consistent with Linux's include/uapi/linux/const.h file, also add an _ULL macro. Signed-off-by: Alexandru Elisei --- Changes: * Renamed UL->_UL and ULL->_ULL. * Replaced some uses of _AC(x, UL) with _UL(x). Same for ULL. lib/linux/const.h | 7 +++-- lib/arm64/asm/pgtable-hwdef.h | 50 +++++++++++++++++------------------ 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/lib/linux/const.h b/lib/linux/const.h index c872bfd25e13..1453a886d041 100644 --- a/lib/linux/const.h +++ b/lib/linux/const.h @@ -21,7 +21,10 @@ #define _AT(T,X) ((T)(X)) #endif -#define _BITUL(x) (_AC(1,UL) << (x)) -#define _BITULL(x) (_AC(1,ULL) << (x)) +#define _UL(x) _AC(x, UL) +#define _ULL(x) _AC(x, ULL) + +#define _BITUL(x) (_UL(1) << (x)) +#define _BITULL(x) (_ULL(1) << (x)) #endif /* !(_LINUX_CONST_H) */ diff --git a/lib/arm64/asm/pgtable-hwdef.h b/lib/arm64/asm/pgtable-hwdef.h index 045a3ce12645..f183b48dec5d 100644 --- a/lib/arm64/asm/pgtable-hwdef.h +++ b/lib/arm64/asm/pgtable-hwdef.h @@ -9,8 +9,6 @@ * This work is licensed under the terms of the GNU GPL, version 2. */ -#define UL(x) _AC(x, UL) - #define PTRS_PER_PTE (1 << (PAGE_SHIFT - 3)) /* @@ -18,21 +16,21 @@ * (depending on the configuration, this level can be 0, 1 or 2). */ #define PGDIR_SHIFT ((PAGE_SHIFT - 3) * PGTABLE_LEVELS + 3) -#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) +#define PGDIR_SIZE (_UL(1) << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) #define PTRS_PER_PGD (1 << (VA_BITS - PGDIR_SHIFT)) /* From include/asm-generic/pgtable-nopmd.h */ #define PMD_SHIFT PGDIR_SHIFT #define PTRS_PER_PMD 1 -#define PMD_SIZE (UL(1) << PMD_SHIFT) +#define PMD_SIZE (_UL(1) << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) /* * Section address mask and size definitions. */ #define SECTION_SHIFT PMD_SHIFT -#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT) +#define SECTION_SIZE (_UL(1) << SECTION_SHIFT) #define SECTION_MASK (~(SECTION_SIZE-1)) /* @@ -90,31 +88,31 @@ * Highest possible physical address supported. */ #define PHYS_MASK_SHIFT (48) -#define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) +#define PHYS_MASK ((_UL(1) << PHYS_MASK_SHIFT) - 1) /* * TCR flags. */ -#define TCR_TxSZ(x) (((UL(64) - (x)) << 16) | ((UL(64) - (x)) << 0)) -#define TCR_IRGN_NC ((UL(0) << 8) | (UL(0) << 24)) -#define TCR_IRGN_WBWA ((UL(1) << 8) | (UL(1) << 24)) -#define TCR_IRGN_WT ((UL(2) << 8) | (UL(2) << 24)) -#define TCR_IRGN_WBnWA ((UL(3) << 8) | (UL(3) << 24)) -#define TCR_IRGN_MASK ((UL(3) << 8) | (UL(3) << 24)) -#define TCR_ORGN_NC ((UL(0) << 10) | (UL(0) << 26)) -#define TCR_ORGN_WBWA ((UL(1) << 10) | (UL(1) << 26)) -#define TCR_ORGN_WT ((UL(2) << 10) | (UL(2) << 26)) -#define TCR_ORGN_WBnWA ((UL(3) << 10) | (UL(3) << 26)) -#define TCR_ORGN_MASK ((UL(3) << 10) | (UL(3) << 26)) -#define TCR_SHARED ((UL(3) << 12) | (UL(3) << 28)) -#define TCR_TG0_4K (UL(0) << 14) -#define TCR_TG0_64K (UL(1) << 14) -#define TCR_TG0_16K (UL(2) << 14) -#define TCR_TG1_16K (UL(1) << 30) -#define TCR_TG1_4K (UL(2) << 30) -#define TCR_TG1_64K (UL(3) << 30) -#define TCR_ASID16 (UL(1) << 36) -#define TCR_TBI0 (UL(1) << 37) +#define TCR_TxSZ(x) (((_UL(64) - (x)) << 16) | ((_UL(64) - (x)) << 0)) +#define TCR_IRGN_NC ((_UL(0) << 8) | (_UL(0) << 24)) +#define TCR_IRGN_WBWA ((_UL(1) << 8) | (_UL(1) << 24)) +#define TCR_IRGN_WT ((_UL(2) << 8) | (_UL(2) << 24)) +#define TCR_IRGN_WBnWA ((_UL(3) << 8) | (_UL(3) << 24)) +#define TCR_IRGN_MASK ((_UL(3) << 8) | (_UL(3) << 24)) +#define TCR_ORGN_NC ((_UL(0) << 10) | (_UL(0) << 26)) +#define TCR_ORGN_WBWA ((_UL(1) << 10) | (_UL(1) << 26)) +#define TCR_ORGN_WT ((_UL(2) << 10) | (_UL(2) << 26)) +#define TCR_ORGN_WBnWA ((_UL(3) << 10) | (_UL(3) << 26)) +#define TCR_ORGN_MASK ((_UL(3) << 10) | (_UL(3) << 26)) +#define TCR_SHARED ((_UL(3) << 12) | (_UL(3) << 28)) +#define TCR_TG0_4K (_UL(0) << 14) +#define TCR_TG0_64K (_UL(1) << 14) +#define TCR_TG0_16K (_UL(2) << 14) +#define TCR_TG1_16K (_UL(1) << 30) +#define TCR_TG1_4K (_UL(2) << 30) +#define TCR_TG1_64K (_UL(3) << 30) +#define TCR_ASID16 (_UL(1) << 36) +#define TCR_TBI0 (_UL(1) << 37) /* * Memory types available. From patchwork Tue Oct 1 10:23:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168425 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A0C6A16B1 for ; Tue, 1 Oct 2019 10:24:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 76D53222CB for ; Tue, 1 Oct 2019 10:24:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730491AbfJAKYA (ORCPT ); Tue, 1 Oct 2019 06:24:00 -0400 Received: from foss.arm.com ([217.140.110.172]:46012 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730521AbfJAKYA (ORCPT ); Tue, 1 Oct 2019 06:24:00 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B65B01596; Tue, 1 Oct 2019 03:23:58 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6063C3F739; Tue, 1 Oct 2019 03:23:57 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 14/19] lib: arm64: Run existing tests at EL2 Date: Tue, 1 Oct 2019 11:23:18 +0100 Message-Id: <20191001102323.27628-15-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Version 8.3 of the ARM architecture added support for nested virtualization. KVM supports both VHE and non-VHE guest hypervisors running at virtual EL2. To make the changes as minimal as possible, kvm-unit-tests will run as a VHE guest hypervisor when booted at EL2. To distinguish between a L1 non-VHE host calling from EL1 into the L1 hypervisor running at EL2 and a PSCI call, KVM sets the PSCI conduit for guests that boot at EL2 to the SMC instruction. Modify existing tests to take that into account. Nested virtualization is enabled only for arm64 guests using GICv3 and existing tests have been modified to run at EL2. Signed-off-by: Alexandru Elisei --- Changes: * Added an expected_level variable to the selftest test. Prefetch abort injection is broken with version v1 of the NV patches; to run the abort test, I use the following patch: diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index fac962b467bd..3747a31feefc 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -53,15 +53,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr { unsigned long cpsr = *vcpu_cpsr(vcpu); bool is_aarch32 = vcpu_mode_is_32bit(vcpu); - u32 esr = 0; - - vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu)); - *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync); - - *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64; - vcpu_write_spsr(vcpu, cpsr); - - vcpu_write_sys_reg(vcpu, addr, FAR_EL1); + u32 esr = ESR_ELx_FSC_EXTABT; /* * Build an {i,d}abort, depending on the level and the @@ -82,7 +74,20 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr if (!is_iabt) esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT; - vcpu_write_sys_reg(vcpu, esr | ESR_ELx_FSC_EXTABT, ESR_EL1); + if (is_hyp_ctxt(vcpu)) { + kvm_inject_nested_sync(vcpu, esr); + return; + } + + vcpu_write_sys_reg(vcpu, esr, ESR_EL1); + + vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu)); + *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync); + + *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64; + vcpu_write_spsr(vcpu, cpsr); + + vcpu_write_sys_reg(vcpu, addr, FAR_EL1); } static void inject_undef64(struct kvm_vcpu *vcpu) @@ -103,7 +108,18 @@ static void inject_undef64(struct kvm_vcpu *vcpu) if (kvm_vcpu_trap_il_is32bit(vcpu)) esr |= ESR_ELx_IL; + if (is_hyp_ctxt(vcpu)) { + kvm_inject_nested_sync(vcpu, esr); + return; + } + vcpu_write_sys_reg(vcpu, esr, ESR_EL1); + + vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu)); + *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync); + + *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64; + vcpu_write_spsr(vcpu, cpsr); } /** lib/arm/asm/psci.h | 1 + lib/arm64/asm/esr.h | 2 + lib/arm64/asm/processor.h | 5 ++ lib/arm64/asm/sysreg.h | 20 ++++++ lib/arm/psci.c | 43 ++++++++++++- lib/arm/setup.c | 4 ++ lib/arm64/processor.c | 2 + arm/cstart64.S | 28 +++++++++ arm/micro-bench.c | 17 ++++- arm/selftest.c | 41 +++++++++--- arm/timer.c | 127 +++++++++++++++++++++++++++++++++----- 11 files changed, 261 insertions(+), 29 deletions(-) diff --git a/lib/arm/asm/psci.h b/lib/arm/asm/psci.h index 7b956bf5987d..2ed6613fe5ea 100644 --- a/lib/arm/asm/psci.h +++ b/lib/arm/asm/psci.h @@ -3,6 +3,7 @@ #include #include +extern void psci_init(void); extern int psci_invoke(unsigned long function_id, unsigned long arg0, unsigned long arg1, unsigned long arg2); extern int psci_cpu_on(unsigned long cpuid, unsigned long entry_point); diff --git a/lib/arm64/asm/esr.h b/lib/arm64/asm/esr.h index 8c351631b0a0..6d4f572923f2 100644 --- a/lib/arm64/asm/esr.h +++ b/lib/arm64/asm/esr.h @@ -25,6 +25,8 @@ #define ESR_EL1_EC_ILL_ISS (0x0E) #define ESR_EL1_EC_SVC32 (0x11) #define ESR_EL1_EC_SVC64 (0x15) +#define ESR_EL2_EC_HVC64 (0x16) +#define ESR_EL2_EC_SMC64 (0x17) #define ESR_EL1_EC_SYS64 (0x18) #define ESR_EL1_EC_IABT_EL0 (0x20) #define ESR_EL1_EC_IABT_EL1 (0x21) diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index fd508c02f30d..7e9f76d73f1b 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -6,6 +6,8 @@ * This work is licensed under the terms of the GNU LGPL, version 2. */ +#include + /* System Control Register (SCTLR_EL1) bits */ #define SCTLR_EL1_EE (1 << 25) #define SCTLR_EL1_WXN (1 << 19) @@ -16,6 +18,9 @@ #define SCTLR_EL1_A (1 << 1) #define SCTLR_EL1_M (1 << 0) +#define HCR_EL2_TGE (1 << 27) +#define HCR_EL2_E2H (_UL(1) << 34) + #define CTR_EL0_DMINLINE_SHIFT 16 #define CTR_EL0_DMINLINE_MASK (0xf << 16) #define CTR_EL0_DMINLINE(x) \ diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h index a03830bceb8f..ed407f93330d 100644 --- a/lib/arm64/asm/sysreg.h +++ b/lib/arm64/asm/sysreg.h @@ -11,6 +11,14 @@ #define sys_reg(op0, op1, crn, crm, op2) \ ((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5)) +#define SYS_CNTP_TVAL_EL02 sys_reg(3, 5, 14, 2, 0) +#define SYS_CNTP_CTL_EL02 sys_reg(3, 5, 14, 2, 1) +#define SYS_CNTP_CVAL_EL02 sys_reg(3, 5, 14, 2, 2) + +#define SYS_CNTV_TVAL_EL02 sys_reg(3, 5, 14, 3, 0) +#define SYS_CNTV_CTL_EL02 sys_reg(3, 5, 14, 3, 1) +#define SYS_CNTV_CVAL_EL02 sys_reg(3, 5, 14, 3, 2) + #ifdef __ASSEMBLY__ .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 .equ .L__reg_num_x\num, \num @@ -52,5 +60,17 @@ asm( " .inst 0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n" " .endm\n" ); + +#define read_sysreg_s(r) ({ \ + u64 __val; \ + asm volatile("mrs_s %0, " xstr(r) : "=r" (__val)); \ + __val; \ +}) + +#define write_sysreg_s(v, r) do { \ + u64 __val = (u64)v; \ + asm volatile("msr_s " xstr(r) ", %x0" : : "rZ" (__val));\ +} while (0) + #endif /* __ASSEMBLY__ */ #endif /* _ASMARM64_SYSREG_H_ */ diff --git a/lib/arm/psci.c b/lib/arm/psci.c index 936c83948b6a..f0c571cfc5a3 100644 --- a/lib/arm/psci.c +++ b/lib/arm/psci.c @@ -11,8 +11,10 @@ #include #include -__attribute__((noinline)) -int psci_invoke(unsigned long function_id, unsigned long arg0, +static int (*psci_fn)(unsigned long, unsigned long, unsigned long, + unsigned long); + +static int psci_invoke_hvc(unsigned long function_id, unsigned long arg0, unsigned long arg1, unsigned long arg2) { asm volatile( @@ -22,13 +24,48 @@ int psci_invoke(unsigned long function_id, unsigned long arg0, return function_id; } +#ifdef __arm__ +void psci_init(void) +{ + psci_fn = &psci_invoke_hvc; +} + int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) { -#ifdef __arm__ return psci_invoke(PSCI_0_2_FN_CPU_ON, cpuid, entry_point, 0); +} #else +static int psci_invoke_smc(unsigned long function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2) +{ + asm volatile( + "smc #0" + : "+r" (function_id) + : "r" (arg0), "r" (arg1), "r" (arg2)); + return function_id; +} + +void psci_init(void) +{ + if (current_level() == CurrentEL_EL2) + psci_fn = &psci_invoke_smc; + else + psci_fn = &psci_invoke_hvc; +} + +int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) +{ return psci_invoke(PSCI_0_2_FN64_CPU_ON, cpuid, entry_point, 0); +} #endif + +int psci_invoke(unsigned long function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2) +{ + /* Oh-oh, some went wrong */ + if (!psci_fn) + psci_init(); + return psci_fn(function_id, arg0, arg1, arg2); } extern void secondary_entry(void); diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 54fc19a20942..2f23cb07f4fc 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "io.h" @@ -129,6 +130,9 @@ void setup(const void *fdt) u32 fdt_size; int ret; + /* make sure PSCI calls work as soon as possible */ + psci_init(); + /* * Before calling mem_init we need to move the fdt and initrd * to safe locations. We move them to construct the memory diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c index f28066d40145..2030a7a09107 100644 --- a/lib/arm64/processor.c +++ b/lib/arm64/processor.c @@ -42,6 +42,8 @@ static const char *ec_names[EC_MAX] = { [ESR_EL1_EC_ILL_ISS] = "ILL_ISS", [ESR_EL1_EC_SVC32] = "SVC32", [ESR_EL1_EC_SVC64] = "SVC64", + [ESR_EL2_EC_HVC64] = "HVC64", + [ESR_EL2_EC_SMC64] = "SMC64", [ESR_EL1_EC_SYS64] = "SYS64", [ESR_EL1_EC_IABT_EL0] = "IABT_EL0", [ESR_EL1_EC_IABT_EL1] = "IABT_EL1", diff --git a/arm/cstart64.S b/arm/cstart64.S index 87bf873795a1..acf86eb6089e 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -51,6 +51,17 @@ start: add x5, x5, #24 b 1b +1: + mrs x4, CurrentEL + cmp x4, CurrentEL_EL2 + b.ne 1f + mrs x4, mpidr_el1 + msr vmpidr_el2, x4 + mrs x4, midr_el1 + msr vpidr_el2, x4 + ldr x4, =(HCR_EL2_TGE | HCR_EL2_E2H) + msr hcr_el2, x4 + isb 1: /* set up stack */ mov x4, #1 @@ -102,6 +113,17 @@ get_mmu_off: .globl secondary_entry secondary_entry: + mrs x0, CurrentEL + cmp x0, CurrentEL_EL2 + b.ne 1f + mrs x0, mpidr_el1 + msr vmpidr_el2, x0 + mrs x0, midr_el1 + msr vpidr_el2, x0 + ldr x0, =(HCR_EL2_TGE | HCR_EL2_E2H) + msr hcr_el2, x0 + isb +1: /* Enable FP/ASIMD */ mov x0, #(3 << 20) msr cpacr_el1, x0 @@ -132,6 +154,12 @@ secondary_entry: .globl asm_cpu_psci_cpu_die asm_cpu_psci_cpu_die: ldr x0, =PSCI_0_2_FN_CPU_OFF + mrs x9, CurrentEL + cmp x9, CurrentEL_EL2 + b.ne 1f + smc #0 + b halt +1: hvc #0 b . diff --git a/arm/micro-bench.c b/arm/micro-bench.c index 4612f41001c2..5469667ddfe8 100644 --- a/arm/micro-bench.c +++ b/arm/micro-bench.c @@ -112,6 +112,11 @@ static void hvc_exec(void) asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0"); } +static void smc_exec(void) +{ + asm volatile("mov w0, #0x4b000000; smc #0" ::: "w0"); +} + static void mmio_read_user_exec(void) { /* @@ -138,6 +143,8 @@ static void eoi_exec(void) write_eoir(spurious_id); } +static void exec_select(void); + struct exit_test { const char *name; void (*prep)(void); @@ -146,13 +153,21 @@ struct exit_test { }; static struct exit_test tests[] = { - {"hvc", NULL, hvc_exec, true}, + {"hyp_call", exec_select, hvc_exec, true}, {"mmio_read_user", NULL, mmio_read_user_exec, true}, {"mmio_read_vgic", NULL, mmio_read_vgic_exec, true}, {"eoi", NULL, eoi_exec, true}, {"ipi", ipi_prep, ipi_exec, true}, }; +static void exec_select(void) +{ + if (current_level() == CurrentEL_EL2) + tests[0].exec = &smc_exec; + else + tests[0].exec = &hvc_exec; +} + struct ns_time { uint64_t ns; uint64_t ns_frac; diff --git a/arm/selftest.c b/arm/selftest.c index cdf2d1f2badb..68dd34e59f3d 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -210,6 +210,7 @@ static void check_pabt(void) __builtin_unreachable(); } #elif defined(__aarch64__) +static unsigned long expected_level; /* * Capture the current register state and execute an instruction @@ -256,8 +257,7 @@ static bool check_regs(struct pt_regs *regs) { unsigned i; - /* exception handlers should always run in EL1 */ - if (current_level() != CurrentEL_EL1) + if (current_level() != expected_level) return false; for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) { @@ -275,13 +275,14 @@ static bool check_regs(struct pt_regs *regs) static enum vector check_vector_prep(void) { - unsigned long daif; + unsigned long daif, mode; if (is_user()) return EL0_SYNC_64; asm volatile("mrs %0, daif" : "=r" (daif) ::); - expected_regs.pstate = daif | PSR_MODE_EL1h; + mode = current_level() == CurrentEL_EL1 ? PSR_MODE_EL1h : PSR_MODE_EL2h; + expected_regs.pstate = daif | mode; return EL1H_SYNC; } @@ -297,8 +298,8 @@ static bool check_und(void) install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler); - /* try to read an el2 sysreg from el0/1 */ - test_exception("", "mrs x0, sctlr_el2", ""); + /* try to read an el3 sysreg from el0/1/2 */ + test_exception("", "mrs x0, sctlr_el3", ""); install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL); @@ -385,6 +386,10 @@ static void user_psci_system_off(struct pt_regs *regs, unsigned int esr) static void check_vectors(void *arg __unused) { +#ifdef __aarch64__ + if (!is_user()) + expected_level = current_level(); +#endif report("und", check_und()); report("svc", check_svc()); if (!is_user()) { @@ -416,11 +421,29 @@ static bool psci_check(void) printf("bad psci device tree node\n"); return false; } + if (len != 4) { + printf("bad psci method\n"); + return false; + } + +#ifdef __arm__ + if (strcmp(method->data, "hvc") != 0) { + printf("psci method must be hvc\n"); + return false; + } +#else + if (current_level() == CurrentEL_EL2 && + strcmp(method->data, "smc") != 0) { + printf("psci method must be smc\n"); + return false; + } - if (len < 4 || strcmp(method->data, "hvc") != 0) { + if (current_level() == CurrentEL_EL1 && + strcmp(method->data, "hvc") != 0) { printf("psci method must be hvc\n"); return false; } +#endif ver = psci_invoke(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); printf("PSCI version %d.%d\n", PSCI_VERSION_MAJOR(ver), @@ -456,7 +479,9 @@ int main(int argc, char **argv) check_vectors(NULL); } else if (strcmp(argv[1], "vectors-user") == 0) { - +#if defined(__aarch64__) + expected_level = current_level(); +#endif start_usr(check_vectors, NULL, (unsigned long)thread_stack_alloc()); diff --git a/arm/timer.c b/arm/timer.c index 125b9f30ad3c..29477ee65878 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,36 @@ static void write_vtimer_ctl(u64 val) write_sysreg(val, cntv_ctl_el0); } +static u64 read_vtimer_cval_vhe(void) +{ + return read_sysreg_s(SYS_CNTV_CVAL_EL02); +} + +static void write_vtimer_cval_vhe(u64 val) +{ + write_sysreg_s(val, SYS_CNTV_CVAL_EL02); +} + +static s32 read_vtimer_tval_vhe(void) +{ + return read_sysreg_s(SYS_CNTV_TVAL_EL02); +} + +static void write_vtimer_tval_vhe(s32 val) +{ + write_sysreg_s(val, SYS_CNTV_TVAL_EL02); +} + +static u64 read_vtimer_ctl_vhe(void) +{ + return read_sysreg_s(SYS_CNTV_CTL_EL02); +} + +static void write_vtimer_ctl_vhe(u64 val) +{ + write_sysreg_s(val, SYS_CNTV_CTL_EL02); +} + static u64 read_ptimer_counter(void) { return read_sysreg(cntpct_el0); @@ -98,6 +129,36 @@ static void write_ptimer_ctl(u64 val) write_sysreg(val, cntp_ctl_el0); } +static u64 read_ptimer_cval_vhe(void) +{ + return read_sysreg_s(SYS_CNTP_CVAL_EL02); +} + +static void write_ptimer_cval_vhe(u64 val) +{ + write_sysreg_s(val, SYS_CNTP_CVAL_EL02); +} + +static s32 read_ptimer_tval_vhe(void) +{ + return read_sysreg_s(SYS_CNTP_TVAL_EL02); +} + +static void write_ptimer_tval_vhe(s32 val) +{ + write_sysreg_s(val, SYS_CNTP_TVAL_EL02); +} + +static u64 read_ptimer_ctl_vhe(void) +{ + return read_sysreg_s(SYS_CNTP_CTL_EL02); +} + +static void write_ptimer_ctl_vhe(u64 val) +{ + write_sysreg_s(val, SYS_CNTP_CTL_EL02); +} + struct timer_info { u32 irq; u32 irq_flags; @@ -133,6 +194,30 @@ static struct timer_info ptimer_info = { .write_ctl = write_ptimer_ctl, }; +static struct timer_info vtimer_info_vhe = { + .irq_received = false, + .read_counter = read_vtimer_counter, + .read_cval = read_vtimer_cval_vhe, + .write_cval = write_vtimer_cval_vhe, + .read_tval = read_vtimer_tval_vhe, + .write_tval = write_vtimer_tval_vhe, + .read_ctl = read_vtimer_ctl_vhe, + .write_ctl = write_vtimer_ctl_vhe, +}; + +static struct timer_info ptimer_info_vhe = { + .irq_received = false, + .read_counter = read_ptimer_counter, + .read_cval = read_ptimer_cval_vhe, + .write_cval = write_ptimer_cval_vhe, + .read_tval = read_ptimer_tval_vhe, + .write_tval = write_ptimer_tval_vhe, + .read_ctl = read_ptimer_ctl_vhe, + .write_ctl = write_ptimer_ctl_vhe, +}; + +static struct timer_info *vtimer, *ptimer; + static void set_timer_irq_enabled(struct timer_info *info, bool enabled) { u32 val = 1 << PPI(info->irq); @@ -152,10 +237,10 @@ static void irq_handler(struct pt_regs *regs) if (irqnr == GICC_INT_SPURIOUS) return; - if (irqnr == PPI(vtimer_info.irq)) { - info = &vtimer_info; - } else if (irqnr == PPI(ptimer_info.irq)) { - info = &ptimer_info; + if (irqnr == PPI(vtimer->irq)) { + info = vtimer; + } else if (irqnr == PPI(ptimer->irq)) { + info = ptimer; } else { report_info("Unexpected interrupt: %d\n", irqnr); return; @@ -263,7 +348,7 @@ static void test_timer(struct timer_info *info) static void test_vtimer(void) { report_prefix_push("vtimer-busy-loop"); - test_timer(&vtimer_info); + test_timer(vtimer); report_prefix_pop(); } @@ -273,7 +358,7 @@ static void test_ptimer(void) return; report_prefix_push("ptimer-busy-loop"); - test_timer(&ptimer_info); + test_timer(ptimer); report_prefix_pop(); } @@ -284,6 +369,14 @@ static void test_init(void) int node, len; u32 *data; + if (current_level() == CurrentEL_EL1) { + vtimer = &vtimer_info; + ptimer = &ptimer_info; + } else { + vtimer = &vtimer_info_vhe; + ptimer = &ptimer_info_vhe; + } + node = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer"); assert(node >= 0); prop = fdt_get_property(fdt, node, "interrupts", &len); @@ -291,14 +384,14 @@ static void test_init(void) data = (u32 *)prop->data; assert(fdt32_to_cpu(data[3]) == 1); - ptimer_info.irq = fdt32_to_cpu(data[4]); - ptimer_info.irq_flags = fdt32_to_cpu(data[5]); + ptimer->irq = fdt32_to_cpu(data[4]); + ptimer->irq_flags = fdt32_to_cpu(data[5]); assert(fdt32_to_cpu(data[6]) == 1); - vtimer_info.irq = fdt32_to_cpu(data[7]); - vtimer_info.irq_flags = fdt32_to_cpu(data[8]); + vtimer->irq = fdt32_to_cpu(data[7]); + vtimer->irq_flags = fdt32_to_cpu(data[8]); install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, ptimer_unsupported_handler); - read_sysreg(cntp_ctl_el0); + ptimer->read_ctl(); install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, NULL); if (ptimer_unsupported && !ERRATA(7b6b46311a85)) { @@ -332,14 +425,14 @@ static void print_timer_info(void) printf("CNTFRQ_EL0 : 0x%016lx\n", read_sysreg(cntfrq_el0)); if (!ptimer_unsupported){ - printf("CNTPCT_EL0 : 0x%016lx\n", read_sysreg(cntpct_el0)); - printf("CNTP_CTL_EL0 : 0x%016lx\n", read_sysreg(cntp_ctl_el0)); - printf("CNTP_CVAL_EL0: 0x%016lx\n", read_sysreg(cntp_cval_el0)); + printf("CNTPCT_EL0 : 0x%016lx\n", ptimer->read_counter()); + printf("CNTP_CTL_EL0 : 0x%016lx\n", ptimer->read_ctl()); + printf("CNTP_CVAL_EL0: 0x%016lx\n", ptimer->read_cval()); } - printf("CNTVCT_EL0 : 0x%016lx\n", read_sysreg(cntvct_el0)); - printf("CNTV_CTL_EL0 : 0x%016lx\n", read_sysreg(cntv_ctl_el0)); - printf("CNTV_CVAL_EL0: 0x%016lx\n", read_sysreg(cntv_cval_el0)); + printf("CNTVCT_EL0 : 0x%016lx\n", vtimer->read_counter()); + printf("CNTV_CTL_EL0 : 0x%016lx\n", vtimer->read_ctl()); + printf("CNTV_CVAL_EL0: 0x%016lx\n", vtimer->read_cval()); } int main(int argc, char **argv) From patchwork Tue Oct 1 10:23:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168429 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 39E1E1902 for ; Tue, 1 Oct 2019 10:24:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 22CF6222CB for ; Tue, 1 Oct 2019 10:24:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730547AbfJAKYB (ORCPT ); Tue, 1 Oct 2019 06:24:01 -0400 Received: from foss.arm.com ([217.140.110.172]:46020 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730433AbfJAKYA (ORCPT ); Tue, 1 Oct 2019 06:24:00 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 33DAD1000; Tue, 1 Oct 2019 03:24:00 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id ECFBB3F739; Tue, 1 Oct 2019 03:23:58 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 15/19] arm64: timer: Add test for EL2 timers Date: Tue, 1 Oct 2019 11:23:19 +0100 Message-Id: <20191001102323.27628-16-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When VHE is available, EL2 has two extra timers, the physical and virtual EL2 timers. Extend the timer test to include them. Signed-off-by: Alexandru Elisei --- lib/arm64/asm/sysreg.h | 8 +++ arm/timer.c | 150 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 154 insertions(+), 4 deletions(-) diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h index ed407f93330d..02054fbe2763 100644 --- a/lib/arm64/asm/sysreg.h +++ b/lib/arm64/asm/sysreg.h @@ -19,6 +19,14 @@ #define SYS_CNTV_CTL_EL02 sys_reg(3, 5, 14, 3, 1) #define SYS_CNTV_CVAL_EL02 sys_reg(3, 5, 14, 3, 2) +#define SYS_CNTHP_TVAL_EL2 sys_reg(3, 4, 14, 2, 0) +#define SYS_CNTHP_CTL_EL2 sys_reg(3, 4, 14, 2, 1) +#define SYS_CNTHP_CVAL_EL2 sys_reg(3, 4, 14, 2, 2) + +#define SYS_CNTHV_TVAL_EL2 sys_reg(3, 4, 14, 3, 0) +#define SYS_CNTHV_CTL_EL2 sys_reg(3, 4, 14, 3, 1) +#define SYS_CNTHV_CVAL_EL2 sys_reg(3, 4, 14, 3, 2) + #ifdef __ASSEMBLY__ .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 .equ .L__reg_num_x\num, \num diff --git a/arm/timer.c b/arm/timer.c index 29477ee65878..faab671d0fb1 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -23,6 +23,8 @@ static void *gic_icenabler; static bool ptimer_unsupported; +static int current_el; + static void ptimer_unsupported_handler(struct pt_regs *regs, unsigned int esr) { ptimer_unsupported = true; @@ -159,6 +161,66 @@ static void write_ptimer_ctl_vhe(u64 val) write_sysreg_s(val, SYS_CNTP_CTL_EL02); } +static u64 read_hvtimer_cval(void) +{ + return read_sysreg_s(SYS_CNTHV_CVAL_EL2); +} + +static void write_hvtimer_cval(u64 val) +{ + write_sysreg_s(val, SYS_CNTHV_CVAL_EL2); +} + +static s32 read_hvtimer_tval(void) +{ + return read_sysreg_s(SYS_CNTHV_TVAL_EL2); +} + +static void write_hvtimer_tval(s32 val) +{ + write_sysreg_s(val, SYS_CNTHV_TVAL_EL2); +} + +static u64 read_hvtimer_ctl(void) +{ + return read_sysreg_s(SYS_CNTHV_CTL_EL2); +} + +static void write_hvtimer_ctl(u64 val) +{ + write_sysreg_s(val, SYS_CNTHV_CTL_EL2); +} + +static u64 read_hptimer_cval(void) +{ + return read_sysreg_s(SYS_CNTHP_CVAL_EL2); +} + +static void write_hptimer_cval(u64 val) +{ + write_sysreg_s(val, SYS_CNTHP_CVAL_EL2); +} + +static s32 read_hptimer_tval(void) +{ + return read_sysreg_s(SYS_CNTHP_TVAL_EL2); +} + +static void write_hptimer_tval(s32 val) +{ + write_sysreg_s(val, SYS_CNTHP_TVAL_EL2); +} + +static u64 read_hptimer_ctl(void) +{ + return read_sysreg_s(SYS_CNTHP_CTL_EL2); +} + +static void write_hptimer_ctl(u64 val) +{ + write_sysreg_s(val, SYS_CNTHP_CTL_EL2); +} + struct timer_info { u32 irq; u32 irq_flags; @@ -216,7 +278,29 @@ static struct timer_info ptimer_info_vhe = { .write_ctl = write_ptimer_ctl_vhe, }; -static struct timer_info *vtimer, *ptimer; +static struct timer_info hvtimer_info = { + .irq_received = false, + .read_counter = read_vtimer_counter, + .read_cval = read_hvtimer_cval, + .write_cval = write_hvtimer_cval, + .read_tval = read_hvtimer_tval, + .write_tval = write_hvtimer_tval, + .read_ctl = read_hvtimer_ctl, + .write_ctl = write_hvtimer_ctl, +}; + +static struct timer_info hptimer_info = { + .irq_received = false, + .read_counter = read_ptimer_counter, + .read_cval = read_hptimer_cval, + .write_cval = write_hptimer_cval, + .read_tval = read_hptimer_tval, + .write_tval = write_hptimer_tval, + .read_ctl = read_hptimer_ctl, + .write_ctl = write_hptimer_ctl, +}; + +static struct timer_info *vtimer, *ptimer, *hvtimer, *hptimer; static void set_timer_irq_enabled(struct timer_info *info, bool enabled) { @@ -241,6 +325,10 @@ static void irq_handler(struct pt_regs *regs) info = vtimer; } else if (irqnr == PPI(ptimer->irq)) { info = ptimer; + } else if (current_el == CurrentEL_EL2 && irqnr == PPI(hptimer->irq)) { + info = hptimer; + } else if (current_el == CurrentEL_EL2 && irqnr == PPI(hvtimer->irq)) { + info = hvtimer; } else { report_info("Unexpected interrupt: %d\n", irqnr); return; @@ -362,6 +450,20 @@ static void test_ptimer(void) report_prefix_pop(); } +static void test_hvtimer(void) +{ + report_prefix_push("hvtimer-busy-loop"); + test_timer(hvtimer); + report_prefix_pop(); +} + +static void test_hptimer(void) +{ + report_prefix_push("hptimer-busy-loop"); + test_timer(hptimer); + report_prefix_pop(); +} + static void test_init(void) { const struct fdt_property *prop; @@ -369,12 +471,14 @@ static void test_init(void) int node, len; u32 *data; - if (current_level() == CurrentEL_EL1) { + if (current_el == CurrentEL_EL1) { vtimer = &vtimer_info; ptimer = &ptimer_info; } else { vtimer = &vtimer_info_vhe; ptimer = &ptimer_info_vhe; + hvtimer = &hvtimer_info; + hptimer = &hptimer_info; } node = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer"); @@ -390,6 +494,19 @@ static void test_init(void) vtimer->irq = fdt32_to_cpu(data[7]); vtimer->irq_flags = fdt32_to_cpu(data[8]); + if (current_el == CurrentEL_EL2) { + assert(fdt32_to_cpu(data[9]) == 1); + hptimer->irq = fdt32_to_cpu(data[10]); + hptimer->irq_flags = fdt32_to_cpu(data[11]); + /* The hvtimer is not in the DT, assume KVM default. */ + hvtimer->irq = 28; + /* + * With VHE, accesses to the vtimer are redirected to the + * hvtimer. They should have the same interrupt properties. + */ + hvtimer->irq_flags = vtimer->irq_flags; + } + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, ptimer_unsupported_handler); ptimer->read_ctl(); install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, NULL); @@ -433,12 +550,22 @@ static void print_timer_info(void) printf("CNTVCT_EL0 : 0x%016lx\n", vtimer->read_counter()); printf("CNTV_CTL_EL0 : 0x%016lx\n", vtimer->read_ctl()); printf("CNTV_CVAL_EL0: 0x%016lx\n", vtimer->read_cval()); + + if (current_el == CurrentEL_EL2) { + printf("CNTHP_CTL_EL0 : 0x%016lx\n", hptimer->read_ctl()); + printf("CNTHP_CVAL_EL0: 0x%016lx\n", hptimer->read_cval()); + + printf("CNTHV_CTL_EL0 : 0x%016lx\n", hvtimer->read_ctl()); + printf("CNTHV_CVAL_EL0: 0x%016lx\n", hvtimer->read_cval()); + } } int main(int argc, char **argv) { int i; + current_el = current_level(); + test_init(); print_timer_info(); @@ -446,13 +573,28 @@ int main(int argc, char **argv) if (argc == 1) { test_vtimer(); test_ptimer(); + if (current_el == CurrentEL_EL2) { + test_hvtimer(); + test_hptimer(); + } } for (i = 1; i < argc; ++i) { - if (strcmp(argv[i], "vtimer") == 0) + if (strcmp(argv[i], "vtimer") == 0) { test_vtimer(); - if (strcmp(argv[i], "ptimer") == 0) + } if (strcmp(argv[i], "ptimer") == 0) { test_ptimer(); + } if (strcmp(argv[i], "hvtimer") == 0) { + if (current_el == CurrentEL_EL1) + report_info("Skipping hvtimer tests. Boot at EL2 to enable."); + else + test_hvtimer(); + } if (strcmp(argv[i], "hptimer") == 0) { + if (current_el == CurrentEL_EL1) + report_info("Skipping hptimer tests. Boot at EL2 to enable."); + else + test_hptimer(); + } } return report_summary(); From patchwork Tue Oct 1 10:23:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168427 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DF3B013B1 for ; Tue, 1 Oct 2019 10:24:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C8730222CB for ; Tue, 1 Oct 2019 10:24:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730525AbfJAKYD (ORCPT ); Tue, 1 Oct 2019 06:24:03 -0400 Received: from foss.arm.com ([217.140.110.172]:46038 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730556AbfJAKYC (ORCPT ); Tue, 1 Oct 2019 06:24:02 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A36D71570; Tue, 1 Oct 2019 03:24:01 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 68ADB3F739; Tue, 1 Oct 2019 03:24:00 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 16/19] arm64: selftest: Add basic test for EL2 Date: Tue, 1 Oct 2019 11:23:20 +0100 Message-Id: <20191001102323.27628-17-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a rudimentary test for EL2 that checks that we are indeed running with VHE enabled and that we are using SMC for issuing PSCI calls. Signed-off-by: Alexandru Elisei --- lib/arm64/asm/processor.h | 6 ++++++ arm/selftest.c | 35 ++++++++++++++++++++++++++++++++++- arm/unittests.cfg | 8 ++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 7e9f76d73f1b..4bbd82d9bfde 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -116,5 +116,11 @@ static inline u32 get_cntfrq(void) return read_sysreg(cntfrq_el0); } +static inline bool vhe_enabled(void) +{ + unsigned long hcr = read_sysreg(hcr_el2); + return (hcr & HCR_EL2_E2H) && (hcr & HCR_EL2_TGE); +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM64_PROCESSOR_H_ */ diff --git a/arm/selftest.c b/arm/selftest.c index 68dd34e59f3d..69994dcd3506 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -209,6 +209,11 @@ static void check_pabt(void) test_exception("mov r2, #0x0", "bx r2", ""); __builtin_unreachable(); } + +static void check_el2(void) +{ + report("EL2 only available on arm64", false); +} #elif defined(__aarch64__) static unsigned long expected_level; @@ -382,6 +387,31 @@ static void user_psci_system_off(struct pt_regs *regs, unsigned int esr) { __user_psci_system_off(); } + +#define ID_AA64MMFR1_VHE_MASK (0xf << 8) +#define ID_AA64MMFR1_VHE_SUPPORTED (1 << 8) +static bool vhe_supported(void) +{ + u64 aa64mmfr1 = read_sysreg(id_aa64mmfr1_el1); + + return (aa64mmfr1 & ID_AA64MMFR1_VHE_MASK) == ID_AA64MMFR1_VHE_SUPPORTED; +} + +static void check_el2_cpu(void *data __unused) +{ + int cpu = smp_processor_id(); + + report("CPU(%3d) Running at EL2", current_level() == CurrentEL_EL2, cpu); + report("CPU(%3d) VHE supported and enabled", + vhe_supported() && vhe_enabled(), cpu); +} + +static bool psci_check(void); +static void check_el2(void) +{ + report("PSCI conduit", psci_check()); + on_cpus(check_el2_cpu, NULL); +} #endif static void check_vectors(void *arg __unused) @@ -437,7 +467,6 @@ static bool psci_check(void) printf("psci method must be smc\n"); return false; } - if (current_level() == CurrentEL_EL1 && strcmp(method->data, "hvc") != 0) { printf("psci method must be hvc\n"); @@ -490,6 +519,10 @@ int main(int argc, char **argv) report("PSCI version", psci_check()); on_cpus(cpu_report, NULL); + } else if (strcmp(argv[1], "el2") == 0) { + + check_el2(); + } else { printf("Unknown subtest\n"); abort(); diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 6d3df92a4e28..c632f4e75382 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -55,6 +55,14 @@ smp = $MAX_SMP extra_params = -append 'smp' groups = selftest +# Test EL2 support +[selftest-el2] +file = selftest.flat +smp = 2 +extra_params = -append 'el2' +groups = selftest +arch = arm64 + # Test PCI emulation [pci-test] file = pci-test.flat From patchwork Tue Oct 1 10:23:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168431 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7D25D16B1 for ; Tue, 1 Oct 2019 10:24:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5BC1B21906 for ; Tue, 1 Oct 2019 10:24:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730560AbfJAKYE (ORCPT ); Tue, 1 Oct 2019 06:24:04 -0400 Received: from foss.arm.com ([217.140.110.172]:46050 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730583AbfJAKYE (ORCPT ); Tue, 1 Oct 2019 06:24:04 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 25CC915A2; Tue, 1 Oct 2019 03:24:03 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id DD3BD3F739; Tue, 1 Oct 2019 03:24:01 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 17/19] lib: arm64: Add support for disabling and re-enabling VHE Date: Tue, 1 Oct 2019 11:23:21 +0100 Message-Id: <20191001102323.27628-18-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a function to disable VHE and another one to re-enable VHE. Both functions work under the assumption that the CPU had VHE mode enabled at boot. Minimal support to run with VHE has been added to the TLB invalidate functions and to the exception handling code. Since we're touch the assembly enable/disable MMU code, let's take this opportunity to replace a magic number with the proper define. Signed-off-by: Alexandru Elisei --- Changes: * Removed the stack pointer swapping before disabling/re-enabling VHE. lib/arm64/asm/mmu.h | 11 +- lib/arm64/asm/pgtable-hwdef.h | 53 +++++++--- lib/arm64/asm/processor.h | 19 +++- lib/arm/setup.c | 1 + lib/arm64/processor.c | 41 +++++++- arm/cstart64.S | 193 ++++++++++++++++++++++++++++++++-- 6 files changed, 294 insertions(+), 24 deletions(-) diff --git a/lib/arm64/asm/mmu.h b/lib/arm64/asm/mmu.h index fa554b0c20ae..6ce6c8958910 100644 --- a/lib/arm64/asm/mmu.h +++ b/lib/arm64/asm/mmu.h @@ -6,6 +6,7 @@ * This work is licensed under the terms of the GNU LGPL, version 2. */ #include +#include #define PMD_SECT_UNCACHED PMD_ATTRINDX(MT_DEVICE_nGnRE) #define PTE_WBWA PTE_ATTRINDX(MT_NORMAL) @@ -13,7 +14,10 @@ static inline void flush_tlb_all(void) { dsb(ishst); - asm("tlbi vmalle1is"); + if (current_level() == CurrentEL_EL2 && !cpu_el2_e2h_is_set()) + asm("tlbi alle2is"); + else + asm("tlbi vmalle1is"); dsb(ish); isb(); } @@ -22,7 +26,10 @@ static inline void flush_tlb_page(unsigned long vaddr) { unsigned long page = vaddr >> 12; dsb(ishst); - asm("tlbi vaae1is, %0" :: "r" (page)); + if (current_level() == CurrentEL_EL2 && !cpu_el2_e2h_is_set()) + asm("tlbi vae2is, %0" :: "r" (page)); + else + asm("tlbi vaae1is, %0" :: "r" (page)); dsb(ish); } diff --git a/lib/arm64/asm/pgtable-hwdef.h b/lib/arm64/asm/pgtable-hwdef.h index f183b48dec5d..019e84216983 100644 --- a/lib/arm64/asm/pgtable-hwdef.h +++ b/lib/arm64/asm/pgtable-hwdef.h @@ -93,18 +93,42 @@ /* * TCR flags. */ -#define TCR_TxSZ(x) (((_UL(64) - (x)) << 16) | ((_UL(64) - (x)) << 0)) -#define TCR_IRGN_NC ((_UL(0) << 8) | (_UL(0) << 24)) -#define TCR_IRGN_WBWA ((_UL(1) << 8) | (_UL(1) << 24)) -#define TCR_IRGN_WT ((_UL(2) << 8) | (_UL(2) << 24)) -#define TCR_IRGN_WBnWA ((_UL(3) << 8) | (_UL(3) << 24)) -#define TCR_IRGN_MASK ((_UL(3) << 8) | (_UL(3) << 24)) -#define TCR_ORGN_NC ((_UL(0) << 10) | (_UL(0) << 26)) -#define TCR_ORGN_WBWA ((_UL(1) << 10) | (_UL(1) << 26)) -#define TCR_ORGN_WT ((_UL(2) << 10) | (_UL(2) << 26)) -#define TCR_ORGN_WBnWA ((_UL(3) << 10) | (_UL(3) << 26)) -#define TCR_ORGN_MASK ((_UL(3) << 10) | (_UL(3) << 26)) -#define TCR_SHARED ((_UL(3) << 12) | (_UL(3) << 28)) +#define TCR_T0SZ(x) ((_UL(64) - (x)) << 0) +#define TCR_T1SZ(x) ((_UL(64) - (x)) << 16) +#define TCR_TxSZ(x) (TCR_T0SZ(x) | TCR_T1SZ(x)) +#define TCR_IRGN0_NC (_UL(0) << 8) +#define TCR_IRGN1_NC (_UL(0) << 24) +#define TCR_IRGN_NC (TCR_IRGN0_NC | TCR_IRGN1_NC) +#define TCR_IRGN0_WBWA (_UL(1) << 8) +#define TCR_IRGN1_WBWA (_UL(1) << 24) +#define TCR_IRGN_WBWA (TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) +#define TCR_IRGN0_WT (_UL(2) << 8) +#define TCR_IRGN1_WT (_UL(2) << 24) +#define TCR_IRGN_WT (TCR_IRGN0_WT | TCR_IRGN1_WT) +#define TCR_IRGN0_WBnWA (_UL(3) << 8) +#define TCR_IRGN1_WBnWA (_UL(3) << 24) +#define TCR_IRGN_WBnWA (TCR_IRGN0_WBnWA | TCR_IRGN1_WBnWA) +#define TCR_IRGN0_MASK (_UL(3) << 8) +#define TCR_IRGN1_MASK (_UL(3) << 24) +#define TCR_IRGN_MASK (TCR_IRGN0_MASK | TCR_IRGN1_MASK) +#define TCR_ORGN0_NC (_UL(0) << 10) +#define TCR_ORGN1_NC (_UL(0) << 26) +#define TCR_ORGN_NC (TCR_ORGN0_NC | TCR_ORGN1_NC) +#define TCR_ORGN0_WBWA (_UL(1) << 10) +#define TCR_ORGN1_WBWA (_UL(1) << 26) +#define TCR_ORGN_WBWA (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA) +#define TCR_ORGN0_WT (_UL(2) << 10) +#define TCR_ORGN1_WT (_UL(2) << 26) +#define TCR_ORGN_WT (TCR_ORGN0_WT | TCR_ORGN1_WT) +#define TCR_ORGN0_WBnWA (_UL(3) << 8) +#define TCR_ORGN1_WBnWA (_UL(3) << 24) +#define TCR_ORGN_WBnWA (TCR_ORGN0_WBnWA | TCR_ORGN1_WBnWA) +#define TCR_ORGN0_MASK (_UL(3) << 10) +#define TCR_ORGN1_MASK (_UL(3) << 26) +#define TCR_ORGN_MASK (TCR_ORGN0_MASK | TCR_ORGN1_MASK) +#define TCR_SH0_IS (_UL(3) << 12) +#define TCR_SH1_IS (_UL(3) << 28) +#define TCR_SHARED (TCR_SH0_IS | TCR_SH1_IS) #define TCR_TG0_4K (_UL(0) << 14) #define TCR_TG0_64K (_UL(1) << 14) #define TCR_TG0_16K (_UL(2) << 14) @@ -114,6 +138,11 @@ #define TCR_ASID16 (_UL(1) << 36) #define TCR_TBI0 (_UL(1) << 37) +#define TCR_EL1_IPS_SHIFT 32 + +#define TCR_EL2_RES1 ((_UL(1) << 31) | (_UL(1) << 23)) +#define TCR_EL2_PS_SHIFT 16 + /* * Memory types available. */ diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 4bbd82d9bfde..70a5261dfe97 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -18,8 +18,15 @@ #define SCTLR_EL1_A (1 << 1) #define SCTLR_EL1_M (1 << 0) -#define HCR_EL2_TGE (1 << 27) -#define HCR_EL2_E2H (_UL(1) << 34) +#define HCR_EL2_TGE (1 << 27) +#define HCR_EL2_E2H_SHIFT 34 +#define HCR_EL2_E2H (_UL(1) << 34) + +#define SCTLR_EL2_RES1 (3 << 28 | 3 << 22 | 1 << 18 | \ + 1 << 16 | 1 << 11 | 3 << 4) +#define SCTLR_EL2_I SCTLR_EL1_I +#define SCTLR_EL2_C SCTLR_EL1_C +#define SCTLR_EL2_M SCTLR_EL1_M #define CTR_EL0_DMINLINE_SHIFT 16 #define CTR_EL0_DMINLINE_MASK (0xf << 16) @@ -72,6 +79,9 @@ extern void show_regs(struct pt_regs *regs); extern bool get_far(unsigned int esr, unsigned long *far); extern void init_dcache_line_size(void); +extern void disable_vhe(void); +extern void enable_vhe(void); + static inline unsigned long current_level(void) { unsigned long el; @@ -122,5 +132,10 @@ static inline bool vhe_enabled(void) return (hcr & HCR_EL2_E2H) && (hcr & HCR_EL2_TGE); } +static inline bool cpu_el2_e2h_is_set(void) +{ + return read_sysreg(hcr_el2) & HCR_EL2_E2H; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM64_PROCESSOR_H_ */ diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 2f23cb07f4fc..4544bf863d9a 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "io.h" diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c index 2030a7a09107..ba55a0d57603 100644 --- a/lib/arm64/processor.c +++ b/lib/arm64/processor.c @@ -86,7 +86,10 @@ bool get_far(unsigned int esr, unsigned long *far) { unsigned int ec = esr >> ESR_EL1_EC_SHIFT; - asm volatile("mrs %0, far_el1": "=r" (*far)); + if (current_level() == CurrentEL_EL2 && !cpu_el2_e2h_is_set()) + asm volatile("mrs %0, far_el2": "=r" (*far)); + else + asm volatile("mrs %0, far_el1": "=r" (*far)); switch (ec) { case ESR_EL1_EC_IABT_EL0: @@ -270,3 +273,39 @@ void init_dcache_line_size(void) /* DminLine is log2 of the number of words in the smallest cache line */ dcache_line_size = 1 << (CTR_EL0_DMINLINE(ctr) + 2); } + +extern void asm_disable_vhe(void); +void disable_vhe(void) +{ + u64 daif; + + assert(current_level() == CurrentEL_EL2 && vhe_enabled()); + + /* + * Make sure we don't take any exceptions while we run with the MMU off. + * On secondaries the stack is allocated from the vmalloc area, which + * means it isn't identity mapped, and the exception handling code uses + * it. + */ + asm volatile("mrs %0, daif" : "=r" (daif)); + local_irq_disable(); + isb(); + asm_disable_vhe(); + asm volatile("msr daif, %0" :: "r" (daif)); + isb(); +} + +extern void asm_enable_vhe(void); +void enable_vhe(void) +{ + u64 daif; + + assert(current_level() == CurrentEL_EL2 && !vhe_enabled()); + + asm volatile("mrs %0, daif" : "=r" (daif)); + local_irq_disable(); + isb(); + asm_enable_vhe(); + asm volatile("msr daif, %0" :: "r" (daif)); + isb(); +} diff --git a/arm/cstart64.S b/arm/cstart64.S index acf86eb6089e..cf5374a7bab3 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -104,6 +104,13 @@ exceptions_init: .text +exceptions_init_nvhe: + adrp x0, vector_table_nvhe + add x0, x0, :lo12:vector_table_nvhe + msr vbar_el2, x0 + isb + ret + .globl get_mmu_off get_mmu_off: adrp x0, auxinfo @@ -204,7 +211,7 @@ asm_mmu_enable: TCR_IRGN_WBWA | TCR_ORGN_WBWA | \ TCR_SHARED mrs x2, id_aa64mmfr0_el1 - bfi x1, x2, #32, #3 + bfi x1, x2, #TCR_EL1_IPS_SHIFT, #3 msr tcr_el1, x1 /* MAIR */ @@ -229,6 +236,33 @@ asm_mmu_enable: ret +asm_mmu_enable_nvhe: + ic iallu + tlbi alle2 + dsb nsh + + /* TCR */ + ldr x1, =TCR_EL2_RES1 | \ + TCR_T0SZ(VA_BITS) | \ + TCR_TG0_64K | \ + TCR_IRGN0_WBWA | TCR_ORGN0_WBWA | \ + TCR_SH0_IS + mrs x2, id_aa64mmfr0_el1 + bfi x1, x2, #TCR_EL2_PS_SHIFT, #3 + msr tcr_el2, x1 + + /* Same MAIR and TTBR0 as in VHE mode */ + + /* SCTLR */ + ldr x1, =SCTLR_EL2_RES1 | \ + SCTLR_EL2_C | \ + SCTLR_EL2_I | \ + SCTLR_EL2_M + msr sctlr_el2, x1 + isb + + ret + /* Taken with small changes from arch/arm64/incluse/asm/assembler.h */ .macro dcache_by_line_op op, domain, start, end, tmp1, tmp2 adrp \tmp1, dcache_line_size @@ -243,21 +277,58 @@ asm_mmu_enable: dsb \domain .endm +clean_inval_memory: + adrp x0, __phys_offset + ldr x0, [x0, :lo12:__phys_offset] + adrp x1, __phys_end + ldr x1, [x1, :lo12:__phys_end] + dcache_by_line_op civac, sy, x0, x1, x2, x3 + isb + ret + .globl asm_mmu_disable asm_mmu_disable: mrs x0, sctlr_el1 bic x0, x0, SCTLR_EL1_M msr sctlr_el1, x0 isb + b clean_inval_memory - /* Clean + invalidate the entire memory */ - adrp x0, __phys_offset - ldr x0, [x0, :lo12:__phys_offset] - adrp x1, __phys_end - ldr x1, [x1, :lo12:__phys_end] - dcache_by_line_op civac, sy, x0, x1, x2, x3 +asm_mmu_disable_nvhe: + mrs x0, sctlr_el2 + bic x0, x0, SCTLR_EL2_M + msr sctlr_el2, x0 + isb + b clean_inval_memory + +.globl asm_disable_vhe +asm_disable_vhe: + str x30, [sp, #-16]! + + bl asm_mmu_disable + msr hcr_el2, xzr isb + bl exceptions_init_nvhe + bl asm_mmu_enable_nvhe + ldr x30, [sp], #16 + ret + +.globl asm_enable_vhe +asm_enable_vhe: + str x30, [sp, #-16]! + + bl asm_mmu_disable_nvhe + ldr x0, =(HCR_EL2_E2H | HCR_EL2_TGE) + msr hcr_el2, x0 + isb + bl exceptions_init + /* Make asm_mmu_enable happy by having TTBR0 value in x0 */ + mrs x0, ttbr0_el1 + isb + bl asm_mmu_enable + + ldr x30, [sp], #16 ret /* @@ -350,6 +421,92 @@ vector_stub el0_irq_32, 13 vector_stub el0_fiq_32, 14 vector_stub el0_error_32, 15 +.macro vector_stub_nvhe, name, vec +\name: + stp x0, x1, [sp, #-S_FRAME_SIZE]! + stp x2, x3, [sp, #16] + stp x4, x5, [sp, #32] + stp x6, x7, [sp, #48] + stp x8, x9, [sp, #64] + stp x10, x11, [sp, #80] + stp x12, x13, [sp, #96] + stp x14, x15, [sp, #112] + stp x16, x17, [sp, #128] + stp x18, x19, [sp, #144] + stp x20, x21, [sp, #160] + stp x22, x23, [sp, #176] + stp x24, x25, [sp, #192] + stp x26, x27, [sp, #208] + stp x28, x29, [sp, #224] + + str x30, [sp, #S_LR] + + .if \vec >= 8 + mrs x1, sp_el1 + .else + add x1, sp, #S_FRAME_SIZE + .endif + str x1, [sp, #S_SP] + + mrs x1, elr_el2 + mrs x2, spsr_el2 + stp x1, x2, [sp, #S_PC] + + mov x0, \vec + mov x1, sp + mrs x2, esr_el2 + bl do_handle_exception + + ldp x1, x2, [sp, #S_PC] + msr spsr_el2, x2 + msr elr_el2, x1 + + .if \vec >= 8 + ldr x1, [sp, #S_SP] + msr sp_el1, x1 + .endif + + ldr x30, [sp, #S_LR] + + ldp x28, x29, [sp, #224] + ldp x26, x27, [sp, #208] + ldp x24, x25, [sp, #192] + ldp x22, x23, [sp, #176] + ldp x20, x21, [sp, #160] + ldp x18, x19, [sp, #144] + ldp x16, x17, [sp, #128] + ldp x14, x15, [sp, #112] + ldp x12, x13, [sp, #96] + ldp x10, x11, [sp, #80] + ldp x8, x9, [sp, #64] + ldp x6, x7, [sp, #48] + ldp x4, x5, [sp, #32] + ldp x2, x3, [sp, #16] + ldp x0, x1, [sp], #S_FRAME_SIZE + + eret +.endm + +vector_stub_nvhe el2t_sync, 0 +vector_stub_nvhe el2t_irq, 1 +vector_stub_nvhe el2t_fiq, 2 +vector_stub_nvhe el2t_error, 3 + +vector_stub_nvhe el2h_sync, 4 +vector_stub_nvhe el2h_irq, 5 +vector_stub_nvhe el2h_fiq, 6 +vector_stub_nvhe el2h_error, 7 + +vector_stub_nvhe el1_sync_64, 8 +vector_stub_nvhe el1_irq_64, 9 +vector_stub_nvhe el1_fiq_64, 10 +vector_stub_nvhe el1_error_64, 11 + +vector_stub_nvhe el1_sync_32, 12 +vector_stub_nvhe el1_irq_32, 13 +vector_stub_nvhe el1_fiq_32, 14 +vector_stub_nvhe el1_error_32, 15 + .section .text.ex .macro ventry, label @@ -378,3 +535,25 @@ vector_table: ventry el0_irq_32 // IRQ 32-bit EL0 ventry el0_fiq_32 // FIQ 32-bit EL0 ventry el0_error_32 // Error 32-bit EL0 + +.align 11 +vector_table_nvhe: + ventry el2t_sync // Synchronous EL2t + ventry el2t_irq // IRQ EL2t + ventry el2t_fiq // FIQ EL2t + ventry el2t_error // Error EL2t + + ventry el2h_sync // Synchronous EL2h + ventry el2h_irq // IRQ EL2h + ventry el2h_fiq // FIQ EL2h + ventry el2h_error // Error EL2h + + ventry el1_sync_64 // Synchronous 64-bit EL1 + ventry el1_irq_64 // IRQ 64-bit EL1 + ventry el1_fiq_64 // FIQ 64-bit EL1 + ventry el1_error_64 // Error 64-bit EL1 + + ventry el1_sync_32 // Synchronous 32-bit EL1 + ventry el1_irq_32 // IRQ 32-bit EL1 + ventry el1_fiq_32 // FIQ 32-bit EL1 + ventry el1_error_32 // Error 32-bit EL1 From patchwork Tue Oct 1 10:23:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168435 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B71CB13B1 for ; Tue, 1 Oct 2019 10:24:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9D8ED222CC for ; Tue, 1 Oct 2019 10:24:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730591AbfJAKYF (ORCPT ); Tue, 1 Oct 2019 06:24:05 -0400 Received: from foss.arm.com ([217.140.110.172]:46062 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730577AbfJAKYE (ORCPT ); Tue, 1 Oct 2019 06:24:04 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 97D8E15AD; Tue, 1 Oct 2019 03:24:04 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 5DEED3F739; Tue, 1 Oct 2019 03:24:03 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 18/19] arm64: selftest: Expand EL2 test to disable and re-enable VHE Date: Tue, 1 Oct 2019 11:23:22 +0100 Message-Id: <20191001102323.27628-19-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Alexandru Elisei --- Disabling VHE is broken with version v1 of the NV patches; to run the tests I use this patch: diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 1d896113f1f8..977905f6aacd 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -333,7 +333,8 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) * to reverse-translate virtual EL2 system registers for a * non-VHE guest hypervisor. */ - __vcpu_sys_reg(vcpu, reg) = val; + if (reg != HCR_EL2) + __vcpu_sys_reg(vcpu, reg) = val; switch (reg) { case ELR_EL2: @@ -370,7 +371,17 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) return; memory_write: - __vcpu_sys_reg(vcpu, reg) = val; + if (reg == HCR_EL2 && vcpu_el2_e2h_is_set(vcpu) && !(val & HCR_E2H)) { + preempt_disable(); + kvm_arch_vcpu_put(vcpu); + + __vcpu_sys_reg(vcpu, reg) = val; + + kvm_arch_vcpu_load(vcpu, smp_processor_id()); + preempt_enable(); + } else { + __vcpu_sys_reg(vcpu, reg) = val; + } } /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */ arm/selftest.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arm/selftest.c b/arm/selftest.c index 69994dcd3506..f94498e83d97 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -404,6 +404,18 @@ static void check_el2_cpu(void *data __unused) report("CPU(%3d) Running at EL2", current_level() == CurrentEL_EL2, cpu); report("CPU(%3d) VHE supported and enabled", vhe_supported() && vhe_enabled(), cpu); + + report_info("CPU(%3d) Disabling VHE", cpu); + disable_vhe(); + + report("CPU(%3d) Running at EL2", current_level() == CurrentEL_EL2, cpu); + report("CPU(%3d) VHE disabled", !vhe_enabled(), cpu); + + report_info("CPU(%3d) Re-enabling VHE", cpu); + enable_vhe(); + + report("CPU(%3d) Running at EL2", current_level() == CurrentEL_EL2, cpu); + report("CPU(%3d) VHE enabled", vhe_enabled(), cpu); } static bool psci_check(void); From patchwork Tue Oct 1 10:23:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11168433 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 16E7B16B1 for ; Tue, 1 Oct 2019 10:24:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 00276222CB for ; Tue, 1 Oct 2019 10:24:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730462AbfJAKYG (ORCPT ); Tue, 1 Oct 2019 06:24:06 -0400 Received: from foss.arm.com ([217.140.110.172]:46070 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730577AbfJAKYG (ORCPT ); Tue, 1 Oct 2019 06:24:06 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 161821000; Tue, 1 Oct 2019 03:24:06 -0700 (PDT) Received: from e123195-lin.cambridge.arm.com (e123195-lin.cambridge.arm.com [10.1.196.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id D075C3F739; Tue, 1 Oct 2019 03:24:04 -0700 (PDT) From: Alexandru Elisei To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: drjones@redhat.com, pbonzini@redhat.com, rkrcmar@redhat.com, maz@kernel.org, vladimir.murzin@arm.com, andre.przywara@arm.com, mark.rutland@arm.com Subject: [kvm-unit-tests RFC PATCH v2 19/19] arm64: timer: Run tests with VHE disabled Date: Tue, 1 Oct 2019 11:23:23 +0100 Message-Id: <20191001102323.27628-20-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191001102323.27628-1-alexandru.elisei@arm.com> References: <20191001102323.27628-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Disable VHE if first command line parameter is "nvhe" and then test the timers. Just like with VHE enabled, if no other parameter is given, all four timers are tested; otherwise, only the timers specified by the user. Signed-off-by: Alexandru Elisei --- lib/arm64/asm/processor.h | 2 ++ arm/timer.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 70a5261dfe97..45a3176629e7 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -21,6 +21,8 @@ #define HCR_EL2_TGE (1 << 27) #define HCR_EL2_E2H_SHIFT 34 #define HCR_EL2_E2H (_UL(1) << 34) +#define HCR_EL2_IMO (1 << 4) +#define HCR_EL2_FMO (1 << 3) #define SCTLR_EL2_RES1 (3 << 28 | 3 << 22 | 1 << 18 | \ 1 << 16 | 1 << 11 | 3 << 4) diff --git a/arm/timer.c b/arm/timer.c index faab671d0fb1..6b9d5d57a658 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -464,19 +464,34 @@ static void test_hptimer(void) report_prefix_pop(); } -static void test_init(void) +static void test_init(bool without_vhe) { const struct fdt_property *prop; const void *fdt = dt_fdt(); + u64 hcr; int node, len; u32 *data; + if (without_vhe) { + disable_vhe(); + hcr = read_sysreg(hcr_el2); + /* KVM doesn't support different IMO/FMO settings */ + hcr |= HCR_EL2_IMO | HCR_EL2_FMO; + write_sysreg(hcr, hcr_el2); + isb(); + } + if (current_el == CurrentEL_EL1) { vtimer = &vtimer_info; ptimer = &ptimer_info; } else { - vtimer = &vtimer_info_vhe; - ptimer = &ptimer_info_vhe; + if (without_vhe) { + vtimer = &vtimer_info; + ptimer = &ptimer_info; + } else { + vtimer = &vtimer_info_vhe; + ptimer = &ptimer_info_vhe; + } hvtimer = &hvtimer_info; hptimer = &hptimer_info; } @@ -563,10 +578,20 @@ static void print_timer_info(void) int main(int argc, char **argv) { int i; + bool without_vhe = false; current_el = current_level(); - test_init(); + if (argc > 1 && strcmp(argv[1], "nvhe") == 0) { + if (current_el == CurrentEL_EL1) + report_info("Skipping EL2 tests. Boot at EL2 to enable."); + else + without_vhe = true; + argv = &argv[1]; + argc--; + } + + test_init(without_vhe); print_timer_info();