linux/tools/testing/selftests/kvm/s390x/resets.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Test for s390x CPU resets
   4 *
   5 * Copyright (C) 2020, IBM
   6 */
   7
   8#include <stdio.h>
   9#include <stdlib.h>
  10#include <string.h>
  11#include <sys/ioctl.h>
  12
  13#include "test_util.h"
  14#include "kvm_util.h"
  15
  16#define VCPU_ID 3
  17#define LOCAL_IRQS 32
  18
  19struct kvm_s390_irq buf[VCPU_ID + LOCAL_IRQS];
  20
  21struct kvm_vm *vm;
  22struct kvm_run *run;
  23struct kvm_sync_regs *sync_regs;
  24static uint8_t regs_null[512];
  25
  26static void guest_code_initial(void)
  27{
  28        /* set several CRs to "safe" value */
  29        unsigned long cr2_59 = 0x10;    /* enable guarded storage */
  30        unsigned long cr8_63 = 0x1;     /* monitor mask = 1 */
  31        unsigned long cr10 = 1;         /* PER START */
  32        unsigned long cr11 = -1;        /* PER END */
  33
  34
  35        /* Dirty registers */
  36        asm volatile (
  37                "       lghi    2,0x11\n"       /* Round toward 0 */
  38                "       sfpc    2\n"            /* set fpc to !=0 */
  39                "       lctlg   2,2,%0\n"
  40                "       lctlg   8,8,%1\n"
  41                "       lctlg   10,10,%2\n"
  42                "       lctlg   11,11,%3\n"
  43                /* now clobber some general purpose regs */
  44                "       llihh   0,0xffff\n"
  45                "       llihl   1,0x5555\n"
  46                "       llilh   2,0xaaaa\n"
  47                "       llill   3,0x0000\n"
  48                /* now clobber a floating point reg */
  49                "       lghi    4,0x1\n"
  50                "       cdgbr   0,4\n"
  51                /* now clobber an access reg */
  52                "       sar     9,4\n"
  53                /* We embed diag 501 here to control register content */
  54                "       diag 0,0,0x501\n"
  55                :
  56                : "m" (cr2_59), "m" (cr8_63), "m" (cr10), "m" (cr11)
  57                /* no clobber list as this should not return */
  58                );
  59}
  60
  61static void test_one_reg(uint64_t id, uint64_t value)
  62{
  63        struct kvm_one_reg reg;
  64        uint64_t eval_reg;
  65
  66        reg.addr = (uintptr_t)&eval_reg;
  67        reg.id = id;
  68        vcpu_get_reg(vm, VCPU_ID, &reg);
  69        TEST_ASSERT(eval_reg == value, "value == 0x%lx", value);
  70}
  71
  72static void assert_noirq(void)
  73{
  74        struct kvm_s390_irq_state irq_state;
  75        int irqs;
  76
  77        irq_state.len = sizeof(buf);
  78        irq_state.buf = (unsigned long)buf;
  79        irqs = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_GET_IRQ_STATE, &irq_state);
  80        /*
  81         * irqs contains the number of retrieved interrupts. Any interrupt
  82         * (notably, the emergency call interrupt we have injected) should
  83         * be cleared by the resets, so this should be 0.
  84         */
  85        TEST_ASSERT(irqs >= 0, "Could not fetch IRQs: errno %d\n", errno);
  86        TEST_ASSERT(!irqs, "IRQ pending");
  87}
  88
  89static void assert_clear(void)
  90{
  91        struct kvm_sregs sregs;
  92        struct kvm_regs regs;
  93        struct kvm_fpu fpu;
  94
  95        vcpu_regs_get(vm, VCPU_ID, &regs);
  96        TEST_ASSERT(!memcmp(&regs.gprs, regs_null, sizeof(regs.gprs)), "grs == 0");
  97
  98        vcpu_sregs_get(vm, VCPU_ID, &sregs);
  99        TEST_ASSERT(!memcmp(&sregs.acrs, regs_null, sizeof(sregs.acrs)), "acrs == 0");
 100
 101        vcpu_fpu_get(vm, VCPU_ID, &fpu);
 102        TEST_ASSERT(!memcmp(&fpu.fprs, regs_null, sizeof(fpu.fprs)), "fprs == 0");
 103
 104        /* sync regs */
 105        TEST_ASSERT(!memcmp(sync_regs->gprs, regs_null, sizeof(sync_regs->gprs)),
 106                    "gprs0-15 == 0 (sync_regs)");
 107
 108        TEST_ASSERT(!memcmp(sync_regs->acrs, regs_null, sizeof(sync_regs->acrs)),
 109                    "acrs0-15 == 0 (sync_regs)");
 110
 111        TEST_ASSERT(!memcmp(sync_regs->vrs, regs_null, sizeof(sync_regs->vrs)),
 112                    "vrs0-15 == 0 (sync_regs)");
 113}
 114
 115static void assert_initial_noclear(void)
 116{
 117        TEST_ASSERT(sync_regs->gprs[0] == 0xffff000000000000UL,
 118                    "gpr0 == 0xffff000000000000 (sync_regs)");
 119        TEST_ASSERT(sync_regs->gprs[1] == 0x0000555500000000UL,
 120                    "gpr1 == 0x0000555500000000 (sync_regs)");
 121        TEST_ASSERT(sync_regs->gprs[2] == 0x00000000aaaa0000UL,
 122                    "gpr2 == 0x00000000aaaa0000 (sync_regs)");
 123        TEST_ASSERT(sync_regs->gprs[3] == 0x0000000000000000UL,
 124                    "gpr3 == 0x0000000000000000 (sync_regs)");
 125        TEST_ASSERT(sync_regs->fprs[0] == 0x3ff0000000000000UL,
 126                    "fpr0 == 0f1 (sync_regs)");
 127        TEST_ASSERT(sync_regs->acrs[9] == 1, "ar9 == 1 (sync_regs)");
 128}
 129
 130static void assert_initial(void)
 131{
 132        struct kvm_sregs sregs;
 133        struct kvm_fpu fpu;
 134
 135        /* KVM_GET_SREGS */
 136        vcpu_sregs_get(vm, VCPU_ID, &sregs);
 137        TEST_ASSERT(sregs.crs[0] == 0xE0UL, "cr0 == 0xE0 (KVM_GET_SREGS)");
 138        TEST_ASSERT(sregs.crs[14] == 0xC2000000UL,
 139                    "cr14 == 0xC2000000 (KVM_GET_SREGS)");
 140        TEST_ASSERT(!memcmp(&sregs.crs[1], regs_null, sizeof(sregs.crs[1]) * 12),
 141                    "cr1-13 == 0 (KVM_GET_SREGS)");
 142        TEST_ASSERT(sregs.crs[15] == 0, "cr15 == 0 (KVM_GET_SREGS)");
 143
 144        /* sync regs */
 145        TEST_ASSERT(sync_regs->crs[0] == 0xE0UL, "cr0 == 0xE0 (sync_regs)");
 146        TEST_ASSERT(sync_regs->crs[14] == 0xC2000000UL,
 147                    "cr14 == 0xC2000000 (sync_regs)");
 148        TEST_ASSERT(!memcmp(&sync_regs->crs[1], regs_null, 8 * 12),
 149                    "cr1-13 == 0 (sync_regs)");
 150        TEST_ASSERT(sync_regs->crs[15] == 0, "cr15 == 0 (sync_regs)");
 151        TEST_ASSERT(sync_regs->fpc == 0, "fpc == 0 (sync_regs)");
 152        TEST_ASSERT(sync_regs->todpr == 0, "todpr == 0 (sync_regs)");
 153        TEST_ASSERT(sync_regs->cputm == 0, "cputm == 0 (sync_regs)");
 154        TEST_ASSERT(sync_regs->ckc == 0, "ckc == 0 (sync_regs)");
 155        TEST_ASSERT(sync_regs->pp == 0, "pp == 0 (sync_regs)");
 156        TEST_ASSERT(sync_regs->gbea == 1, "gbea == 1 (sync_regs)");
 157
 158        /* kvm_run */
 159        TEST_ASSERT(run->psw_addr == 0, "psw_addr == 0 (kvm_run)");
 160        TEST_ASSERT(run->psw_mask == 0, "psw_mask == 0 (kvm_run)");
 161
 162        vcpu_fpu_get(vm, VCPU_ID, &fpu);
 163        TEST_ASSERT(!fpu.fpc, "fpc == 0");
 164
 165        test_one_reg(KVM_REG_S390_GBEA, 1);
 166        test_one_reg(KVM_REG_S390_PP, 0);
 167        test_one_reg(KVM_REG_S390_TODPR, 0);
 168        test_one_reg(KVM_REG_S390_CPU_TIMER, 0);
 169        test_one_reg(KVM_REG_S390_CLOCK_COMP, 0);
 170}
 171
 172static void assert_normal_noclear(void)
 173{
 174        TEST_ASSERT(sync_regs->crs[2] == 0x10, "cr2 == 10 (sync_regs)");
 175        TEST_ASSERT(sync_regs->crs[8] == 1, "cr10 == 1 (sync_regs)");
 176        TEST_ASSERT(sync_regs->crs[10] == 1, "cr10 == 1 (sync_regs)");
 177        TEST_ASSERT(sync_regs->crs[11] == -1, "cr11 == -1 (sync_regs)");
 178}
 179
 180static void assert_normal(void)
 181{
 182        test_one_reg(KVM_REG_S390_PFTOKEN, KVM_S390_PFAULT_TOKEN_INVALID);
 183        TEST_ASSERT(sync_regs->pft == KVM_S390_PFAULT_TOKEN_INVALID,
 184                        "pft == 0xff.....  (sync_regs)");
 185        assert_noirq();
 186}
 187
 188static void inject_irq(int cpu_id)
 189{
 190        struct kvm_s390_irq_state irq_state;
 191        struct kvm_s390_irq *irq = &buf[0];
 192        int irqs;
 193
 194        /* Inject IRQ */
 195        irq_state.len = sizeof(struct kvm_s390_irq);
 196        irq_state.buf = (unsigned long)buf;
 197        irq->type = KVM_S390_INT_EMERGENCY;
 198        irq->u.emerg.code = cpu_id;
 199        irqs = _vcpu_ioctl(vm, cpu_id, KVM_S390_SET_IRQ_STATE, &irq_state);
 200        TEST_ASSERT(irqs >= 0, "Error injecting EMERGENCY IRQ errno %d\n", errno);
 201}
 202
 203static void test_normal(void)
 204{
 205        pr_info("Testing normal reset\n");
 206        /* Create VM */
 207        vm = vm_create_default(VCPU_ID, 0, guest_code_initial);
 208        run = vcpu_state(vm, VCPU_ID);
 209        sync_regs = &run->s.regs;
 210
 211        vcpu_run(vm, VCPU_ID);
 212
 213        inject_irq(VCPU_ID);
 214
 215        vcpu_ioctl(vm, VCPU_ID, KVM_S390_NORMAL_RESET, 0);
 216
 217        /* must clears */
 218        assert_normal();
 219        /* must not clears */
 220        assert_normal_noclear();
 221        assert_initial_noclear();
 222
 223        kvm_vm_free(vm);
 224}
 225
 226static void test_initial(void)
 227{
 228        pr_info("Testing initial reset\n");
 229        vm = vm_create_default(VCPU_ID, 0, guest_code_initial);
 230        run = vcpu_state(vm, VCPU_ID);
 231        sync_regs = &run->s.regs;
 232
 233        vcpu_run(vm, VCPU_ID);
 234
 235        inject_irq(VCPU_ID);
 236
 237        vcpu_ioctl(vm, VCPU_ID, KVM_S390_INITIAL_RESET, 0);
 238
 239        /* must clears */
 240        assert_normal();
 241        assert_initial();
 242        /* must not clears */
 243        assert_initial_noclear();
 244
 245        kvm_vm_free(vm);
 246}
 247
 248static void test_clear(void)
 249{
 250        pr_info("Testing clear reset\n");
 251        vm = vm_create_default(VCPU_ID, 0, guest_code_initial);
 252        run = vcpu_state(vm, VCPU_ID);
 253        sync_regs = &run->s.regs;
 254
 255        vcpu_run(vm, VCPU_ID);
 256
 257        inject_irq(VCPU_ID);
 258
 259        vcpu_ioctl(vm, VCPU_ID, KVM_S390_CLEAR_RESET, 0);
 260
 261        /* must clears */
 262        assert_normal();
 263        assert_initial();
 264        assert_clear();
 265
 266        kvm_vm_free(vm);
 267}
 268
 269int main(int argc, char *argv[])
 270{
 271        setbuf(stdout, NULL);   /* Tell stdout not to buffer its content */
 272
 273        test_initial();
 274        if (kvm_check_cap(KVM_CAP_S390_VCPU_RESETS)) {
 275                test_normal();
 276                test_clear();
 277        }
 278        return 0;
 279}
 280