All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aaron Brown <aaronmbr@linux.ibm.com>
To: Janosch Frank <frankja@linux.ibm.com>, kvm@vger.kernel.org
Cc: Claudio Imbrenda <imbrenda@linux.ibm.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	linux-s390@vger.kernel.org, linux-kselftest@vger.kernel.org,
	Nitya Khamar <nkhamar@linux.ibm.com>
Subject: Re: [PATCH 1/6] KVM: s390: selftests: Add kvm_exit test for instruction intercepts
Date: Fri, 13 Nov 2026 02:35:28 -0500	[thread overview]
Message-ID: <6df96ce4-7065-4c2c-b3d0-1874bedefdd1@linux.ibm.com> (raw)
In-Reply-To: <90cf2229-af79-4f08-b001-753dc7a86aa2@linux.ibm.com>

On 11/12/26 8:45 AM, Janosch Frank wrote:
> On 11/10/26 12:16 PM, Aaron M. Brown wrote:
[...]
>> +++ b/tools/testing/selftests/kvm/include/s390/kvm_lifecycle.h
>> @@ -0,0 +1,35 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Definition of structs for KVM lifecycle tests.
>> + *
>> + * Copyright IBM Corp. 2026
>> + *
>> + * Authors:
>> + *  Nitya Khamar (nkhamar@linux.ibm.com)
>> + *  Aaron Malik Brown (aaronmbr@linux.ibm.com)
>> + */
>> +#ifndef SELFTEST_KVM_LIFECYCLE_H
>> +#define SELFTEST_KVM_LIFECYCLE_H
>> +
>> +#include "kvm_util.h"
>> +#include <stdbool.h>
>> +
>> +struct kvm_lifecycle_testdef {
>> +    const char *name;
>> +    bool (*test)(void);
>> +};
>> +
>> +struct kvm_parameters {
>> +    struct kvm_vm *vm;
>> +    struct kvm_vcpu *vcpu;
>> +    void *guest_code;
>> +    struct kvm_run *run;
>> +    unsigned int interrupt_type;
>> +    struct kvm_s390_irq *irq;
>> +    struct kvm_s390_irq_state *irq_state;
>> +    struct {
>> +        bool immediate_exit_condition;
>> +    } manual_parameters;
>> +};
> 
> In this patch I don't see any benefit in having this struct.
> I'm hoping there's some use for it in later patches.

Yeah I may have added it a bit prematurely, as most of these fields are 
only used by the ucontrol tests later in the series, so patch 1 doesn't 
need them. I'll drop the struct from this patch and use local variables
in the next version, thanks

[...]
>> +
>> +static struct kvm_parameters create_vm_kvm_exit(struct kvm_parameters 
>> parameters)
> 
> Why aren't we using a pointer to the argument?
> 
>> +{
>> +    parameters.vm = vm_create_with_one_vcpu(&parameters.vcpu,
>> +                        parameters.guest_code);
>> +    return parameters;
>> +}
>> +
>> +static void cleanup_kvm(struct kvm_parameters *parameters)
>> +{
>> +    kvm_vm_free(parameters->vm);
>> +}
> 
> These two function generate >= 4 lines for a single line of useful code.
> 

Good point, I'll remove these helpers as well and just call
vm_create_with_one_vcpu() and kvm_vm_free() directly
>> +
>> +static void compare_regs(struct kvm_regs *regs, struct kvm_sync_regs 
>> *sregs)
>> +{
>> +    int register_number;
>> +
>> +    for (register_number = 0; register_number < NUM_GPRS; 
>> register_number++)
>> +        TEST_ASSERT_EQ(regs->gprs[register_number], sregs- 
>> >gprs[register_number]);
>> +}
>> +
>> +static void guestcode_instruction_intercept(void)
>> +{
>> +    asm volatile("diag 0,0, 0x500\n" :::);
>> +    GUEST_DONE();
>> +}
>> +
>> +static bool test_instruction_intercept(void)
>> +{
>> +    struct kvm_parameters param = {
>> +        .guest_code = guestcode_instruction_intercept,
>> +        .interrupt_type = KVM_S390_INT_EXTERNAL_CALL,
>> +        .manual_parameters.immediate_exit_condition = false,
>> +    };
>> +    struct kvm_s390_irq_state irq_state = {};
>> +    struct kvm_s390_irq irq = {};
>> +    struct kvm_regs regs;
>> +    int interrupts;
>> +
>> +    ksft_print_msg("Testing Instruction Intercept Exit\n");
>> +    param = create_vm_kvm_exit(param);
>> +    vcpu_run(param.vcpu);
>> +    param.run = param.vcpu->run;
>> +    irq.type = param.interrupt_type;
>> +    irq.u.extcall.code = param.vcpu->id;
>> +    irq_state.len = sizeof(irq);
>> +    irq_state.buf = (unsigned long)&irq;
>> +    param.irq = &irq;
>> +    param.irq_state = &irq_state;
>> +    TEST_ASSERT_KVM_EXIT_REASON(param.vcpu, KVM_EXIT_S390_SIEIC);
>> +    TEST_ASSERT(param.run->s390_sieic.icptcode == ICPT_INST,
>> +            "Failed with Unexpected icptcode of 0x%x\n",
>> +            param.run->s390_sieic.icptcode);
>> +    interrupts = __vcpu_ioctl(param.vcpu, KVM_S390_SET_IRQ_STATE,
>> +                  param.irq_state);
> 
> Why are we doing two things at the same time?
> What does the IRQ code add to the test?

You're right, we should focus on only  testing the exit, moreover 
irq_injection has gotten its own test file now, ill drop this
in v2 >> +    TEST_ASSERT(interrupts >= 0, "Cannot Inject Interrupt 
(%d)", errno);
> 
> That should be a == 0, no?
> Documentations says "0 on success".
> 

Indeed, this can also go away in v2, lets keep it simple
>> +    irq_state.buf = (unsigned long)&irq;
>> +    irq_state.len = sizeof(irq);
>> +    interrupts = __vcpu_ioctl(param.vcpu, KVM_S390_GET_IRQ_STATE,
>> +                  &irq_state);
>> +    TEST_ASSERT(interrupts > 0,
>> +            "Expected pending interrupt after injection, got %d", 
>> interrupts);
> 
> Here it's fine since the rc returns the number of bytes KVM copied.
> But we could actually check for a number being at least len(irq_state)

Good point, I will note that for possibly extending the irq tests in the 
future! >> +    TEST_ASSERT_EQ(irq.type, KVM_S390_INT_EXTERNAL_CALL);
>> +    TEST_ASSERT_EQ(irq.u.extcall.code, param.vcpu->id);
>> +    vcpu_run(param.vcpu);
>> +    TEST_ASSERT_KVM_EXIT_REASON(param.vcpu, KVM_EXIT_S390_SIEIC);
>> +    TEST_ASSERT(param.run->s390_sieic.icptcode == ICPT_INST,
>> +            "Expected ICPT_INST from GUEST_DONE after inject, got 
>> 0x%x\n",
>> +            param.run->s390_sieic.icptcode);
>> +    vcpu_regs_get(param.vcpu, &regs);
>> +    compare_regs(&regs, &param.run->s.regs);
>> +    cleanup_kvm(&param);
>> +    return true;
>> +}
>> +
>> +static void guestcode_diagnose_hypercall(void)
>> +{
>> +    asm volatile("diag 0,0, 0x501\n" :::);
>> +}
>> +
>> +static bool test_diagnose_code(void)
>> +{
>> +    struct kvm_parameters param = {
>> +        .guest_code = guestcode_diagnose_hypercall,
>> +        .manual_parameters.immediate_exit_condition = false,
>> +    };
>> +    ksft_print_msg("Testing Diagnosis Hypercall Exit\n");
> 
> Instruction is called diagnose according to the POP.

I will update that accordingly, thanks !

>> +    param = create_vm_kvm_exit(param);
>> +    vcpu_run(param.vcpu);
>> +    param.run = param.vcpu->run;
>> +    TEST_ASSERT_KVM_EXIT_REASON(param.vcpu, KVM_EXIT_S390_SIEIC);
>> +    TEST_ASSERT(param.run->s390_sieic.icptcode == ICPT_INST,
>> +            "Failed with Unexpected Exit Reason of %u and icptcode of 
>> 0x%x\n",
>> +            param.run->exit_reason, param.run->s390_sieic.icptcode);
>> +    TEST_ASSERT(param.run->s390_sieic.ipa >> 8 == IPA_DIAG,
>> +            "Failed with Unexpected Opcode of %u\n",
>> +            param.run->s390_sieic.ipa >> 8);
>> +    TEST_ASSERT(param.run->s390_sieic.ipb >> 16 == DIAG_ASSEMBLY_CODE,
>> +            "Failed with Unexpected Diagnose Code of %u\n",
>> +            param.run->s390_sieic.ipb >> 16);
>> +    cleanup_kvm(&param);
>> +    return true;
>> +}
>> +
>> +static void guestcode_diagnose_conditional(void)
>> +{
>> +    asm volatile("lghi %%r3,0x3333\n"
>> +        "lghi %%r5, 0x555\n"
>> +        "lghi %%r6, 0x3333\n"
>> +        "cgrjne %%r6, %%r3, 1f\n"
>> +        "diag 0,0, 0x501\n"
>> +        "1:\n"
>> +        :
>> +        :
>> +        : "r3", "r5", "r6"
>> +    );
>> +    GUEST_DONE();
>> +}
>> +
>> +static bool test_diagnose_conditional_code(void)
>> +{
>> +    struct kvm_parameters param = {
>> +        .guest_code = guestcode_diagnose_conditional,
>> +        .manual_parameters.immediate_exit_condition = false,
>> +    };
>> +    struct kvm_regs regs;
>> +
>> +    ksft_print_msg("Testing Diagnosis Hypercall for Conditional Code 
>> Exit\n");
> 
> What is this testing?

It is only testing that r3-r6 survive the intercept, so I think I can 
merge it into the DIAG 0x501 test for v2 >> +    param = 
create_vm_kvm_exit(param);
>> +    vcpu_run(param.vcpu);
>> +    param.run = param.vcpu->run;
>> +    TEST_ASSERT_KVM_EXIT_REASON(param.vcpu, KVM_EXIT_S390_SIEIC);
>> +    TEST_ASSERT(param.run->s390_sieic.icptcode == ICPT_INST,
>> +            "Failed with Unexpected Exit Reason of %u and icptcode of 
>> 0x%x\n",
>> +            param.run->exit_reason, param.run->s390_sieic.icptcode);
>> +    TEST_ASSERT(param.run->s390_sieic.ipa >> 8 == IPA_DIAG,
>> +            "Failed with Unexpected Opcode of %u\n",
>> +            param.run->s390_sieic.ipa >> 8);
>> +    TEST_ASSERT(param.run->s390_sieic.ipb >> 16 == DIAG_ASSEMBLY_CODE,
> 
> Which diag assembly code?
> There's a huge number of them and this test already uses 2.
This is for the virtio notify hypercall (500) in particular, I will be 
more explicit with the variable names in v2 ! >> +            "Failed 
with Unexpected Diagnose Code of %u\n",
>> +            param.run->s390_sieic.ipb >> 16);
>> +    vcpu_regs_get(param.vcpu, &regs);
>> +    TEST_ASSERT_EQ(regs.gprs[3], 0x3333);
>> +    TEST_ASSERT_EQ(regs.gprs[5], 0x555);
>> +    TEST_ASSERT_EQ(regs.gprs[6], 0x3333);
>> +    cleanup_kvm(&param);
>> +    return true;
>> +}
>> +
>> +static void test(void)
>> +{
>> +    int i;
>> +    struct kvm_lifecycle_testdef testlist[] = {
>> +        {
>> +            .name = "Testing Instruction Intercepts",
>> +            .test = test_instruction_intercept,
>> +        },
>> +        {
>> +            .name = "Testing DIAG Code",
>> +            .test = test_diagnose_code,
>> +        },
>> +        {
>> +            .name = "Testing Conditional DIAG Code",
>> +            .test = test_diagnose_conditional_code,
>> +        },
>> +    };
>> +
>> +    ksft_print_header();
>> +    ksft_set_plan(ARRAY_SIZE(testlist));
>> +
>> +    for (i = 0; i < ARRAY_SIZE(testlist); i++) {
>> +        if (testlist[i].test())
>> +            ksft_test_result_pass("%s\n", testlist[i].name);
>> +        else
>> +            ksft_test_result_skip("%s\n", testlist[i].name);
>> +    }
>> +}
>> +
>> +int main(void)
>> +{
>> +    TEST_REQUIRE(kvm_has_cap(KVM_CAP_USER_MEMORY2));
>> +    TEST_REQUIRE(kvm_has_cap(KVM_CAP_SYNC_REGS));
>> +    test();
>> +    ksft_finished();
>> +}
> 
thanks for the constructive comments Janosch, I will get to updating this,

Aaron

  reply	other threads:[~2026-11-13  7:35 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 11:16 [PATCH 0/6] KVM: s390: selftests: Add selftests for KVM exits on s390x Aaron M. Brown
2026-11-10 11:16 ` [PATCH 1/6] KVM: s390: selftests: Add kvm_exit test for instruction intercepts Aaron M. Brown
2026-11-10 11:30   ` sashiko-bot
2026-11-12 13:45   ` Janosch Frank
2026-11-13  7:35     ` Aaron Brown [this message]
2026-11-10 11:16 ` [PATCH 2/6] KVM: s390: selftests: Add SIGP and program exception tests Aaron M. Brown
2026-11-10 11:24   ` sashiko-bot
2026-11-13 10:21   ` Janosch Frank
2026-11-10 11:16 ` [PATCH 3/6] KVM: s390: selftests: Add wait state and VM lifecycle tests Aaron M. Brown
2026-11-10 11:21   ` sashiko-bot
2026-11-13 10:37   ` Janosch Frank
2026-11-10 11:16 ` [PATCH 4/6] KVM: s390: selftests: Add ucontrol helpers and instruction tests Aaron M. Brown
2026-11-10 11:24   ` sashiko-bot
2026-11-13 10:47   ` Janosch Frank
2026-11-10 11:16 ` [PATCH 5/6] KVM: s390: selftests: Add ucontrol storage key and immediate exit tests Aaron M. Brown
2026-11-10 11:25   ` sashiko-bot
2026-11-10 11:16 ` [PATCH 6/6] KVM: s390: selftests: Add clock comparator interrupt test Aaron M. Brown
2026-11-10 11:23   ` sashiko-bot

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=6df96ce4-7065-4c2c-b3d0-1874bedefdd1@linux.ibm.com \
    --to=aaronmbr@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=frankja@linux.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=nkhamar@linux.ibm.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.