kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexandru Elisei <alexandru.elisei@arm.com>
To: Andrew Jones <drjones@redhat.com>
Cc: kvm@vger.kernel.org, pbonzini@redhat.com, rkrcmar@redhat.com,
	maz@kernel.org, andre.przywara@arm.com, vladimir.murzin@arm.com,
	mark.rutland@arm.com
Subject: Re: [kvm-unit-tests PATCH 10/18] arm/arm64: selftest: Add prefetch abort test
Date: Thu, 28 Nov 2019 09:59:36 +0000	[thread overview]
Message-ID: <82684f76-2157-e96a-00e2-a30451619751@arm.com> (raw)
In-Reply-To: <20191127184756.encuqdupgwcky6ys@kamzik.brq.redhat.com>

Hi,

On 11/27/19 6:47 PM, Andrew Jones wrote:
> On Wed, Nov 27, 2019 at 02:24:02PM +0000, Alexandru Elisei wrote:
>> 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 <alexandru.elisei@arm.com>
>> ---
>>  lib/arm64/asm/esr.h |  3 ++
>>  arm/selftest.c      | 97 +++++++++++++++++++++++++++++++++++++++++++--
>>  2 files changed, 97 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 e9dc5c0cab28..caad524378fc 100644
>> --- a/arm/selftest.c
>> +++ b/arm/selftest.c
>> @@ -16,6 +16,8 @@
>>  #include <asm/psci.h>
>>  #include <asm/smp.h>
>>  #include <asm/barrier.h>
>> +#include <asm/mmu.h>
>> +#include <asm/pgtable.h>
>>  
>>  static cpumask_t ready, valid;
>>  
>> @@ -68,6 +70,7 @@ static void check_setup(int argc, char **argv)
>>  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
>> @@ -91,7 +94,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)
>>  {
>> @@ -171,6 +174,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__)
>>  
>>  /*
>> @@ -212,7 +254,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)
>>  {
>> @@ -288,6 +330,53 @@ 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;
>> +}
>> +
>> +static void check_pabt(void)
>> +{
>> +	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.
>> +	 */
>> +	mmu_clear_user(current_thread_info()->pgtable, 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();
>> @@ -298,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
>> -- 
>> 2.20.1
>>
> Did you also test with QEMU? Because this new test dies on an unhandled
> unknown exception for me. Both with KVM and with TCG, and both arm64 and
> arm32 (KVM:aarch32 or TCG:arm).

To my chagrin, I forgot to test it on qemu. Tried it now and indeed it causes an
unknown exception. I'll try to figure out why it breaks on qemu and not on kvmtool.

Thanks,
Alex
>
> Thanks,
> drew
>

  reply	other threads:[~2019-11-28  9:59 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-27 14:23 [kvm-unit-tests PATCH 00/18] Various fixes Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 01/18] lib: arm/arm64: Remove unnecessary dcache maintenance operations Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 02/18] lib: arm64: Remove barriers before TLB operations Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 03/18] lib: Add WRITE_ONCE and READ_ONCE implementations in compiler.h Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 04/18] lib: arm/arm64: Use WRITE_ONCE to update the translation tables Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 05/18] lib: arm/arm64: Remove unused CPU_OFF parameter Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 06/18] arm/arm64: psci: Don't run C code without stack or vectors Alexandru Elisei
2019-11-27 14:23 ` [kvm-unit-tests PATCH 07/18] lib: arm/arm64: Add missing include for alloc_page.h in pgtable.h Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 08/18] lib: arm: Implement flush_tlb_all Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 09/18] lib: arm/arm64: Teach mmu_clear_user about block mappings Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 10/18] arm/arm64: selftest: Add prefetch abort test Alexandru Elisei
2019-11-27 18:47   ` Andrew Jones
2019-11-28  9:59     ` Alexandru Elisei [this message]
2019-11-28 16:56       ` Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 11/18] arm64: timer: Write to ICENABLER to disable timer IRQ Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 12/18] arm64: timer: EOIR the interrupt after masking the timer Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 13/18] arm64: timer: Test behavior when timer disabled or masked Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 14/18] lib: arm/arm64: Refuse to disable the MMU with non-identity stack pointer Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 15/18] arm/arm64: Perform dcache clean + invalidate after turning MMU off Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 16/18] arm: cstart64.S: Downgrade TLBI to non-shareable in asm_mmu_enable Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 17/18] arm/arm64: Invalidate TLB before enabling MMU Alexandru Elisei
2019-11-27 14:24 ` [kvm-unit-tests PATCH 18/18] arm: cstart64.S: Remove icache invalidation from asm_mmu_enable Alexandru Elisei
2019-11-27 14:41   ` Alexandru Elisei

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=82684f76-2157-e96a-00e2-a30451619751@arm.com \
    --to=alexandru.elisei@arm.com \
    --cc=andre.przywara@arm.com \
    --cc=drjones@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=vladimir.murzin@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).