Path: blob/master/tools/testing/selftests/kvm/lib/guest_modes.c
38235 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2020, Red Hat, Inc.3*/4#include "guest_modes.h"56#ifdef __aarch64__7#include "processor.h"8enum vm_guest_mode vm_mode_default;9#endif1011struct guest_mode guest_modes[NUM_VM_MODES];1213void guest_modes_append_default(void)14{15#ifndef __aarch64__16guest_mode_append(VM_MODE_DEFAULT, true);17#else18{19unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);20uint32_t ipa4k, ipa16k, ipa64k;21int i;2223aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k);2425guest_mode_append(VM_MODE_P52V48_4K, ipa4k >= 52);26guest_mode_append(VM_MODE_P52V48_16K, ipa16k >= 52);27guest_mode_append(VM_MODE_P52V48_64K, ipa64k >= 52);2829guest_mode_append(VM_MODE_P48V48_4K, ipa4k >= 48);30guest_mode_append(VM_MODE_P48V48_16K, ipa16k >= 48);31guest_mode_append(VM_MODE_P48V48_64K, ipa64k >= 48);3233guest_mode_append(VM_MODE_P40V48_4K, ipa4k >= 40);34guest_mode_append(VM_MODE_P40V48_16K, ipa16k >= 40);35guest_mode_append(VM_MODE_P40V48_64K, ipa64k >= 40);3637guest_mode_append(VM_MODE_P36V48_4K, ipa4k >= 36);38guest_mode_append(VM_MODE_P36V48_16K, ipa16k >= 36);39guest_mode_append(VM_MODE_P36V48_64K, ipa64k >= 36);40guest_mode_append(VM_MODE_P36V47_16K, ipa16k >= 36);4142vm_mode_default = ipa4k >= 40 ? VM_MODE_P40V48_4K : NUM_VM_MODES;4344/*45* Pick the first supported IPA size if the default46* isn't available.47*/48for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) {49if (guest_modes[i].supported && guest_modes[i].enabled)50vm_mode_default = i;51}5253TEST_ASSERT(vm_mode_default != NUM_VM_MODES,54"No supported mode!");55}56#endif57#ifdef __s390x__58{59int kvm_fd, vm_fd;60struct kvm_s390_vm_cpu_processor info;6162kvm_fd = open_kvm_dev_path_or_exit();63vm_fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, NULL);64kvm_device_attr_get(vm_fd, KVM_S390_VM_CPU_MODEL,65KVM_S390_VM_CPU_PROCESSOR, &info);66close(vm_fd);67close(kvm_fd);68/* Starting with z13 we have 47bits of physical address */69if (info.ibc >= 0x30)70guest_mode_append(VM_MODE_P47V64_4K, true);71}72#endif73#ifdef __riscv74{75unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);7677if (sz >= 52)78guest_mode_append(VM_MODE_P52V48_4K, true);79if (sz >= 48)80guest_mode_append(VM_MODE_P48V48_4K, true);81}82#endif83}8485void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg)86{87int i;8889for (i = 0; i < NUM_VM_MODES; ++i) {90if (!guest_modes[i].enabled)91continue;92TEST_ASSERT(guest_modes[i].supported,93"Guest mode ID %d (%s) not supported.",94i, vm_guest_mode_string(i));95func(i, arg);96}97}9899void guest_modes_help(void)100{101int i;102103printf(" -m: specify the guest mode ID to test\n"104" (default: test all supported modes)\n"105" This option may be used multiple times.\n"106" Guest mode IDs:\n");107for (i = 0; i < NUM_VM_MODES; ++i) {108printf(" %d: %s%s\n", i, vm_guest_mode_string(i),109guest_modes[i].supported ? " (supported)" : "");110}111}112113void guest_modes_cmdline(const char *arg)114{115static bool mode_selected;116unsigned int mode;117int i;118119if (!mode_selected) {120for (i = 0; i < NUM_VM_MODES; ++i)121guest_modes[i].enabled = false;122mode_selected = true;123}124125mode = atoi_non_negative("Guest mode ID", arg);126TEST_ASSERT(mode < NUM_VM_MODES, "Guest mode ID %d too big", mode);127guest_modes[mode].enabled = true;128}129130131