KVM Archive mirror
 help / color / mirror / Atom feed
From: Muhammad Usama Anjum <usama.anjum@collabora.com>
To: Xin Li <xin3.li@intel.com>,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org
Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>,
	seanjc@google.com, pbonzini@redhat.com, corbet@lwn.net,
	tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
	shuah@kernel.org, vkuznets@redhat.com, peterz@infradead.org,
	ravi.v.shankar@intel.com, xin@zytor.com
Subject: Re: [PATCH v2 25/25] KVM: selftests: Add fred exception tests
Date: Sat, 30 Mar 2024 01:18:54 +0500	[thread overview]
Message-ID: <42ca1da5-445b-47ca-a952-444eaa921360@collabora.com> (raw)
In-Reply-To: <20240207172646.3981-26-xin3.li@intel.com>

On 2/7/24 10:26 PM, Xin Li wrote:
> Add tests for FRED event data and VMX nested-exception.
> 
> FRED is designed to save a complete event context in its stack frame,
> e.g., FRED saves the faulting linear address of a #PF into a 64-bit
> event data field defined in FRED stack frame.  As such, FRED VMX adds
> event data handling during VMX transitions.
> 
> Besides, FRED introduces event stack levels to dispatch an event handler
> onto a stack baesd on current stack level and stack levels defined in
> IA32_FRED_STKLVLS MSR for each exception vector.  VMX nested-exception
> support ensures a correct event stack level is chosen when a VM entry
> injects a nested exception, which is regarded as occurred in ring 0.
> 
> To fully test the underlying FRED VMX code, this test should be run one
> more round with EPT disabled to inject page faults as nested exceptions.
> 
> Originally-by: Shan Kang <shan.kang@intel.com>
> Signed-off-by: Xin Li <xin3.li@intel.com>
Thank you for the new test patch. We have been trying to ensure TAP
conformance for tests which cannot be achieved if new tests aren't using
TAP already. Please make your test TAP compliant.

> ---
>  tools/testing/selftests/kvm/Makefile          |   1 +
>  .../selftests/kvm/include/x86_64/processor.h  |  32 ++
>  .../testing/selftests/kvm/x86_64/fred_test.c  | 297 ++++++++++++++++++
Add generated binary object to .gitignore.

>  3 files changed, 330 insertions(+)
>  create mode 100644 tools/testing/selftests/kvm/x86_64/fred_test.c
> 
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index 492e937fab00..eaac13a605f2 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -67,6 +67,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/get_msr_index_features
>  TEST_GEN_PROGS_x86_64 += x86_64/exit_on_emulation_failure_test
>  TEST_GEN_PROGS_x86_64 += x86_64/fix_hypercall_test
>  TEST_GEN_PROGS_x86_64 += x86_64/hwcr_msr_test
> +TEST_GEN_PROGS_x86_64 += x86_64/fred_test
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_clock
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_cpuid
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_evmcs
> diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
> index bc5cd8628a20..ef7aaab790e0 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/processor.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
> @@ -1275,4 +1275,36 @@ void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
>  #define PFERR_GUEST_PAGE_MASK	BIT_ULL(PFERR_GUEST_PAGE_BIT)
>  #define PFERR_IMPLICIT_ACCESS	BIT_ULL(PFERR_IMPLICIT_ACCESS_BIT)
>  
> +/*
> + * FRED related data structures and functions
> + */
> +
> +#define FRED_SSX_NMI		BIT_ULL(18)
> +
> +struct fred_stack {
> +	u64 r15;
> +	u64 r14;
> +	u64 r13;
> +	u64 r12;
> +	u64 bp;
> +	u64 bx;
> +	u64 r11;
> +	u64 r10;
> +	u64 r9;
> +	u64 r8;
> +	u64 ax;
> +	u64 cx;
> +	u64 dx;
> +	u64 si;
> +	u64 di;
> +	u64 error_code;
> +	u64 ip;
> +	u64 csx;
> +	u64 flags;
> +	u64 sp;
> +	u64 ssx;
> +	u64 event_data;
> +	u64 reserved;
> +};
> +
>  #endif /* SELFTEST_KVM_PROCESSOR_H */
> diff --git a/tools/testing/selftests/kvm/x86_64/fred_test.c b/tools/testing/selftests/kvm/x86_64/fred_test.c
> new file mode 100644
> index 000000000000..412afa919568
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/x86_64/fred_test.c
> @@ -0,0 +1,297 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * FRED nested exception tests
> + *
> + * Copyright (C) 2023, Intel, Inc.
> + */
> +#define _GNU_SOURCE /* for program_invocation_short_name */
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <asm/msr-index.h>
> +
> +#include "apic.h"
> +#include "kvm_util.h"
> +#include "test_util.h"
> +#include "guest_modes.h"
> +#include "processor.h"
> +
> +#define IRQ_VECTOR 0xAA
> +
> +#define FRED_STKLVL(v,l)		(_AT(unsigned long, l) << (2 * (v)))
> +#define FRED_CONFIG_ENTRYPOINT(p)	_AT(unsigned long, (p))
> +
> +/* This address is already mapped in guest page table. */
> +#define FRED_VALID_RSP			0x8000
> +
> +/*
> + * The following addresses are not yet mapped in both EPT and guest page
> + * tables at the beginning.  As a result, it causes an EPT violation VM
> + * exit with an original guest #PF to access any of them for the first
> + * time.
> + *
> + * Use these addresses as guest FRED RSP0 to generate nested #PFs to test
> + * if event data are properly virtualized.
> + */
> +static unsigned long fred_invalid_rsp[4] = {
> +	0x0,
> +	0xf0000000,
> +	0xe0000000,
> +	0xd0000000,
> +};
> +
> +extern char asm_user_nop[];
> +extern char asm_user_ud[];
> +extern char asm_done_fault[];
> +
> +extern void asm_test_fault(int test);
> +
> +/*
> + * user level code for triggering faults.
> + */
> +asm(".pushsection .text\n"
> +    ".align 4096\n"
> +
> +    ".type asm_user_nop, @function\n"
> +    "asm_user_nop:\n"
> +    "1: .byte 0x90\n"
> +    "jmp 1b\n"
> +
> +    ".fill asm_user_ud - ., 1, 0xcc\n"
> +
> +    ".type asm_user_ud, @function\n"
> +    ".org asm_user_nop + 16\n"
> +    "asm_user_ud:\n"
> +    /* Trigger a #UD */
> +    "ud2\n"
> +
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +/* Send current stack level and #PF address */
> +#define GUEST_SYNC_CSL_FA(__stage, __pf_address)		\
> +	GUEST_SYNC_ARGS(__stage, __pf_address, 0, 0, 0)
> +
> +void fred_entry_from_user(struct fred_stack *stack)
> +{
> +	u32 current_stack_level = rdmsr(MSR_IA32_FRED_CONFIG) & 0x3;
> +
> +	GUEST_SYNC_CSL_FA(current_stack_level, stack->event_data);
> +
> +	/* Do NOT go back to user level, continue the next test instead */
> +	stack->ssx = 0x18;
> +	stack->csx = 0x10;
> +	stack->ip = (u64)&asm_done_fault;
> +}
> +
> +void fred_entry_from_kernel(struct fred_stack *stack)
> +{
> +	/*
> +	 * Keep NMI blocked to delay the delivery of the next NMI until
> +	 * returning to user level.
> +	 * */
> +	stack->ssx &= ~FRED_SSX_NMI;
> +}
> +
> +#define PUSH_REGS	\
> +	"push %rdi\n"	\
> +	"push %rsi\n"	\
> +	"push %rdx\n"	\
> +	"push %rcx\n"	\
> +	"push %rax\n"	\
> +	"push %r8\n"	\
> +	"push %r9\n"	\
> +	"push %r10\n"	\
> +	"push %r11\n"	\
> +	"push %rbx\n"	\
> +	"push %rbp\n"	\
> +	"push %r12\n"	\
> +	"push %r13\n"	\
> +	"push %r14\n"	\
> +	"push %r15\n"
> +
> +#define POP_REGS	\
> +	"pop %r15\n"	\
> +	"pop %r14\n"	\
> +	"pop %r13\n"	\
> +	"pop %r12\n"	\
> +	"pop %rbp\n"	\
> +	"pop %rbx\n"	\
> +	"pop %r11\n"	\
> +	"pop %r10\n"	\
> +	"pop %r9\n"	\
> +	"pop %r8\n"	\
> +	"pop %rax\n"	\
> +	"pop %rcx\n"	\
> +	"pop %rdx\n"	\
> +	"pop %rsi\n"	\
> +	"pop %rdi\n"
> +
> +/*
> + * FRED entry points.
> + */
> +asm(".pushsection .text\n"
> +    ".type asm_fred_entrypoint_user, @function\n"
> +    ".align 4096\n"
> +    "asm_fred_entrypoint_user:\n"
> +    "endbr64\n"
> +    PUSH_REGS
> +    "movq %rsp, %rdi\n"
> +    "call fred_entry_from_user\n"
> +    POP_REGS
> +    /* Do NOT go back to user level, continue the next test instead */
> +    ".byte 0xf2,0x0f,0x01,0xca\n"	/* ERETS */
> +
> +    ".fill asm_fred_entrypoint_kernel - ., 1, 0xcc\n"
> +
> +    ".type asm_fred_entrypoint_kernel, @function\n"
> +    ".org asm_fred_entrypoint_user + 256\n"
> +    "asm_fred_entrypoint_kernel:\n"
> +    "endbr64\n"
> +    PUSH_REGS
> +    "movq %rsp, %rdi\n"
> +    "call fred_entry_from_kernel\n"
> +    POP_REGS
> +    ".byte 0xf2,0x0f,0x01,0xca\n"	/* ERETS */
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +extern char asm_fred_entrypoint_user[];
> +
> +/*
> + * Prepare a FRED stack frame for ERETU to return to user level code,
> + * nop or ud2.
> + *
> + * Because FRED RSP0 is deliberately not mapped in guest page table,
> + * the delivery of interrupt/NMI or #UD from ring 3 causes a nested
> + * #PF, which is then delivered on FRED RSPx (x is 1, 2 or 3,
> + * determinated by MSR FRED_STKLVL[PF_VECTOR]).
> + */
> +asm(".pushsection .text\n"
> +    ".type asm_test_fault, @function\n"
> +    ".align 4096\n"
> +    "asm_test_fault:\n"
> +    "endbr64\n"
> +    "push %rbp\n"
> +    "mov %rsp, %rbp\n"
> +    "and $(~0x3f), %rsp\n"
> +    "push $0\n"
> +    "push $0\n"
> +    "mov $0x2b, %rax\n"
> +    /* Unblock NMI */
> +    "bts $18, %rax\n"
> +    /* Set long mode bit */
> +    "bts $57, %rax\n"
> +    "push %rax\n"
> +    /* No stack required for the FRED user level test code */
> +    "push $0\n"
> +    "pushf\n"
> +    "pop %rax\n"
> +    /* Allow external interrupts */
> +    "bts $9, %rax\n"
> +    "push %rax\n"
> +    "mov $0x33, %rax\n"
> +    "push %rax\n"
> +    "cmp $0, %edi\n"
> +    "jne 1f\n"
> +    "lea asm_user_nop(%rip), %rax\n"
> +    "jmp 2f\n"
> +    "1: lea asm_user_ud(%rip), %rax\n"
> +    "2: push %rax\n"
> +    "push $0\n"
> +    /* ERETU to user level code to allow event delivery immediately */
> +    ".byte 0xf3,0x0f,0x01,0xca\n"
> +    "asm_done_fault:\n"
> +    "mov %rbp, %rsp\n"
> +    "pop %rbp\n"
> +    "ret\n"
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +/*
> + * To fully test the underlying FRED VMX code, this test should be run one
> + * more round with EPT disabled to inject page faults as nested exceptions.
> + */
> +static void guest_code(void)
> +{
> +	wrmsr(MSR_IA32_FRED_CONFIG,
> +	      FRED_CONFIG_ENTRYPOINT(asm_fred_entrypoint_user));
> +
> +	wrmsr(MSR_IA32_FRED_RSP1, FRED_VALID_RSP);
> +	wrmsr(MSR_IA32_FRED_RSP2, FRED_VALID_RSP);
> +	wrmsr(MSR_IA32_FRED_RSP3, FRED_VALID_RSP);
> +
> +	/* Enable FRED */
> +	set_cr4(get_cr4() | X86_CR4_FRED);
> +
> +	x2apic_enable();
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 1));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[1]);
> +	/* 1: ud2 to generate #UD */
> +	asm_test_fault(1);
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 2));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[2]);
> +	asm volatile("cli");
> +	/* Create a pending interrupt on current vCPU */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_FIXED | IRQ_VECTOR);
> +	/* Return to ring 3 */
> +	asm_test_fault(0);
> +	x2apic_write_reg(APIC_EOI, 0);
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 3));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[3]);
> +	/*
> +	 * The first NMI is just to have NMI blocked in ring 0, because
> +	 * fred_entry_from_kernel() deliberately clears the NMI bit in
> +	 * FRED stack frame.
> +	 */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_NMI | NMI_VECTOR);
> +	/* The second NMI will be delivered after returning to ring 3 */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_NMI | NMI_VECTOR);
> +	/* Return to ring 3 */
> +	asm_test_fault(0);
> +
> +	GUEST_DONE();
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct kvm_vm *vm;
> +	struct ucall uc;
> +	uint64_t expected_current_stack_level = 1;
> +
> +	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_FRED));
> +
> +	vm = __vm_create_with_vcpus(VM_SHAPE(VM_MODE_PXXV48_4K_USER), 1, 0,
> +				    guest_code, &vcpu);
> +
> +	while (true) {
> +		uint64_t r;
> +
> +		vcpu_run(vcpu);
> +
> +		r = get_ucall(vcpu, &uc);
> +
> +		if (r == UCALL_DONE)
> +			break;
> +
> +		if (r == UCALL_SYNC) {
> +			TEST_ASSERT((uc.args[1] == expected_current_stack_level) &&
> +				    (uc.args[2] == fred_invalid_rsp[expected_current_stack_level] - 1),
> +				    "Incorrect stack level %lx and #PF address %lx\n",
> +				    uc.args[1], uc.args[2]);
> +			expected_current_stack_level++;
> +		}
> +	}
> +
> +	kvm_vm_free(vm);
> +	return 0;
> +}

-- 
BR,
Muhammad Usama Anjum

WARNING: multiple messages have this Message-ID (diff)
From: Muhammad Usama Anjum <usama.anjum@collabora.com>
To: Xin Li <xin3.li@intel.com>,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org
Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>,
	seanjc@google.com, pbonzini@redhat.com, corbet@lwn.net,
	tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
	shuah@kernel.org, vkuznets@redhat.com, peterz@infradead.org,
	ravi.v.shankar@intel.com, xin@zytor.com
Subject: Re: [PATCH v2 25/25] KVM: selftests: Add fred exception tests
Date: Sat, 30 Mar 2024 01:18:54 +0500	[thread overview]
Message-ID: <42ca1da5-445b-47ca-a952-444eaa921360@collabora.com> (raw)
Message-ID: <20240329201854.f24ZDY24JtVE3gfa0i3m1MOFYfXVhCKdkXd0j5c-B6I@z> (raw)
In-Reply-To: <20240207172646.3981-26-xin3.li@intel.com>

On 2/7/24 10:26 PM, Xin Li wrote:
> Add tests for FRED event data and VMX nested-exception.
> 
> FRED is designed to save a complete event context in its stack frame,
> e.g., FRED saves the faulting linear address of a #PF into a 64-bit
> event data field defined in FRED stack frame.  As such, FRED VMX adds
> event data handling during VMX transitions.
> 
> Besides, FRED introduces event stack levels to dispatch an event handler
> onto a stack baesd on current stack level and stack levels defined in
> IA32_FRED_STKLVLS MSR for each exception vector.  VMX nested-exception
> support ensures a correct event stack level is chosen when a VM entry
> injects a nested exception, which is regarded as occurred in ring 0.
> 
> To fully test the underlying FRED VMX code, this test should be run one
> more round with EPT disabled to inject page faults as nested exceptions.
> 
> Originally-by: Shan Kang <shan.kang@intel.com>
> Signed-off-by: Xin Li <xin3.li@intel.com>
Thank you for the new test patch. We have been trying to ensure TAP
conformance for tests which cannot be achieved if new tests aren't using
TAP already. Please make your test TAP compliant.

> ---
>  tools/testing/selftests/kvm/Makefile          |   1 +
>  .../selftests/kvm/include/x86_64/processor.h  |  32 ++
>  .../testing/selftests/kvm/x86_64/fred_test.c  | 297 ++++++++++++++++++
Add generated binary object to .gitignore.

>  3 files changed, 330 insertions(+)
>  create mode 100644 tools/testing/selftests/kvm/x86_64/fred_test.c
> 
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index 492e937fab00..eaac13a605f2 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -67,6 +67,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/get_msr_index_features
>  TEST_GEN_PROGS_x86_64 += x86_64/exit_on_emulation_failure_test
>  TEST_GEN_PROGS_x86_64 += x86_64/fix_hypercall_test
>  TEST_GEN_PROGS_x86_64 += x86_64/hwcr_msr_test
> +TEST_GEN_PROGS_x86_64 += x86_64/fred_test
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_clock
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_cpuid
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_evmcs
> diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
> index bc5cd8628a20..ef7aaab790e0 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/processor.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
> @@ -1275,4 +1275,36 @@ void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
>  #define PFERR_GUEST_PAGE_MASK	BIT_ULL(PFERR_GUEST_PAGE_BIT)
>  #define PFERR_IMPLICIT_ACCESS	BIT_ULL(PFERR_IMPLICIT_ACCESS_BIT)
>  
> +/*
> + * FRED related data structures and functions
> + */
> +
> +#define FRED_SSX_NMI		BIT_ULL(18)
> +
> +struct fred_stack {
> +	u64 r15;
> +	u64 r14;
> +	u64 r13;
> +	u64 r12;
> +	u64 bp;
> +	u64 bx;
> +	u64 r11;
> +	u64 r10;
> +	u64 r9;
> +	u64 r8;
> +	u64 ax;
> +	u64 cx;
> +	u64 dx;
> +	u64 si;
> +	u64 di;
> +	u64 error_code;
> +	u64 ip;
> +	u64 csx;
> +	u64 flags;
> +	u64 sp;
> +	u64 ssx;
> +	u64 event_data;
> +	u64 reserved;
> +};
> +
>  #endif /* SELFTEST_KVM_PROCESSOR_H */
> diff --git a/tools/testing/selftests/kvm/x86_64/fred_test.c b/tools/testing/selftests/kvm/x86_64/fred_test.c
> new file mode 100644
> index 000000000000..412afa919568
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/x86_64/fred_test.c
> @@ -0,0 +1,297 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * FRED nested exception tests
> + *
> + * Copyright (C) 2023, Intel, Inc.
> + */
> +#define _GNU_SOURCE /* for program_invocation_short_name */
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <asm/msr-index.h>
> +
> +#include "apic.h"
> +#include "kvm_util.h"
> +#include "test_util.h"
> +#include "guest_modes.h"
> +#include "processor.h"
> +
> +#define IRQ_VECTOR 0xAA
> +
> +#define FRED_STKLVL(v,l)		(_AT(unsigned long, l) << (2 * (v)))
> +#define FRED_CONFIG_ENTRYPOINT(p)	_AT(unsigned long, (p))
> +
> +/* This address is already mapped in guest page table. */
> +#define FRED_VALID_RSP			0x8000
> +
> +/*
> + * The following addresses are not yet mapped in both EPT and guest page
> + * tables at the beginning.  As a result, it causes an EPT violation VM
> + * exit with an original guest #PF to access any of them for the first
> + * time.
> + *
> + * Use these addresses as guest FRED RSP0 to generate nested #PFs to test
> + * if event data are properly virtualized.
> + */
> +static unsigned long fred_invalid_rsp[4] = {
> +	0x0,
> +	0xf0000000,
> +	0xe0000000,
> +	0xd0000000,
> +};
> +
> +extern char asm_user_nop[];
> +extern char asm_user_ud[];
> +extern char asm_done_fault[];
> +
> +extern void asm_test_fault(int test);
> +
> +/*
> + * user level code for triggering faults.
> + */
> +asm(".pushsection .text\n"
> +    ".align 4096\n"
> +
> +    ".type asm_user_nop, @function\n"
> +    "asm_user_nop:\n"
> +    "1: .byte 0x90\n"
> +    "jmp 1b\n"
> +
> +    ".fill asm_user_ud - ., 1, 0xcc\n"
> +
> +    ".type asm_user_ud, @function\n"
> +    ".org asm_user_nop + 16\n"
> +    "asm_user_ud:\n"
> +    /* Trigger a #UD */
> +    "ud2\n"
> +
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +/* Send current stack level and #PF address */
> +#define GUEST_SYNC_CSL_FA(__stage, __pf_address)		\
> +	GUEST_SYNC_ARGS(__stage, __pf_address, 0, 0, 0)
> +
> +void fred_entry_from_user(struct fred_stack *stack)
> +{
> +	u32 current_stack_level = rdmsr(MSR_IA32_FRED_CONFIG) & 0x3;
> +
> +	GUEST_SYNC_CSL_FA(current_stack_level, stack->event_data);
> +
> +	/* Do NOT go back to user level, continue the next test instead */
> +	stack->ssx = 0x18;
> +	stack->csx = 0x10;
> +	stack->ip = (u64)&asm_done_fault;
> +}
> +
> +void fred_entry_from_kernel(struct fred_stack *stack)
> +{
> +	/*
> +	 * Keep NMI blocked to delay the delivery of the next NMI until
> +	 * returning to user level.
> +	 * */
> +	stack->ssx &= ~FRED_SSX_NMI;
> +}
> +
> +#define PUSH_REGS	\
> +	"push %rdi\n"	\
> +	"push %rsi\n"	\
> +	"push %rdx\n"	\
> +	"push %rcx\n"	\
> +	"push %rax\n"	\
> +	"push %r8\n"	\
> +	"push %r9\n"	\
> +	"push %r10\n"	\
> +	"push %r11\n"	\
> +	"push %rbx\n"	\
> +	"push %rbp\n"	\
> +	"push %r12\n"	\
> +	"push %r13\n"	\
> +	"push %r14\n"	\
> +	"push %r15\n"
> +
> +#define POP_REGS	\
> +	"pop %r15\n"	\
> +	"pop %r14\n"	\
> +	"pop %r13\n"	\
> +	"pop %r12\n"	\
> +	"pop %rbp\n"	\
> +	"pop %rbx\n"	\
> +	"pop %r11\n"	\
> +	"pop %r10\n"	\
> +	"pop %r9\n"	\
> +	"pop %r8\n"	\
> +	"pop %rax\n"	\
> +	"pop %rcx\n"	\
> +	"pop %rdx\n"	\
> +	"pop %rsi\n"	\
> +	"pop %rdi\n"
> +
> +/*
> + * FRED entry points.
> + */
> +asm(".pushsection .text\n"
> +    ".type asm_fred_entrypoint_user, @function\n"
> +    ".align 4096\n"
> +    "asm_fred_entrypoint_user:\n"
> +    "endbr64\n"
> +    PUSH_REGS
> +    "movq %rsp, %rdi\n"
> +    "call fred_entry_from_user\n"
> +    POP_REGS
> +    /* Do NOT go back to user level, continue the next test instead */
> +    ".byte 0xf2,0x0f,0x01,0xca\n"	/* ERETS */
> +
> +    ".fill asm_fred_entrypoint_kernel - ., 1, 0xcc\n"
> +
> +    ".type asm_fred_entrypoint_kernel, @function\n"
> +    ".org asm_fred_entrypoint_user + 256\n"
> +    "asm_fred_entrypoint_kernel:\n"
> +    "endbr64\n"
> +    PUSH_REGS
> +    "movq %rsp, %rdi\n"
> +    "call fred_entry_from_kernel\n"
> +    POP_REGS
> +    ".byte 0xf2,0x0f,0x01,0xca\n"	/* ERETS */
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +extern char asm_fred_entrypoint_user[];
> +
> +/*
> + * Prepare a FRED stack frame for ERETU to return to user level code,
> + * nop or ud2.
> + *
> + * Because FRED RSP0 is deliberately not mapped in guest page table,
> + * the delivery of interrupt/NMI or #UD from ring 3 causes a nested
> + * #PF, which is then delivered on FRED RSPx (x is 1, 2 or 3,
> + * determinated by MSR FRED_STKLVL[PF_VECTOR]).
> + */
> +asm(".pushsection .text\n"
> +    ".type asm_test_fault, @function\n"
> +    ".align 4096\n"
> +    "asm_test_fault:\n"
> +    "endbr64\n"
> +    "push %rbp\n"
> +    "mov %rsp, %rbp\n"
> +    "and $(~0x3f), %rsp\n"
> +    "push $0\n"
> +    "push $0\n"
> +    "mov $0x2b, %rax\n"
> +    /* Unblock NMI */
> +    "bts $18, %rax\n"
> +    /* Set long mode bit */
> +    "bts $57, %rax\n"
> +    "push %rax\n"
> +    /* No stack required for the FRED user level test code */
> +    "push $0\n"
> +    "pushf\n"
> +    "pop %rax\n"
> +    /* Allow external interrupts */
> +    "bts $9, %rax\n"
> +    "push %rax\n"
> +    "mov $0x33, %rax\n"
> +    "push %rax\n"
> +    "cmp $0, %edi\n"
> +    "jne 1f\n"
> +    "lea asm_user_nop(%rip), %rax\n"
> +    "jmp 2f\n"
> +    "1: lea asm_user_ud(%rip), %rax\n"
> +    "2: push %rax\n"
> +    "push $0\n"
> +    /* ERETU to user level code to allow event delivery immediately */
> +    ".byte 0xf3,0x0f,0x01,0xca\n"
> +    "asm_done_fault:\n"
> +    "mov %rbp, %rsp\n"
> +    "pop %rbp\n"
> +    "ret\n"
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +/*
> + * To fully test the underlying FRED VMX code, this test should be run one
> + * more round with EPT disabled to inject page faults as nested exceptions.
> + */
> +static void guest_code(void)
> +{
> +	wrmsr(MSR_IA32_FRED_CONFIG,
> +	      FRED_CONFIG_ENTRYPOINT(asm_fred_entrypoint_user));
> +
> +	wrmsr(MSR_IA32_FRED_RSP1, FRED_VALID_RSP);
> +	wrmsr(MSR_IA32_FRED_RSP2, FRED_VALID_RSP);
> +	wrmsr(MSR_IA32_FRED_RSP3, FRED_VALID_RSP);
> +
> +	/* Enable FRED */
> +	set_cr4(get_cr4() | X86_CR4_FRED);
> +
> +	x2apic_enable();
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 1));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[1]);
> +	/* 1: ud2 to generate #UD */
> +	asm_test_fault(1);
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 2));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[2]);
> +	asm volatile("cli");
> +	/* Create a pending interrupt on current vCPU */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_FIXED | IRQ_VECTOR);
> +	/* Return to ring 3 */
> +	asm_test_fault(0);
> +	x2apic_write_reg(APIC_EOI, 0);
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 3));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[3]);
> +	/*
> +	 * The first NMI is just to have NMI blocked in ring 0, because
> +	 * fred_entry_from_kernel() deliberately clears the NMI bit in
> +	 * FRED stack frame.
> +	 */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_NMI | NMI_VECTOR);
> +	/* The second NMI will be delivered after returning to ring 3 */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_NMI | NMI_VECTOR);
> +	/* Return to ring 3 */
> +	asm_test_fault(0);
> +
> +	GUEST_DONE();
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct kvm_vm *vm;
> +	struct ucall uc;
> +	uint64_t expected_current_stack_level = 1;
> +
> +	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_FRED));
> +
> +	vm = __vm_create_with_vcpus(VM_SHAPE(VM_MODE_PXXV48_4K_USER), 1, 0,
> +				    guest_code, &vcpu);
> +
> +	while (true) {
> +		uint64_t r;
> +
> +		vcpu_run(vcpu);
> +
> +		r = get_ucall(vcpu, &uc);
> +
> +		if (r == UCALL_DONE)
> +			break;
> +
> +		if (r == UCALL_SYNC) {
> +			TEST_ASSERT((uc.args[1] == expected_current_stack_level) &&
> +				    (uc.args[2] == fred_invalid_rsp[expected_current_stack_level] - 1),
> +				    "Incorrect stack level %lx and #PF address %lx\n",
> +				    uc.args[1], uc.args[2]);
> +			expected_current_stack_level++;
> +		}
> +	}
> +
> +	kvm_vm_free(vm);
> +	return 0;
> +}

-- 
BR,
Muhammad Usama Anjum

X-sender: <linux-kernel+bounces-125382-steffen.klassert=secunet.com@vger.kernel.org>
X-Receiver: <steffen.klassert@secunet.com> ORCPT=rfc822;steffen.klassert@secunet.com NOTIFY=NEVER; X-ExtendedProps=BQAVABYAAgAAAAUAFAARAPDFCS25BAlDktII2g02frgPADUAAABNaWNyb3NvZnQuRXhjaGFuZ2UuVHJhbnNwb3J0LkRpcmVjdG9yeURhdGEuSXNSZXNvdXJjZQIAAAUAagAJAAEAAAAAAAAABQAWAAIAAAUAQwACAAAFAEYABwADAAAABQBHAAIAAAUAEgAPAGIAAAAvbz1zZWN1bmV0L291PUV4Y2hhbmdlIEFkbWluaXN0cmF0aXZlIEdyb3VwIChGWURJQk9IRjIzU1BETFQpL2NuPVJlY2lwaWVudHMvY249U3RlZmZlbiBLbGFzc2VydDY4YwUACwAXAL4AAACheZxkHSGBRqAcAp3ukbifQ049REI2LENOPURhdGFiYXNlcyxDTj1FeGNoYW5nZSBBZG1pbmlzdHJhdGl2ZSBHcm91cCAoRllESUJPSEYyM1NQRExUKSxDTj1BZG1pbmlzdHJhdGl2ZSBHcm91cHMsQ049c2VjdW5ldCxDTj1NaWNyb3NvZnQgRXhjaGFuZ2UsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1zZWN1bmV0LERDPWRlBQAOABEABiAS9uuMOkqzwmEZDvWNNQUAHQAPAAwAAABtYngtZXNzZW4tMDIFADwAAgAADwA2AAAATWljcm9zb2Z0LkV4Y2hhbmdlLlRyYW5zcG9ydC5NYWlsUmVjaXBpZW50LkRpc3BsYXlOYW1lDwARAAAAS2xhc3NlcnQsIFN0ZWZmZW4FAAwAAgAABQBsAAIAAAUAWAAXAEoAAADwxQktuQQJQ5LSCNoNNn64Q049S2xhc3NlcnQgU3RlZmZlbixPVT1Vc2VycyxPVT1NaWdyYXRpb24sREM9c2VjdW5ldCxEQz1kZQUAJgACAAEFACIADwAxAAAAQXV0b1Jlc3BvbnNlU3VwcHJlc3M6IDANClRyYW5zbWl0SGlzdG9yeTogRmFsc2UNCg8ALwAAAE1pY3Jvc29mdC5FeGNoYW5nZS5UcmFuc3BvcnQuRXhwYW5zaW9uR3JvdXBUeXBlDwAVAAAATWVtYmVyc0dyb3VwRXhwYW5zaW9uBQAjAAIAAQ==
X-CreatedBy: MSExchange15
X-HeloDomain: b.mx.secunet.com
X-ExtendedProps: BQBjAAoAdEWmlidQ3AgFAGEACAABAAAABQA3AAIAAA8APAAAAE1pY3Jvc29mdC5FeGNoYW5nZS5UcmFuc3BvcnQuTWFpbFJlY2lwaWVudC5Pcmdhbml6YXRpb25TY29wZREAAAAAAAAAAAAAAAAAAAAAAAUASQACAAEFAAQAFCABAAAAHAAAAHN0ZWZmZW4ua2xhc3NlcnRAc2VjdW5ldC5jb20FAAYAAgABBQApAAIAAQ8ACQAAAENJQXVkaXRlZAIAAQUAAgAHAAEAAAAFAAMABwAAAAAABQAFAAIAAQUAYgAKAD0AAADLigAABQBkAA8AAwAAAEh1Yg==
X-Source: SMTP:Default MBX-ESSEN-02
X-SourceIPAddress: 62.96.220.37
X-EndOfInjectedXHeaders: 31682
Received: from cas-essen-01.secunet.de (10.53.40.201) by
 mbx-essen-02.secunet.de (10.53.40.198) with Microsoft SMTP Server
 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id
 15.1.2507.37; Fri, 29 Mar 2024 21:18:58 +0100
Received: from b.mx.secunet.com (62.96.220.37) by cas-essen-01.secunet.de
 (10.53.40.201) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35 via Frontend
 Transport; Fri, 29 Mar 2024 21:18:58 +0100
Received: from localhost (localhost [127.0.0.1])
	by b.mx.secunet.com (Postfix) with ESMTP id EF002202A6
	for <steffen.klassert@secunet.com>; Fri, 29 Mar 2024 21:18:57 +0100 (CET)
X-Virus-Scanned: by secunet
X-Spam-Flag: NO
X-Spam-Score: -5.051
X-Spam-Level:
X-Spam-Status: No, score=-5.051 tagged_above=-999 required=2.1
	tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1,
	DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249,
	MAILING_LIST_MULTI=-1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001,
	SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: a.mx.secunet.com (amavisd-new);
	dkim=pass (2048-bit key) header.d=collabora.com
Received: from b.mx.secunet.com ([127.0.0.1])
	by localhost (a.mx.secunet.com [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id Xr8udnqlhNFw for <steffen.klassert@secunet.com>;
	Fri, 29 Mar 2024 21:18:56 +0100 (CET)
Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=139.178.88.99; helo=sv.mirrors.kernel.org; envelope-from=linux-kernel+bounces-125382-steffen.klassert=secunet.com@vger.kernel.org; receiver=steffen.klassert@secunet.com 
DKIM-Filter: OpenDKIM Filter v2.11.0 b.mx.secunet.com 89D0720270
Authentication-Results: b.mx.secunet.com;
	dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="L2zt8eif"
Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org [139.178.88.99])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by b.mx.secunet.com (Postfix) with ESMTPS id 89D0720270
	for <steffen.klassert@secunet.com>; Fri, 29 Mar 2024 21:18:56 +0100 (CET)
Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by sv.mirrors.kernel.org (Postfix) with ESMTPS id 11B09286CE4
	for <steffen.klassert@secunet.com>; Fri, 29 Mar 2024 20:18:54 +0000 (UTC)
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
	by smtp.subspace.kernel.org (Postfix) with ESMTP id D6E6713BC1B;
	Fri, 29 Mar 2024 20:18:38 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
	dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="L2zt8eif"
Received: from madrid.collaboradmins.com (madrid.collaboradmins.com [46.235.227.194])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4699D13BAD1;
	Fri, 29 Mar 2024 20:18:32 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=46.235.227.194
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
	t=1711743514; cv=none; b=j2hUMl9NyGzSDJP9D+OX7+sbNQl02uJeOwLiIYfS7ZIoMaBPLsqmW/jyWFUtGqZN4jPEzBxKaNM7IowzhVMslqTg+//xfLymH6hV62MaIaGnIgOuOii5e9xzwtIRkH5HWMjNpof2iW7QWN7Tcw8zkKXKTjtgqP9CWAgXF8imcAQ=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
	s=arc-20240116; t=1711743514; c=relaxed/simple;
	bh=M1bVLI2QVrqN4cSmcZhh5HNh6nWGHhPJEonGQgPvO00=;
	h=Message-ID:Date:MIME-Version:Cc:Subject:To:References:From:
	 In-Reply-To:Content-Type; b=Q8XWirNIrCY/iG2sgaBNL9z10ipPNp8KvMULAgzBLiQ3oxYnUsFdhW++cX5jhVlGbpdAUnZG20D2pnBZ2mgswRNCJhh4m1A3AuXfmG60vYtoGDkDdiVVeJcQA7IKbu/UkeUEIi7tV7upwlWyDD7BLzxzw0IOs1hlQVJFBV1BUWw=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=L2zt8eif; arc=none smtp.client-ip=46.235.227.194
Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=collabora.com
Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com;
	s=mail; t=1711743510;
	bh=M1bVLI2QVrqN4cSmcZhh5HNh6nWGHhPJEonGQgPvO00=;
	h=Date:Cc:Subject:To:References:From:In-Reply-To:From;
	b=L2zt8eif9xbOYilCC0YsH5YJqm0E16o6ScfkTW8PJ/tzy1yVnA9m7MIrFJkygElI4
	 9hCl+N3ah/v40+3Yx+05eCqrFqcX/Awpvn4TAeuhHQOQ+2N0rNKzn/gOCGMxoZr/Gq
	 DF/h2vk8S2rZYUfUNjluciLLrYgJv+amN4UxvGROCmzTJmOZ+DVJJnw3K4pPOUc4TY
	 i/xNMJah3fDLREZOStrAZWyACogXW5CaWGDtRv5u0TLiGFA9n0LpoIpiTsYcr08Jxl
	 b7svNLTCyPu+7BoeuNWz0Bky0Jlr+lhnkzgi3pd6Fh/OFrM5fTlRMzBRvyWIRIa/JA
	 +luzgRZU3AZeg==
Received: from [100.113.15.66] (ec2-34-240-57-77.eu-west-1.compute.amazonaws.com [34.240.57.77])
	(using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256)
	(No client certificate requested)
	(Authenticated sender: usama.anjum)
	by madrid.collaboradmins.com (Postfix) with ESMTPSA id 9C34B3780C21;
	Fri, 29 Mar 2024 20:18:23 +0000 (UTC)
Message-ID: <42ca1da5-445b-47ca-a952-444eaa921360@collabora.com>
Date: Sat, 30 Mar 2024 01:18:54 +0500
Precedence: bulk
X-Mailing-List: linux-kernel@vger.kernel.org
List-Id: <linux-kernel.vger.kernel.org>
List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org>
List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org>
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>, seanjc@google.com,
 pbonzini@redhat.com, corbet@lwn.net, tglx@linutronix.de, mingo@redhat.com,
 bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
 shuah@kernel.org, vkuznets@redhat.com, peterz@infradead.org,
 ravi.v.shankar@intel.com, xin@zytor.com
Subject: Re: [PATCH v2 25/25] KVM: selftests: Add fred exception tests
To: Xin Li <xin3.li@intel.com>, linux-kernel@vger.kernel.org,
 kvm@vger.kernel.org, linux-doc@vger.kernel.org,
 linux-kselftest@vger.kernel.org
References: <20240207172646.3981-1-xin3.li@intel.com>
 <20240207172646.3981-26-xin3.li@intel.com>
Content-Language: en-US
From: Muhammad Usama Anjum <usama.anjum@collabora.com>
In-Reply-To: <20240207172646.3981-26-xin3.li@intel.com>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Return-Path: linux-kernel+bounces-125382-steffen.klassert=secunet.com@vger.kernel.org
X-MS-Exchange-Organization-OriginalArrivalTime: 29 Mar 2024 20:18:58.0490
 (UTC)
X-MS-Exchange-Organization-Network-Message-Id: 7abcb20b-c178-40ec-af7b-08dc502d7707
X-MS-Exchange-Organization-OriginalClientIPAddress: 62.96.220.37
X-MS-Exchange-Organization-OriginalServerIPAddress: 10.53.40.201
X-MS-Exchange-Organization-Cross-Premises-Headers-Processed: cas-essen-01.secunet.de
X-MS-Exchange-Organization-OrderedPrecisionLatencyInProgress: LSRV=mbx-essen-02.secunet.de:TOTAL-HUB=0.233|SMR=0.133(SMRDE=0.003|SMRC=0.129(SMRCL=0.103|X-SMRCR=0.128))|CAT=0.099(CATRESL=0.029
 (CATRESLP2R=0.019)|CATORES=0.064(CATRS=0.064(CATRS-Transport Rule
 Agent=0.001(X-ETREX=0.001 )|CATRS-Index Routing
 Agent=0.060))|CATORT=0.003(CATRT=0.003(CATRT-Journal Agent=0.003
 )));2024-03-29T20:18:58.317Z
X-MS-Exchange-Forest-ArrivalHubServer: mbx-essen-02.secunet.de
X-MS-Exchange-Organization-AuthSource: cas-essen-01.secunet.de
X-MS-Exchange-Organization-AuthAs: Anonymous
X-MS-Exchange-Organization-FromEntityHeader: Internet
X-MS-Exchange-Organization-OriginalSize: 19243
X-MS-Exchange-Organization-HygienePolicy: Standard
X-MS-Exchange-Organization-MessageLatency: SRV=cas-essen-01.secunet.de:TOTAL-FE=0.034|SMR=0.024(SMRPI=0.021(SMRPI-FrontendProxyAgent=0.021))|SMS=0.010
X-MS-Exchange-Organization-Recipient-Limit-Verified: True
X-MS-Exchange-Organization-TotalRecipientCount: 1
X-MS-Exchange-Organization-Rules-Execution-History: 0b0cf904-14ac-4724-8bdf-482ee6223cf2%%%fd34672d-751c-45ae-a963-ed177fcabe23%%%d8080257-b0c3-47b4-b0db-23bc0c8ddb3c%%%95e591a2-5d7d-4afa-b1d0-7573d6c0a5d9%%%f7d0f6bc-4dcc-4876-8c5d-b3d6ddbb3d55%%%16355082-c50b-4214-9c7d-d39575f9f79b
X-MS-Exchange-Forest-RulesExecuted: mbx-essen-02
X-MS-Exchange-Organization-RulesExecuted: mbx-essen-02
X-MS-Exchange-Forest-IndexAgent-0: AQ0CZW4AAa8WAAAPAAADH4sIAAAAAAAEAMU6C1fbVpoSfvHOm6avmT
 u0zdqJMbYhhCTtnFDipJxAYDBkM6fToyPLMqixJY9kE9ht53/uv9nv
 oStLsgROmp31SYx87/d993s/rv0/7X1b1FcfrdbXRa36pL4hDvbK4q
 1li11LvHedgflkYfavYqvdFgPTG3ii47jixWHjuTDPTHsg2vpAF7rd
 Fm/23gobIMz2inlumP2B5dgVQEVsgrc80TY968Q2gZQjPP3MFLownF
 6/aw5Mn5zh2APzfCDgfAsO8wa68U50XL1nlpGQWTmplJkc4nticGqK
 jj7sDiz7RHQt29Rdobfbrul5wukA/W8OXgAxOE8XG+srLWtAZEasdy
 yz2wbGOhbyBccy8dG5FSG2gJGhceofjILCEV6M0CkooYtctIcu/kGw
 gavbnoWa8KQqfgQVgBp8WsCZ67SHBkjCpPjgLnzoeqiltuX19YFxCi
 r2Iegc00VaDsvFOC3d9NqwJIyh68ZIkYEipEcCI6GdrbW6hgxpzaNX
 u292m2KveUiWNnU4O7CnODONgeOCSpKsjZS8Yb/vuANh2t4QjEAGBn
 aMwbh86BDGqeOZtnh/Cm86EAW8gXuBhCz7V8BCAnzMiIkygFvAFaC7
 5onutmFTB2sbJDjZkAxQlSo/ckRn2O1ekAOTxwzttul2LxAqMKnhtM
 0y7AJZgvNOnSF4RssU7tAGvZpIque48NkBfPHeGpyKxsERmkhvddmp
 mWvR1098t/SQtbgEgTPsu9aJZevA20rr4ologm3FKx24+t6Dx8o7eH
 wGLmJ2KxAmhNGk+FlxOh3C8OP0+3PLXqt0rQjwEZB4Jy6cIRkSxbbN
 9ywbuVRF/KcJ3gRR2DJB/aB31AcIwbYTR1sHC7MQj4Dd023DZDKUA9
 gAhm7bzgA1BE5igUlB953gEJAc3PA/BmLoAV1gZ+tA6F3X1NsXFXHQ
 NXXPFD39nYkcMl08kfOBpdsD0BEKvLKygn+AL6frrSIYUFv1zG6HDl
 l9d9Zb3QMyHatriuD1G/yviQeEWalUYvCWbXSHbXP1fHND21hf7bsO
 BKAHfn1KmGt18WCEmnykj9oBh9NwtWIgav3xI0CNvxZmMXuemLbp6u
 gHLTC5eyGcFvkKKLxyAjnixAbf8oUWawLlwfgAFzDbZbG2VgXn8kyX
 /Kf4oERgBqgTUmcPXBeSd3Vjff1SPY0z7fth2+p0QNPAhtBXJ9J0ay
 IwDuS2eS7WH9fNx2uPOnqrWq1UTF03amv6RvVhp+4z7tt6wvMRGjT7
 AWw8eyZWNh6VN8QDeH+EH48azSPtZeO1dnC4/7KpsXLEgx+Er6YTc6
 D1PFcjAbQOaBozGun9KlTz3Bpojq2ZvWFXR4tpHd3qAjqpfSISHetc
 O73om64B6WFytNP3hktcS4wHVx4kvWEy+sjSmWZ0HePdByH0h1b7Qx
 DMs57hfZBvXhLVl7tJOuLIf1vGQ6O9uVHf1Ovov51Huq63Hj2umtUP
 8t/Lj7raoy/HRx+v1R89LIM+6e/aBq6dOVZbnFkuuLPe16j2Fr2BO4
 TkAzS1s564f9YriyEUj411bSDOsIEKfe7TZzLeN9w3iIMXjcND7eUx
 2vJg62VD29tqvpLJ98edI+14d7c4BgQbpQQyO3sHuzvbgLS1vd1oNp
 PJxIAkLVLb6n36I+5zNXfNLuVZastYUO5FoGp3hrZBKdTHWKW/9CaZ
 4j6o+VZ7vbcj4szUNksjDF+JFEHc2Pw3k8XXELzarT18Gl9ZH1tZG1
 upx1Za/fjC+RhObWylGl95HF/YjC3ocbJGfKEdX/CsOER8wXRdx9Ww
 vYptWHGpDC9OvdPVT7z4iXE0bwyNek0N7R+X2IQSCo0KL//+NLCl+M
 a0IdOI1fui2dh9QUnq1Zs9TFLobvuH2k++s0ycjxJahMuDO7E8Uz9F
 JTdU5Ud5qRp6VSrrtbre0R/XHj/c2JQJabVtnq3a0P9OlmGSmcDMUi
 1XIa2Uscd59ozjblU0D56/Xdm1DOgZzZWdNqjdgonKfSJeHuyu1CvV
 FcfuXiQFabwn5p7RB5GQ207/Alrk04EobpdEvVpfK4sdbHHxj1GJxL
 AMX+3l62OtuX98uN1Aa2LTCmnyBEY5qORnjsH1GLp7yIc2zHcBvp9b
 xfcdwx50K6d/jS17g7blJC53rVbSOk4hCesX3qrlGEkn6F5vFWr3Cp
 lWbkdhlvW+ZVROl2OrmMeHA6s7voNqTdk6GeIeupU3vhkqLcvjOXLn
 8G/am8b20f6hqJ5vbaUlURomi2flbkmEX0Vt66g4tP27gK5jn5QFgH
 z/vSjWwerFs1KpNE5te//1i52XWuP10eHfD/Z3Xh8V+0Q2gRjshNI0
 eMERjnXyXgAfeRCBAaTf55GRlMGD2wDHuUrcr4iHN1u7O8+1w+aBSH
 5VzzchEMNHS1c+wosKp9t13uOU5bNi0pAkcIq6MAchblqOP1xizRqx
 JokRh4DL02zLhCHSRmejqwodsxyMnmUBKcrQh3SKTdTOLIf7UZh4JS
 3sVXmYBSDHH0j9M/HyBK8YDHQF2L/AOxU4sheMlB3L9ftMZMvqmZVY
 CB/DmAeA8B6S2fPpUyYAbVbxFDkgydQAh9MVSNDJAjXI0OFrJ9Ad+G
 kfZ3lqcIZ61/ovsx1NDFCZB5YhIi7CNRvyASC0Ndfr/7z+i/ghXL6r
 59Vy+FPHT7KRRTNpsR1ZDNWYB+b5wHRtHOpc0AFELBQjzXb6P//yNH
 1/2E7bbju2qdEtg4QIg1HXh2CUAQisCB0dqbP0NMlF8Tj/agarNdsY
 HOLEpPsUvs+I6hboF5cr/aF36pnUV4kKXt/9w14ONLJcAR2f2GK9+n
 hDroc2B9DuR5RRFs9kkxYhE4Z5EtmpPRGV1gU4TvX8cTWy82uvL2qt
 hFOhoHbDKhYrolIWtTKQMIwruRy205isOO5JRBpYr20kyzFsR8TALM
 XKxlvL4+dSxYQ0bNcTuBopNso47/advm+U5ai9RRN6ndRrQox5mSlj
 KZBb+ebfX29r281d7cVWUcO+98QsC03rdzQfLZrs/zGKjRD+1uHLZj
 I2iML/QhmcfJlClu4HtY7rsBKL4y34ffrDyOF2fK0uRWZAHoQg6N02
 1NziXhNmjOAalGtNSdwDva49jeo9QQ0JhMus2JW/jnrRUpwQmOK5I1
 7vH4kTR7SQeUh3oygs0224ZQ9N//bunKMXL4IGUL7CHiJPg14YRKqe
 18Ktvb9nyL3q+J7Vh60itMile9HU4nfKV9jiHWSc0VR5tTVk0qHXff
 HKNPsCx60W3ivwVWobprgLEhyerDPTlcWHFYHQQ9BON0LINWHUs/17
 zJEmKxGgFLXd+0H8Kzz7jUkeTK3HzZ+0w8bLZsy9lzEPiu/ctgWBmL
 zlpW+1z1O3jPQtPX1rk3eSth6nb9WqqQRrtdStVjobrX46wXr61lr6
 1nr61sNIlgwMtn8Q2CuKBgnax0rZWk/fWkvfqqduSW0kbZ2nE6ylb1
 VTt6SVE7Y207f0dDaM9K12+pb0+SQsK2Kv2IhI+UX0HehaPqbtCGr2
 KFkRLSocqQV8vFmh9TQ60U4E6mrL3VgPrwXJYgTVc87+iXqBViesAt
 rD297ESheh6ftzuHf4VIVkWbZSnXoZeuAOvtXgzdB9K8JZjcPGUTNy
 d8aYQVcV1xSXh4mbrGT0K3uuJPsATP3h1abkE/4txuSjLjXnB9sg7r
 of0A7Gh4okJUbGi1GQHrhmH0cwfew7cxodkMNjdEQuylGX5K9bJSVs
 lAEDutz4+PijSRNsaFKknxF0rRbNijD34fCcPsYHR8QbCfym1HWH/c
 EqdhJwOLbcaCD+8ngtmJz9cVTSgfY49AX0AL+49sma9O27ZPRcFM8R
 Aty9juTXAk7aJpzcgymbvgu8oK/aQ9clPx+88K9Wfin9kaw3Gvs+Jt
 eNsK8MikihjwRGEBexLRwzvi3+C1rrTqlMQOP0vq1euYYnfFs9r7fK
 smyFE+KxTc0kNYrhMGkNPPFtbTMRp2kO+HqA7lpb1mAc8+GjccxIMx
 am99rxo8I1/zm00EPkvQm5SSgcKB3T1B0+MU0TnejKqG6HD9/CyybB
 8a13Rw7vjQv1eFKZpM7X1ibGMGAG/xbmue/MWHb8FTqzWlSSrqlHpu
 fid67VLyUchYN9PYpbeyIi6MN2Knb9iUjmNUHffqo9TkhfdDXGSuY7
 KZlerF4PhOX0lFha18bTejT8RvPXk4SgavWTombUX44WIfWmhfwHXR
 nI3PUJf0qD5D7hz2lE/L6P5lS+4kZ+ivh5bA5976bN/qErPX6l3EGn
 1czS2LSfdBYUilo5drVcenolTv0jcNZScEaI6Oo26p4tGRmTTdCiu1
 488f+WxG/i7eaGtn24TgeM0Tqv4xcVoBSkV5xIF/5Pz8qR7w6CYgiN
 Y2kCKSHRjF3t1n4JI4KUkCqg1YjcOccu3OIXp7VPIkH9YyWoRyQA3s
 C78SIfVLtsdK3lmHzb/LMgXfTxS02IzCD3h38feLZ9cByR2bfZe9ca
 mJprnhS3Dna2tZ1t4JyentO1V2P3BRift14faVvNZuPwSPwWD5fQi5
 H3tBc7b8Gtfgt9eRTj+zBoFP0e7BKLVMO4yZw39nfwGvFTWG7tYy23
 FvO9kJr874TwCxRqUiBb/jr06Adh9Ku88H1Y8JvGMmRR6kwjhFKu40
 rRTtmA+ujyT2aJtjXwf/4Z0Bn77Wt499/oKcjeb8hksp+g3qBOOVA2
 EPI9jp0tM9SH6x3w9+hlYIJH/T9L8THePgLgS+jn+68bMruGbirxe5
 6ebtn0hY/unhhlHvDuw/PZz7+MlcHwr4GM/lDcx/enyfv0a6HxvSEN
 u0Mj/IML+QMi87wPZRxcNPkCvhaXjX59cdj42/HOYaOIhwI32qnuFb
 HkvGhsHR0fNrjsjKkF2PtBaBriUBLUsK8gobzimz2t+dPWQQMf9vaf
 N7SDt2/frG9q66+0YzBqie8mxgp/8mvUWZTFPaQ/nmdO8VcbRVCPWQ
 p/syhfgXrcOKZ8IVkNWqZiIn35ckFirMtkAQIFjoZGKrzVEUXA+UEc
 b2/t7pILldJlboEa301ICr8SSRRVvsiwHEHF4tCogDt6UJ6RwmU+Uh
 L37k1mlYBonYiOpePLTvlFrECPMaH5l3ds+cP28Bdo33XPx75EgzXo
 siekO1JKWYxkCWeO+OsykR48SED8fbT0e8yuHODYz0K/3Auf6t/hVI
 NUszCLP8z+8RDk2hue6r2e3hbHnt7TxZb967CHAIoypWRUVcnzP2VK
 Vaam1My0okwrsxklC7s5esgpeXjPKjl4gHd4hn+Acl0pzCg3YAUgp5
 UZeIdnIALPAFlQpmGF0YlOninACgDklQIDqErGR1SnphRkIo9YhZyE
 ZzB+zvnPPhtZZZrBmCCszCm3CsoMrMwqcwSfh/WAPaI2x0zyLiwWiA
 gzxvB0Yj6rKjeUHADDRxYZnmeU2bwyExJ/AXbhHxAM6DBZoMMH0bkz
 DJNHlDkGYJZ8vakAqaiSSZZullilc3EF/rEsxEwhbA4mwicyDLzPKj
 dnVWVBmZsizrMk0S2iQ8JO53G3QIbO8juLzDxkpE6Cf4RYYFuED8oo
 uTllXho6ovBApTk6qEBmYnTmfEa5yyaeIU+bVpdID/P8ETWPzpmdIl
 +FRVXN0/NigBIGAP5niLKqAnElo9ylI8BkBeIqO6PeIPpo/YI6QzCg
 55vIlQoSKcRq/griynSWxPHpBMwrM2Mr8/BxXlmcVxeI+OIYwPX4in
 oNuVKzyKc6NXqGo1XlDikN7eJzlQ9zCM9LZCkAmFYWroQHgD+RueHo
 Ago1M8kRN0mlkwBn0cHYgScCJvVeDQl+O49mmv0/gJxJtGyCH1K2vA
 omd7n1k1DiLpQUApBnwAvz7CH8zBJlyUkWpaQYm5hOMbSnKGVNKwWi
 Xwg9z6PPo37yOT/PzANWgR1JVW7L9QzFEUNSvl0Mg33uL4L2ljhnch
 KmAPyK4gs0zLVD0veFWuDdWVTXDQJYTHwHyOA9bf3y9xyeArJci9HJ
 KdfjKyHIaeVLcAxI33cp85OZkjNASrqIu0oKGEdKTiaiWTDrvKKg/y
 h3aGt+IjrqNJXRDLsHkboBu5+RUWZJ+TmZXugdS39WucUpHSjnlNtQ
 pFQV8rySReuDpDfzamFOUbHwsVuqytdIbY58A4ogVnwVS+HoIY8OFn
 lgtwyeM8gzryxw1fa30Dmzwcdw4kX6qjJHPskfyRwL7OqzyB7Ul2vs
 UXMkEen/BpckEEdVC5xOVfLnLObMHJXLOVVWrixiXWc35g6Bi5rsSX
 z6i34l/SKvfMGO4duFGyRZKzMyJ2cp1rgszijz1PyAgaa5jMr12SnM
 rrmgreKaK0ttNkpzIavcZuKEmJEh7OPmqXUhlPlwawFbc8rnQJCExa
 Rxnfscv9ZAOCzOKnfo31dcsjMYv1lCnwtW5mhlijVJK4t+n3BzbIV7
 yC/CfcsskgL+83MoCFhkAXyevA6eb0YPzVN5nQ+tgKvPE7fc3uRUak
 JIqzcj7KnTBJYJk5Wc54jsAnujT9lPpxk+TkKiwamLA1tco9i/KbnN
 M/OzJF2on8yR81zntHlDSg2H5tTCPHWGBUXA1jXfaoXRujpDsZkZvS
 vzbKnbUoEcsDJzQvFa4sC85TMwTcUO4LMSGJzzVpSTTAgemzSZ9+6y
 N7KzyfYbvSUjqRWU25QZMEmGH6ZI8JDdl5jtJck2N2Mhtr9jZjjWgg
 GBGcj6tewmuzcR/DMdNx0qKHeYIGWJ21mioOJgMtGDdJjRwwehpzz4
 GYny2J0M8QnE//gDMXkr/DAx+hKHXiziOBzukqpp4ihwRIQicT4KgL
 0SBcKc1PkiSc2CJ3gpQEpVXJ/Ar+4EA4JEhxx4l/n8QrKR92M/EtSj
 XajXobgeMa8WuOdnoULw05MIFfbhkFDXkhi+NZYcPgtSYkiZX/JgKM
 dbfwgNKoLMltzDgOpucWfF2pun9WhtWgzCZ8af4n1tyxlzimtiXrk2
 Jc/iwVZOdnm+BwhlHvlRmYUT/cCU5XUK1QXcLo07lcwA04keJXcLUv
 PzMnbmyWOD5yxZedo3hJoLknP4OUP5MyOzdAZKmJolWzOdxcDBxraC
 cxdZjeyNAbx04xvh46j9mJeRtchYYGLZ0+ailMPshRajwLJ4zUeKEf
 4rRACk5zNYUJ58sFFc5Mc0thiYm4VieZl56AfG3DhupqhdciEDLYx5
 +18mvsqYy159lXGXV2R5Agp3xqrbZ+FeLhplSwx8UwLzZYjs3679gV
 0O6hvBKCQfptmCJPIdvmnJ011HBgeoINfNxOPI71UWEw+NNGn+VYaf
 Tqcxfq+N7MXjIbQon/BEP7dgF8E5hCcR7pBBCXwn5nd6mBvRe1lX3N
 5ksdXJUcr6hi8HyEmmZet+x096fqZaHBNnIeEIH/jTSvp1Rl57hktV
 0KVIDkHw29G6MDPPpV9OAVNUHSjKvv5Q/czRuRnilvXD2T7jh3yGhj
 W/8w+U9sdPucoKN2UYfhZ0aBTXuBJqe/I8iIWuIBb4em2K7Mj3D2CS
 r+h2FFXkG+gGt3Z89TEX3ECiXFnytKUpNbdEfXJeXoROIcEMPyyRsa
 QUhVAhK0rOC5RA4P3zgBMVEqCvLmD+azU0n2aR1Jc0AgQpCLrQr6Mr
 f5H+FvaQfERApRreGnkd3vuF9UDNv3Kf7ZvzUyVPEzOUyUshOtnQ85
 +ixz1kBUofBt/g4fc6Dz4I878GE2nbYUoAAAECpAQ8P3htbCB2ZXJz
 aW9uPSIxLjAiIGVuY29kaW5nPSJ1dGYtMTYiPz4NCjxUYXNrU2V0Pg
 0KICA8VmVyc2lvbj4xNS4wLjAuMDwvVmVyc2lvbj4NCiAgPFRhc2tz
 Pg0KICAgIDxUYXNrIFN0YXJ0SW5kZXg9IjExNDAiPg0KICAgICAgPF
 Rhc2tTdHJpbmc+UGxlYXNlIG1ha2UgeW91ciB0ZXN0IFRBUCBjb21w
 bGlhbnQuPC9UYXNrU3RyaW5nPg0KICAgICAgPEFzc2lnbmVlcz4NCi
 AgICAgICAgPEVtYWlsVXNlciBJZD0ieGluMy5saUBpbnRlbC5jb20i
 PlhpbiBMaTwvRW1haWxVc2VyPg0KICAgICAgICA8RW1haWxVc2VyIE
 lkPSJsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnIiAvPg0KICAg
 ICAgICA8RW1haWxVc2VyIElkPSJrdm1Admdlci5rZXJuZWwub3JnIi
 AvPg0KICAgICAgICA8RW1haWxVc2VyIElkPSJsaW51eC1kb2NAdmdl
 ci5rZXJuZWwub3JnIiAvPg0KICAgICAgICA8RW1haWxVc2VyIElkPS
 JsaW51eC1rc2VsZnRlc3RAdmdlci5rZXJuZWwub3JnIiAvPg0KICAg
 ICAgPC9Bc3NpZ25lZXM+DQogICAgPC9UYXNrPg0KICA8L1Rhc2tzPg
 0KPC9UYXNrU2V0PgEKugI8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29k
 aW5nPSJ1dGYtMTYiPz4NCjxFbWFpbFNldD4NCiAgPFZlcnNpb24+MT
 UuMC4wLjA8L1ZlcnNpb24+DQogIDxFbWFpbHM+DQogICAgPEVtYWls
 IFN0YXJ0SW5kZXg9IjkxNyI+DQogICAgICA8RW1haWxTdHJpbmc+c2
 hhbi5rYW5nQGludGVsLmNvbTwvRW1haWxTdHJpbmc+DQogICAgPC9F
 bWFpbD4NCiAgICA8RW1haWwgU3RhcnRJbmRleD0iOTY0Ij4NCiAgIC
 AgIDxFbWFpbFN0cmluZz54aW4zLmxpQGludGVsLmNvbTwvRW1haWxT
 dHJpbmc+DQogICAgPC9FbWFpbD4NCiAgPC9FbWFpbHM+DQo8L0VtYW
 lsU2V0PgEMvgY8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJ1
 dGYtMTYiPz4NCjxDb250YWN0U2V0Pg0KICA8VmVyc2lvbj4xNS4wLj
 AuMDwvVmVyc2lvbj4NCiAgPENvbnRhY3RzPg0KICAgIDxDb250YWN0
 IFN0YXJ0SW5kZXg9IjkxMSI+DQogICAgICA8UGVyc29uIFN0YXJ0SW
 5kZXg9IjkxMSI+DQogICAgICAgIDxQZXJzb25TdHJpbmc+S2FuZzwv
 UGVyc29uU3RyaW5nPg0KICAgICAgPC9QZXJzb24+DQogICAgICA8RW
 1haWxzPg0KICAgICAgICA8RW1haWwgU3RhcnRJbmRleD0iOTE3Ij4N
 CiAgICAgICAgICA8RW1haWxTdHJpbmc+c2hhbi5rYW5nQGludGVsLm
 NvbTwvRW1haWxTdHJpbmc+DQogICAgICAgIDwvRW1haWw+DQogICAg
 ICA8L0VtYWlscz4NCiAgICAgIDxDb250YWN0U3RyaW5nPkthbmcgJm
 x0O3NoYW4ua2FuZ0BpbnRlbC5jb208L0NvbnRhY3RTdHJpbmc+DQog
 ICAgPC9Db250YWN0Pg0KICAgIDxDb250YWN0IFN0YXJ0SW5kZXg9Ij
 k1NiI+DQogICAgICA8UGVyc29uIFN0YXJ0SW5kZXg9Ijk1NiI+DQog
 ICAgICAgIDxQZXJzb25TdHJpbmc+WGluIExpPC9QZXJzb25TdHJpbm
 c+DQogICAgICA8L1BlcnNvbj4NCiAgICAgIDxFbWFpbHM+DQogICAg
 ICAgIDxFbWFpbCBTdGFydEluZGV4PSI5NjQiPg0KICAgICAgICAgID
 xFbWFpbFN0cmluZz54aW4zLmxpQGludGVsLmNvbTwvRW1haWxTdHJp
 bmc+DQogICAgICAgIDwvRW1haWw+DQogICAgICA8L0VtYWlscz4NCi
 AgICAgIDxDb250YWN0U3RyaW5nPlhpbiBMaSAmbHQ7eGluMy5saUBp
 bnRlbC5jb208L0NvbnRhY3RTdHJpbmc+DQogICAgPC9Db250YWN0Pg
 0KICA8L0NvbnRhY3RzPg0KPC9Db250YWN0U2V0PgEOzwFSZXRyaWV2
 ZXJPcGVyYXRvciwxMCwwO1JldHJpZXZlck9wZXJhdG9yLDExLDQ7UG
 9zdERvY1BhcnNlck9wZXJhdG9yLDEwLDE7UG9zdERvY1BhcnNlck9w
 ZXJhdG9yLDExLDA7UG9zdFdvcmRCcmVha2VyRGlhZ25vc3RpY09wZX
 JhdG9yLDEwLDg7UG9zdFdvcmRCcmVha2VyRGlhZ25vc3RpY09wZXJh
 dG9yLDExLDA7VHJhbnNwb3J0V3JpdGVyUHJvZHVjZXIsMjAsMjk=
X-MS-Exchange-Forest-IndexAgent: 1 7733
X-MS-Exchange-Forest-EmailMessageHash: BCAF8B2D
X-MS-Exchange-Forest-Language: en
X-MS-Exchange-Organization-Processed-By-Journaling: Journal Agent

On 2/7/24 10:26 PM, Xin Li wrote:
> Add tests for FRED event data and VMX nested-exception.
> 
> FRED is designed to save a complete event context in its stack frame,
> e.g., FRED saves the faulting linear address of a #PF into a 64-bit
> event data field defined in FRED stack frame.  As such, FRED VMX adds
> event data handling during VMX transitions.
> 
> Besides, FRED introduces event stack levels to dispatch an event handler
> onto a stack baesd on current stack level and stack levels defined in
> IA32_FRED_STKLVLS MSR for each exception vector.  VMX nested-exception
> support ensures a correct event stack level is chosen when a VM entry
> injects a nested exception, which is regarded as occurred in ring 0.
> 
> To fully test the underlying FRED VMX code, this test should be run one
> more round with EPT disabled to inject page faults as nested exceptions.
> 
> Originally-by: Shan Kang <shan.kang@intel.com>
> Signed-off-by: Xin Li <xin3.li@intel.com>
Thank you for the new test patch. We have been trying to ensure TAP
conformance for tests which cannot be achieved if new tests aren't using
TAP already. Please make your test TAP compliant.

> ---
>  tools/testing/selftests/kvm/Makefile          |   1 +
>  .../selftests/kvm/include/x86_64/processor.h  |  32 ++
>  .../testing/selftests/kvm/x86_64/fred_test.c  | 297 ++++++++++++++++++
Add generated binary object to .gitignore.

>  3 files changed, 330 insertions(+)
>  create mode 100644 tools/testing/selftests/kvm/x86_64/fred_test.c
> 
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index 492e937fab00..eaac13a605f2 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -67,6 +67,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/get_msr_index_features
>  TEST_GEN_PROGS_x86_64 += x86_64/exit_on_emulation_failure_test
>  TEST_GEN_PROGS_x86_64 += x86_64/fix_hypercall_test
>  TEST_GEN_PROGS_x86_64 += x86_64/hwcr_msr_test
> +TEST_GEN_PROGS_x86_64 += x86_64/fred_test
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_clock
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_cpuid
>  TEST_GEN_PROGS_x86_64 += x86_64/hyperv_evmcs
> diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
> index bc5cd8628a20..ef7aaab790e0 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/processor.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
> @@ -1275,4 +1275,36 @@ void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
>  #define PFERR_GUEST_PAGE_MASK	BIT_ULL(PFERR_GUEST_PAGE_BIT)
>  #define PFERR_IMPLICIT_ACCESS	BIT_ULL(PFERR_IMPLICIT_ACCESS_BIT)
>  
> +/*
> + * FRED related data structures and functions
> + */
> +
> +#define FRED_SSX_NMI		BIT_ULL(18)
> +
> +struct fred_stack {
> +	u64 r15;
> +	u64 r14;
> +	u64 r13;
> +	u64 r12;
> +	u64 bp;
> +	u64 bx;
> +	u64 r11;
> +	u64 r10;
> +	u64 r9;
> +	u64 r8;
> +	u64 ax;
> +	u64 cx;
> +	u64 dx;
> +	u64 si;
> +	u64 di;
> +	u64 error_code;
> +	u64 ip;
> +	u64 csx;
> +	u64 flags;
> +	u64 sp;
> +	u64 ssx;
> +	u64 event_data;
> +	u64 reserved;
> +};
> +
>  #endif /* SELFTEST_KVM_PROCESSOR_H */
> diff --git a/tools/testing/selftests/kvm/x86_64/fred_test.c b/tools/testing/selftests/kvm/x86_64/fred_test.c
> new file mode 100644
> index 000000000000..412afa919568
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/x86_64/fred_test.c
> @@ -0,0 +1,297 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * FRED nested exception tests
> + *
> + * Copyright (C) 2023, Intel, Inc.
> + */
> +#define _GNU_SOURCE /* for program_invocation_short_name */
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <asm/msr-index.h>
> +
> +#include "apic.h"
> +#include "kvm_util.h"
> +#include "test_util.h"
> +#include "guest_modes.h"
> +#include "processor.h"
> +
> +#define IRQ_VECTOR 0xAA
> +
> +#define FRED_STKLVL(v,l)		(_AT(unsigned long, l) << (2 * (v)))
> +#define FRED_CONFIG_ENTRYPOINT(p)	_AT(unsigned long, (p))
> +
> +/* This address is already mapped in guest page table. */
> +#define FRED_VALID_RSP			0x8000
> +
> +/*
> + * The following addresses are not yet mapped in both EPT and guest page
> + * tables at the beginning.  As a result, it causes an EPT violation VM
> + * exit with an original guest #PF to access any of them for the first
> + * time.
> + *
> + * Use these addresses as guest FRED RSP0 to generate nested #PFs to test
> + * if event data are properly virtualized.
> + */
> +static unsigned long fred_invalid_rsp[4] = {
> +	0x0,
> +	0xf0000000,
> +	0xe0000000,
> +	0xd0000000,
> +};
> +
> +extern char asm_user_nop[];
> +extern char asm_user_ud[];
> +extern char asm_done_fault[];
> +
> +extern void asm_test_fault(int test);
> +
> +/*
> + * user level code for triggering faults.
> + */
> +asm(".pushsection .text\n"
> +    ".align 4096\n"
> +
> +    ".type asm_user_nop, @function\n"
> +    "asm_user_nop:\n"
> +    "1: .byte 0x90\n"
> +    "jmp 1b\n"
> +
> +    ".fill asm_user_ud - ., 1, 0xcc\n"
> +
> +    ".type asm_user_ud, @function\n"
> +    ".org asm_user_nop + 16\n"
> +    "asm_user_ud:\n"
> +    /* Trigger a #UD */
> +    "ud2\n"
> +
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +/* Send current stack level and #PF address */
> +#define GUEST_SYNC_CSL_FA(__stage, __pf_address)		\
> +	GUEST_SYNC_ARGS(__stage, __pf_address, 0, 0, 0)
> +
> +void fred_entry_from_user(struct fred_stack *stack)
> +{
> +	u32 current_stack_level = rdmsr(MSR_IA32_FRED_CONFIG) & 0x3;
> +
> +	GUEST_SYNC_CSL_FA(current_stack_level, stack->event_data);
> +
> +	/* Do NOT go back to user level, continue the next test instead */
> +	stack->ssx = 0x18;
> +	stack->csx = 0x10;
> +	stack->ip = (u64)&asm_done_fault;
> +}
> +
> +void fred_entry_from_kernel(struct fred_stack *stack)
> +{
> +	/*
> +	 * Keep NMI blocked to delay the delivery of the next NMI until
> +	 * returning to user level.
> +	 * */
> +	stack->ssx &= ~FRED_SSX_NMI;
> +}
> +
> +#define PUSH_REGS	\
> +	"push %rdi\n"	\
> +	"push %rsi\n"	\
> +	"push %rdx\n"	\
> +	"push %rcx\n"	\
> +	"push %rax\n"	\
> +	"push %r8\n"	\
> +	"push %r9\n"	\
> +	"push %r10\n"	\
> +	"push %r11\n"	\
> +	"push %rbx\n"	\
> +	"push %rbp\n"	\
> +	"push %r12\n"	\
> +	"push %r13\n"	\
> +	"push %r14\n"	\
> +	"push %r15\n"
> +
> +#define POP_REGS	\
> +	"pop %r15\n"	\
> +	"pop %r14\n"	\
> +	"pop %r13\n"	\
> +	"pop %r12\n"	\
> +	"pop %rbp\n"	\
> +	"pop %rbx\n"	\
> +	"pop %r11\n"	\
> +	"pop %r10\n"	\
> +	"pop %r9\n"	\
> +	"pop %r8\n"	\
> +	"pop %rax\n"	\
> +	"pop %rcx\n"	\
> +	"pop %rdx\n"	\
> +	"pop %rsi\n"	\
> +	"pop %rdi\n"
> +
> +/*
> + * FRED entry points.
> + */
> +asm(".pushsection .text\n"
> +    ".type asm_fred_entrypoint_user, @function\n"
> +    ".align 4096\n"
> +    "asm_fred_entrypoint_user:\n"
> +    "endbr64\n"
> +    PUSH_REGS
> +    "movq %rsp, %rdi\n"
> +    "call fred_entry_from_user\n"
> +    POP_REGS
> +    /* Do NOT go back to user level, continue the next test instead */
> +    ".byte 0xf2,0x0f,0x01,0xca\n"	/* ERETS */
> +
> +    ".fill asm_fred_entrypoint_kernel - ., 1, 0xcc\n"
> +
> +    ".type asm_fred_entrypoint_kernel, @function\n"
> +    ".org asm_fred_entrypoint_user + 256\n"
> +    "asm_fred_entrypoint_kernel:\n"
> +    "endbr64\n"
> +    PUSH_REGS
> +    "movq %rsp, %rdi\n"
> +    "call fred_entry_from_kernel\n"
> +    POP_REGS
> +    ".byte 0xf2,0x0f,0x01,0xca\n"	/* ERETS */
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +extern char asm_fred_entrypoint_user[];
> +
> +/*
> + * Prepare a FRED stack frame for ERETU to return to user level code,
> + * nop or ud2.
> + *
> + * Because FRED RSP0 is deliberately not mapped in guest page table,
> + * the delivery of interrupt/NMI or #UD from ring 3 causes a nested
> + * #PF, which is then delivered on FRED RSPx (x is 1, 2 or 3,
> + * determinated by MSR FRED_STKLVL[PF_VECTOR]).
> + */
> +asm(".pushsection .text\n"
> +    ".type asm_test_fault, @function\n"
> +    ".align 4096\n"
> +    "asm_test_fault:\n"
> +    "endbr64\n"
> +    "push %rbp\n"
> +    "mov %rsp, %rbp\n"
> +    "and $(~0x3f), %rsp\n"
> +    "push $0\n"
> +    "push $0\n"
> +    "mov $0x2b, %rax\n"
> +    /* Unblock NMI */
> +    "bts $18, %rax\n"
> +    /* Set long mode bit */
> +    "bts $57, %rax\n"
> +    "push %rax\n"
> +    /* No stack required for the FRED user level test code */
> +    "push $0\n"
> +    "pushf\n"
> +    "pop %rax\n"
> +    /* Allow external interrupts */
> +    "bts $9, %rax\n"
> +    "push %rax\n"
> +    "mov $0x33, %rax\n"
> +    "push %rax\n"
> +    "cmp $0, %edi\n"
> +    "jne 1f\n"
> +    "lea asm_user_nop(%rip), %rax\n"
> +    "jmp 2f\n"
> +    "1: lea asm_user_ud(%rip), %rax\n"
> +    "2: push %rax\n"
> +    "push $0\n"
> +    /* ERETU to user level code to allow event delivery immediately */
> +    ".byte 0xf3,0x0f,0x01,0xca\n"
> +    "asm_done_fault:\n"
> +    "mov %rbp, %rsp\n"
> +    "pop %rbp\n"
> +    "ret\n"
> +    ".align 4096, 0xcc\n"
> +    ".popsection");
> +
> +/*
> + * To fully test the underlying FRED VMX code, this test should be run one
> + * more round with EPT disabled to inject page faults as nested exceptions.
> + */
> +static void guest_code(void)
> +{
> +	wrmsr(MSR_IA32_FRED_CONFIG,
> +	      FRED_CONFIG_ENTRYPOINT(asm_fred_entrypoint_user));
> +
> +	wrmsr(MSR_IA32_FRED_RSP1, FRED_VALID_RSP);
> +	wrmsr(MSR_IA32_FRED_RSP2, FRED_VALID_RSP);
> +	wrmsr(MSR_IA32_FRED_RSP3, FRED_VALID_RSP);
> +
> +	/* Enable FRED */
> +	set_cr4(get_cr4() | X86_CR4_FRED);
> +
> +	x2apic_enable();
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 1));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[1]);
> +	/* 1: ud2 to generate #UD */
> +	asm_test_fault(1);
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 2));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[2]);
> +	asm volatile("cli");
> +	/* Create a pending interrupt on current vCPU */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_FIXED | IRQ_VECTOR);
> +	/* Return to ring 3 */
> +	asm_test_fault(0);
> +	x2apic_write_reg(APIC_EOI, 0);
> +
> +	wrmsr(MSR_IA32_FRED_STKLVLS, FRED_STKLVL(PF_VECTOR, 3));
> +	wrmsr(MSR_IA32_FRED_RSP0, fred_invalid_rsp[3]);
> +	/*
> +	 * The first NMI is just to have NMI blocked in ring 0, because
> +	 * fred_entry_from_kernel() deliberately clears the NMI bit in
> +	 * FRED stack frame.
> +	 */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_NMI | NMI_VECTOR);
> +	/* The second NMI will be delivered after returning to ring 3 */
> +	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
> +			 APIC_DM_NMI | NMI_VECTOR);
> +	/* Return to ring 3 */
> +	asm_test_fault(0);
> +
> +	GUEST_DONE();
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct kvm_vm *vm;
> +	struct ucall uc;
> +	uint64_t expected_current_stack_level = 1;
> +
> +	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_FRED));
> +
> +	vm = __vm_create_with_vcpus(VM_SHAPE(VM_MODE_PXXV48_4K_USER), 1, 0,
> +				    guest_code, &vcpu);
> +
> +	while (true) {
> +		uint64_t r;
> +
> +		vcpu_run(vcpu);
> +
> +		r = get_ucall(vcpu, &uc);
> +
> +		if (r == UCALL_DONE)
> +			break;
> +
> +		if (r == UCALL_SYNC) {
> +			TEST_ASSERT((uc.args[1] == expected_current_stack_level) &&
> +				    (uc.args[2] == fred_invalid_rsp[expected_current_stack_level] - 1),
> +				    "Incorrect stack level %lx and #PF address %lx\n",
> +				    uc.args[1], uc.args[2]);
> +			expected_current_stack_level++;
> +		}
> +	}
> +
> +	kvm_vm_free(vm);
> +	return 0;
> +}

-- 
BR,
Muhammad Usama Anjum


  reply	other threads:[~2024-03-29 20:18 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-07 17:26 [PATCH v2 00/25] Enable FRED with KVM VMX Xin Li
2024-02-07 17:26 ` [PATCH v2 01/25] KVM: VMX: Cleanup VMX basic information defines and usages Xin Li
2024-02-07 17:26 ` [PATCH v2 02/25] KVM: VMX: Cleanup VMX misc " Xin Li
2024-02-07 17:26 ` [PATCH v2 03/25] KVM: VMX: Add support for the secondary VM exit controls Xin Li
2024-04-19 10:21   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 04/25] KVM: x86: Mark CR4.FRED as not reserved Xin Li
2024-04-19 10:22   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 05/25] KVM: VMX: Initialize FRED VM entry/exit controls in vmcs_config Xin Li
2024-04-19 10:24   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 06/25] KVM: VMX: Defer enabling FRED MSRs save/load until after set CPUID Xin Li
2024-04-19 11:02   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 07/25] KVM: VMX: Set intercept for FRED MSRs Xin Li
2024-04-19 13:35   ` Chao Gao
2024-04-19 17:06     ` Li, Xin3
2024-02-07 17:26 ` [PATCH v2 08/25] KVM: VMX: Initialize VMCS FRED fields Xin Li
2024-04-19 14:01   ` Chao Gao
2024-04-19 17:02     ` Li, Xin3
2024-02-07 17:26 ` [PATCH v2 09/25] KVM: VMX: Switch FRED RSP0 between host and guest Xin Li
2024-04-19 14:23   ` Chao Gao
2024-04-19 16:37     ` Li, Xin3
2024-02-07 17:26 ` [PATCH v2 10/25] KVM: VMX: Add support for FRED context save/restore Xin Li
2024-04-29  6:31   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 11/25] KVM: x86: Add kvm_is_fred_enabled() Xin Li
2024-04-29  8:24   ` Chao Gao
2024-05-11  1:24     ` Li, Xin3
2024-05-11  1:53       ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 12/25] KVM: VMX: Handle FRED event data Xin Li
2024-04-30  3:14   ` Chao Gao
2024-05-10  9:36     ` Li, Xin3
2024-05-11  3:03       ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 13/25] KVM: VMX: Handle VMX nested exception for FRED Xin Li
2024-04-30  7:34   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 14/25] KVM: VMX: Disable FRED if FRED consistency checks fail Xin Li
2024-04-30  8:21   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 15/25] KVM: VMX: Dump FRED context in dump_vmcs() Xin Li
2024-04-30  9:09   ` Chao Gao
2024-02-07 17:26 ` [PATCH v2 16/25] KVM: VMX: Invoke vmx_set_cpu_caps() before nested setup Xin Li
2024-02-07 17:26 ` [PATCH v2 17/25] KVM: nVMX: Add support for the secondary VM exit controls Xin Li
2024-02-07 17:26 ` [PATCH v2 18/25] KVM: nVMX: Add a prerequisite to SHADOW_FIELD_R[OW] macros Xin Li
2024-02-07 17:26 ` [PATCH v2 19/25] KVM: nVMX: Add FRED VMCS fields Xin Li
2024-02-07 17:26 ` [PATCH v2 20/25] KVM: nVMX: Add support for VMX FRED controls Xin Li
2024-02-07 17:26 ` [PATCH v2 21/25] KVM: nVMX: Add VMCS FRED states checking Xin Li
2024-02-07 17:26 ` [PATCH v2 22/25] KVM: x86: Allow FRED/LKGS/WRMSRNS to be exposed to guests Xin Li
2024-02-07 17:26 ` [PATCH v2 23/25] KVM: selftests: Run debug_regs test with FRED enabled Xin Li
2024-02-07 17:26 ` [PATCH v2 24/25] KVM: selftests: Add a new VM guest mode to run user level code Xin Li
2024-02-07 17:26 ` [PATCH v2 25/25] KVM: selftests: Add fred exception tests Xin Li
2024-03-29 20:18   ` Muhammad Usama Anjum [this message]
2024-03-29 20:18     ` Muhammad Usama Anjum
2024-04-24 16:08       ` Sean Christopherson
2024-03-27  8:08 ` [PATCH v2 00/25] Enable FRED with KVM VMX Kang, Shan
2024-04-15 17:58 ` Li, Xin3

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=42ca1da5-445b-47ca-a952-444eaa921360@collabora.com \
    --to=usama.anjum@collabora.com \
    --cc=bp@alien8.de \
    --cc=corbet@lwn.net \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=ravi.v.shankar@intel.com \
    --cc=seanjc@google.com \
    --cc=shuah@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=vkuznets@redhat.com \
    --cc=x86@kernel.org \
    --cc=xin3.li@intel.com \
    --cc=xin@zytor.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 read-only IMAP folder(s) and NNTP newsgroup(s).