Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  sync_regs_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Test for s390x KVM_CAP_SYNC_REGS
 *
 * Based on the same test for x86:
 * Copyright (C) 2018, Google LLC.
 *
 * Adaptions for s390x:
 * Copyright (C) 2019, Red Hat, Inc.
 *
 * Test expected behavior of the KVM_CAP_SYNC_REGS functionality.
 */

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

#include "test_util.h"
#include "kvm_util.h"
#include "diag318_test_handler.h"
#include "kselftest.h"

static void guest_code(void)
{
 /*
 * We embed diag 501 here instead of doing a ucall to avoid that
 * the compiler has messed with r11 at the time of the ucall.
 */

 asm volatile (
  "0: diag 0,0,0x501\n"
  " ahi 11,1\n"
  " j 0b\n"
 );
}

#define REG_COMPARE(reg) \
 TEST_ASSERT(left->reg == right->reg, \
      "Register " #reg \
      " values did not match: 0x%llx, 0x%llx", \
      left->reg, right->reg)

#define REG_COMPARE32(reg) \
 TEST_ASSERT(left->reg == right->reg, \
      "Register " #reg \
      " values did not match: 0x%x, 0x%x", \
      left->reg, right->reg)


static void compare_regs(struct kvm_regs *left, struct kvm_sync_regs *right)
{
 int i;

 for (i = 0; i < 16; i++)
  REG_COMPARE(gprs[i]);
}

static void compare_sregs(struct kvm_sregs *left, struct kvm_sync_regs *right)
{
 int i;

 for (i = 0; i < 16; i++)
  REG_COMPARE32(acrs[i]);

 for (i = 0; i < 16; i++)
  REG_COMPARE(crs[i]);
}

#undef REG_COMPARE

#define TEST_SYNC_FIELDS   (KVM_SYNC_GPRS|KVM_SYNC_ACRS|KVM_SYNC_CRS|KVM_SYNC_DIAG318)
#define INVALID_SYNC_FIELD 0x80000000

void test_read_invalid(struct kvm_vcpu *vcpu)
{
 struct kvm_run *run = vcpu->run;
 int rv;

 /* Request reading invalid register set from VCPU. */
 run->kvm_valid_regs = INVALID_SYNC_FIELD;
 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv < 0 && errno == EINVAL,
      "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
      rv);
 run->kvm_valid_regs = 0;

 run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv < 0 && errno == EINVAL,
      "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
      rv);
 run->kvm_valid_regs = 0;
}

void test_set_invalid(struct kvm_vcpu *vcpu)
{
 struct kvm_run *run = vcpu->run;
 int rv;

 /* Request setting invalid register set into VCPU. */
 run->kvm_dirty_regs = INVALID_SYNC_FIELD;
 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv < 0 && errno == EINVAL,
      "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
      rv);
 run->kvm_dirty_regs = 0;

 run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv < 0 && errno == EINVAL,
      "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
      rv);
 run->kvm_dirty_regs = 0;
}

void test_req_and_verify_all_valid_regs(struct kvm_vcpu *vcpu)
{
 struct kvm_run *run = vcpu->run;
 struct kvm_sregs sregs;
 struct kvm_regs regs;
 int rv;

 /* Request and verify all valid register sets. */
 run->kvm_valid_regs = TEST_SYNC_FIELDS;
 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 TEST_ASSERT(run->s390_sieic.icptcode == 4 &&
      (run->s390_sieic.ipa >> 8) == 0x83 &&
      (run->s390_sieic.ipb >> 16) == 0x501,
      "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x",
      run->s390_sieic.icptcode, run->s390_sieic.ipa,
      run->s390_sieic.ipb);

 vcpu_regs_get(vcpu, ®s);
 compare_regs(®s, &run->s.regs);

 vcpu_sregs_get(vcpu, &sregs);
 compare_sregs(&sregs, &run->s.regs);
}

void test_set_and_verify_various_reg_values(struct kvm_vcpu *vcpu)
{
 struct kvm_run *run = vcpu->run;
 struct kvm_sregs sregs;
 struct kvm_regs regs;
 int rv;

 /* Set and verify various register values */
 run->s.regs.gprs[11] = 0xBAD1DEA;
 run->s.regs.acrs[0] = 1 << 11;

 run->kvm_valid_regs = TEST_SYNC_FIELDS;
 run->kvm_dirty_regs = KVM_SYNC_GPRS | KVM_SYNC_ACRS;

 if (get_diag318_info() > 0) {
  run->s.regs.diag318 = get_diag318_info();
  run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
 }

 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1,
      "r11 sync regs value incorrect 0x%llx.",
      run->s.regs.gprs[11]);
 TEST_ASSERT(run->s.regs.acrs[0]  == 1 << 11,
      "acr0 sync regs value incorrect 0x%x.",
      run->s.regs.acrs[0]);
 TEST_ASSERT(run->s.regs.diag318 == get_diag318_info(),
      "diag318 sync regs value incorrect 0x%llx.",
      run->s.regs.diag318);

 vcpu_regs_get(vcpu, ®s);
 compare_regs(®s, &run->s.regs);

 vcpu_sregs_get(vcpu, &sregs);
 compare_sregs(&sregs, &run->s.regs);
}

void test_clear_kvm_dirty_regs_bits(struct kvm_vcpu *vcpu)
{
 struct kvm_run *run = vcpu->run;
 int rv;

 /* Clear kvm_dirty_regs bits, verify new s.regs values are
 * overwritten with existing guest values.
 */

 run->kvm_valid_regs = TEST_SYNC_FIELDS;
 run->kvm_dirty_regs = 0;
 run->s.regs.gprs[11] = 0xDEADBEEF;
 run->s.regs.diag318 = 0x4B1D;
 rv = _vcpu_run(vcpu);
 TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF,
      "r11 sync regs value incorrect 0x%llx.",
      run->s.regs.gprs[11]);
 TEST_ASSERT(run->s.regs.diag318 != 0x4B1D,
      "diag318 sync regs value incorrect 0x%llx.",
      run->s.regs.diag318);
}

struct testdef {
 const char *name;
 void (*test)(struct kvm_vcpu *vcpu);
} testlist[] = {
 { "read invalid", test_read_invalid },
 { "set invalid", test_set_invalid },
 { "request+verify all valid regs", test_req_and_verify_all_valid_regs },
 { "set+verify various regs", test_set_and_verify_various_reg_values },
 { "clear kvm_dirty_regs bits", test_clear_kvm_dirty_regs_bits },
};

int main(int argc, char *argv[])
{
 struct kvm_vcpu *vcpu;
 struct kvm_vm *vm;
 int idx;

 TEST_REQUIRE(kvm_has_cap(KVM_CAP_SYNC_REGS));

 ksft_print_header();

 ksft_set_plan(ARRAY_SIZE(testlist));

 /* Create VM */
 vm = vm_create_with_one_vcpu(&vcpu, guest_code);

 for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) {
  testlist[idx].test(vcpu);
  ksft_test_result_pass("%s\n", testlist[idx].name);
 }

 kvm_vm_free(vm);

 ksft_finished(); /* Print results and exit() accordingly */
}

Messung V0.5
C=99 H=95 G=96

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge