public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Binbin Wu <binbin.wu@linux.intel.com>
To: Sean Christopherson <seanjc@google.com>
Cc: kvm@vger.kernel.org, pbonzini@redhat.com, chao.gao@intel.com,
	robert.hu@linux.intel.com
Subject: Re: [kvm-unit-tests PATCH v6 2/4] x86: Add test case for LAM_SUP
Date: Tue, 18 Jun 2024 13:48:29 +0800	[thread overview]
Message-ID: <00a74cb3-4f03-4eb3-a969-04293841f64a@linux.intel.com> (raw)
In-Reply-To: <ZmCtVWQ_7KdMqcmf@google.com>



On 6/6/2024 2:24 AM, Sean Christopherson wrote:
> On Mon, Jan 22, 2024, Binbin Wu wrote:
>> diff --git a/x86/lam.c b/x86/lam.c
>> new file mode 100644
>> index 00000000..0ad16be5
>> --- /dev/null
>> +++ b/x86/lam.c
>> @@ -0,0 +1,243 @@
>> +/*
>> + * Intel LAM unit test
>> + *
>> + * Copyright (C) 2023 Intel
>> + *
>> + * Author: Robert Hoo <robert.hu@linux.intel.com>
>> + *         Binbin Wu <binbin.wu@linux.intel.com>
>> + *
>> + * This work is licensed under the terms of the GNU LGPL, version 2 or
>> + * later.
>> + */
>> +
>> +#include "libcflat.h"
>> +#include "processor.h"
>> +#include "desc.h"
>> +#include "vmalloc.h"
>> +#include "alloc_page.h"
>> +#include "vm.h"
>> +#include "asm/io.h"
>> +#include "ioram.h"
>> +
>> +#define FLAGS_LAM_ACTIVE	BIT_ULL(0)
>> +#define FLAGS_LA57		BIT_ULL(1)
>> +
>> +struct invpcid_desc {
>> +	u64 pcid : 12;
>> +	u64 rsv  : 52;
>> +	u64 addr;
>> +};
>> +
>> +static inline bool is_la57(void)
>> +{
>> +	return !!(read_cr4() & X86_CR4_LA57);
>> +}
>> +
>> +static inline bool lam_sup_active(void)
> Needs an "is_" prefix.  And be consistent, e.g. is_lam_sup() to go with is_la57(),
> or is_lam_sup_enabled() and is_la57_enabled().  I'd probably vote for the latter,
> though KVM does have is_paging() and the like, so I'm fine either way.
>
> And these belong in processor.h

OK, will use is_lam_sup_enabled() / is_la57_enabled() and move them to 
processor.h.

>
>> +{
>> +	return !!(read_cr4() & X86_CR4_LAM_SUP);
>> +}
>> +
>> +static void cr4_set_lam_sup(void *data)
>> +{
>> +	unsigned long cr4;
>> +
>> +	cr4 = read_cr4();
>> +	write_cr4_safe(cr4 | X86_CR4_LAM_SUP);
>> +}
>> +
>> +static void cr4_clear_lam_sup(void *data)
>> +{
>> +	unsigned long cr4;
>> +
>> +	cr4 = read_cr4();
>> +	write_cr4_safe(cr4 & ~X86_CR4_LAM_SUP);
>> +}
> Please drop these helpers and instead use _safe() variants when possible, e.g.
>
> 	vector = write_cr4_safe(cr4 | X86_CR4_LAM_SUP);
> 	report(has_lam ? !vector : vector == GP_VECTOR,
> 	       "Expected CR4.LAM_SUP=1 to %s" ? has_lam ? "succeed" : "#GP");
>
> 	vector = write_cr4_safe(cr4 & ~X86_CR4_LAM_SUP);
> 	report(!vector, "Expected CR4.LAM_SUP=0 to succeed");
OK.

>
>> +static void test_cr4_lam_set_clear(bool has_lam)
>> +{
>> +	bool fault;
>> +
>> +	fault = test_for_exception(GP_VECTOR, &cr4_set_lam_sup, NULL);
>> +	report((fault != has_lam) && (lam_sup_active() == has_lam),
>> +	       "Set CR4.LAM_SUP");
>> +
>> +	fault = test_for_exception(GP_VECTOR, &cr4_clear_lam_sup, NULL);
>> +	report(!fault, "Clear CR4.LAM_SUP");
>> +}
>> +
>> +/* Refer to emulator.c */
>> +static void do_mov(void *mem)
>> +{
>> +	unsigned long t1, t2;
>> +
>> +	t1 = 0x123456789abcdefull & -1ul;
>> +	asm volatile("mov %[t1], (%[mem])\n\t"
>> +		     "mov (%[mem]), %[t2]"
>> +		     : [t2]"=r"(t2)
>> +		     : [t1]"r"(t1), [mem]"r"(mem)
>> +		     : "memory");
>> +	report(t1 == t2, "Mov result check");
>> +}
>> +
>> +static u64 test_ptr(u64 arg1, u64 arg2, u64 arg3, u64 arg4)
> There's no reason to name these arg1..arg4.  And unless I'm missing something,
> there's no need for these flags at all.  All the info is derived from vCPU state,
> so just re-grab it.  The cost of a CR4 read is negligible relative to the expected
> runtime of these tests.
The reason for these arguments is the userspace pointer will be tested 
in userspace using the same function,
and CR3/CR4 can not be read in ring3, so these CR3/CR4 LAM/LA57 related 
information needs to be passed.

Based on your comment and the comment from patch 3
https://lore.kernel.org/kvm/ZmC0GC3wAdiO0Dp2@google.com/
Does the number of arguments bothering you?
If not, I can pass CR3 and CR4 value to test_ptr() and let the test 
function to retrieve LAM information itself.
I.e, the 4 inputs will be CR3, CR4, memory pointer, is_mmio.


>
>> +{
>> +	bool lam_active = !!(arg1 & FLAGS_LAM_ACTIVE);
>> +	u64 lam_mask = arg2;
>> +	u64 *ptr = (u64 *)arg3;
>> +	bool is_mmio = !!arg4;
>> +	bool fault;
>> +
>> +	fault = test_for_exception(GP_VECTOR, do_mov, ptr);
>> +	report(!fault, "Test untagged addr (%s)", is_mmio ? "MMIO" : "Memory");
>> +
>> +	ptr = (u64 *)set_la_non_canonical((u64)ptr, lam_mask);
>> +	fault = test_for_exception(GP_VECTOR, do_mov, ptr);
>> +	report(fault != lam_active,"Test tagged addr (%s)",
>> +	       is_mmio ? "MMIO" : "Memory");
>> +
>> +	return 0;
>> +}
>> +
>> +static void do_invlpg(void *mem)
>> +{
>> +	invlpg(mem);
>> +}
>> +
>> +static void do_invlpg_fep(void *mem)
>> +{
>> +	asm volatile(KVM_FEP "invlpg (%0)" ::"r" (mem) : "memory");
>> +}
>> +
>> +/* invlpg with tagged address is same as NOP, no #GP expected. */
>> +static void test_invlpg(u64 lam_mask, void *va, bool fep)
>> +{
>> +	bool fault;
>> +	u64 *ptr;
>> +
>> +	ptr = (u64 *)set_la_non_canonical((u64)va, lam_mask);
>> +	if (fep)
>> +		fault = test_for_exception(GP_VECTOR, do_invlpg_fep, ptr);
>> +	else
>> +		fault = test_for_exception(GP_VECTOR, do_invlpg, ptr);
> INVLPG never faults, so don't bother with wrappers.  If INVPLG faults, the test
> fails, i.e. mission accomplished.

OK.
>
>> +
>> +	report(!fault, "%sINVLPG with tagged addr", fep ? "fep: " : "");
>> +}
>> +
>> +static void do_invpcid(void *desc)
>> +{
>> +	struct invpcid_desc *desc_ptr = (struct invpcid_desc *)desc;
>> +
>> +	asm volatile("invpcid %0, %1" :
>> +	                              : "m" (*desc_ptr), "r" (0UL)
>> +	                              : "memory");
>> +}
> Similar thing here, invpcid() belongs in processor.h, alongside invpcid_safe().

OK, I think I can use invpcid_safe() directly for test cases.


>
>> +/* LAM doesn't apply to the linear address in the descriptor of invpcid */
>> +static void test_invpcid(u64 flags, u64 lam_mask, void *data)
>> +{
>> +	/*
>> +	 * Reuse the memory address for the descriptor since stack memory
>> +	 * address in KUT doesn't follow the kernel address space partitions.
>> +	 */
>> +	struct invpcid_desc *desc_ptr = (struct invpcid_desc *)data;
>> +	bool lam_active = !!(flags & FLAGS_LAM_ACTIVE);
>> +	bool fault;
>> +
>> +	if (!this_cpu_has(X86_FEATURE_PCID) ||
> I don't _think_ we need to check for PCID support.  It's a KVM/QEMU bug if INVPCID
> is advertised but it doesn't work for the "all PCIDs" flavor.
OK, will remove it.

>
>> +	    !this_cpu_has(X86_FEATURE_INVPCID)) {
>> +		report_skip("INVPCID not supported");
>> +		return;
>> +	}
>> +
> ...
>
>> diff --git a/x86/unittests.cfg b/x86/unittests.cfg
>> index 3fe59449..224df45b 100644
>> --- a/x86/unittests.cfg
>> +++ b/x86/unittests.cfg
>> @@ -491,3 +491,13 @@ file = cet.flat
>>   arch = x86_64
>>   smp = 2
>>   extra_params = -enable-kvm -m 2048 -cpu host
>> +
>> +[intel-lam]
>> +file = lam.flat
>> +arch = x86_64
>> +extra_params = -enable-kvm -cpu host
>> +
>> +[intel-no-lam]
>> +file = lam.flat
>> +arch = x86_64
>> +extra_params = -enable-kvm -cpu host,-lam
> Hrm, not something that needs to be solved now, but we really need a better
> interface for iterating over features in tests :-/


  reply	other threads:[~2024-06-18  5:48 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-22  8:53 [kvm-unit-tests PATCH v6 0/4] x86: Add test cases for LAM Binbin Wu
2024-01-22  8:53 ` [kvm-unit-tests PATCH v6 1/4] x86: Allow setting of CR3 LAM bits if LAM supported Binbin Wu
2024-01-22  8:53 ` [kvm-unit-tests PATCH v6 2/4] x86: Add test case for LAM_SUP Binbin Wu
2024-06-05 18:24   ` Sean Christopherson
2024-06-18  5:48     ` Binbin Wu [this message]
2024-06-18  6:37       ` Binbin Wu
2024-01-22  8:53 ` [kvm-unit-tests PATCH v6 3/4] x86: Add test cases for LAM_{U48,U57} Binbin Wu
2024-06-05 18:53   ` Sean Christopherson
2024-01-22  8:53 ` [kvm-unit-tests PATCH v6 4/4] x86: Add test case for INVVPID with LAM Binbin Wu
2024-06-05 18:57   ` Sean Christopherson
2024-06-18  5:55     ` Binbin Wu
2024-06-24  8:20       ` Binbin Wu

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=00a74cb3-4f03-4eb3-a969-04293841f64a@linux.intel.com \
    --to=binbin.wu@linux.intel.com \
    --cc=chao.gao@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=robert.hu@linux.intel.com \
    --cc=seanjc@google.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