| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2020, Red Hat, Inc.
- */
- #include "guest_modes.h"
- #if defined(__aarch64__) || defined(__riscv)
- #include "processor.h"
- enum vm_guest_mode vm_mode_default;
- #endif
- struct guest_mode guest_modes[NUM_VM_MODES];
- void guest_modes_append_default(void)
- {
- #if !defined(__aarch64__) && !defined(__riscv)
- guest_mode_append(VM_MODE_DEFAULT, true);
- #endif
- #ifdef __aarch64__
- {
- unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
- uint32_t ipa4k, ipa16k, ipa64k;
- int i;
- aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k);
- guest_mode_append(VM_MODE_P52V48_4K, ipa4k >= 52);
- guest_mode_append(VM_MODE_P52V48_16K, ipa16k >= 52);
- guest_mode_append(VM_MODE_P52V48_64K, ipa64k >= 52);
- guest_mode_append(VM_MODE_P48V48_4K, ipa4k >= 48);
- guest_mode_append(VM_MODE_P48V48_16K, ipa16k >= 48);
- guest_mode_append(VM_MODE_P48V48_64K, ipa64k >= 48);
- guest_mode_append(VM_MODE_P40V48_4K, ipa4k >= 40);
- guest_mode_append(VM_MODE_P40V48_16K, ipa16k >= 40);
- guest_mode_append(VM_MODE_P40V48_64K, ipa64k >= 40);
- guest_mode_append(VM_MODE_P36V48_4K, ipa4k >= 36);
- guest_mode_append(VM_MODE_P36V48_16K, ipa16k >= 36);
- guest_mode_append(VM_MODE_P36V48_64K, ipa64k >= 36);
- guest_mode_append(VM_MODE_P36V47_16K, ipa16k >= 36);
- vm_mode_default = ipa4k >= 40 ? VM_MODE_P40V48_4K : NUM_VM_MODES;
- /*
- * Pick the first supported IPA size if the default
- * isn't available.
- */
- for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) {
- if (guest_modes[i].supported && guest_modes[i].enabled)
- vm_mode_default = i;
- }
- TEST_ASSERT(vm_mode_default != NUM_VM_MODES,
- "No supported mode!");
- }
- #endif
- #ifdef __s390x__
- {
- int kvm_fd, vm_fd;
- struct kvm_s390_vm_cpu_processor info;
- kvm_fd = open_kvm_dev_path_or_exit();
- vm_fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, NULL);
- kvm_device_attr_get(vm_fd, KVM_S390_VM_CPU_MODEL,
- KVM_S390_VM_CPU_PROCESSOR, &info);
- close(vm_fd);
- close(kvm_fd);
- /* Starting with z13 we have 47bits of physical address */
- if (info.ibc >= 0x30)
- guest_mode_append(VM_MODE_P47V64_4K, true);
- }
- #endif
- #ifdef __riscv
- {
- unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);
- unsigned long satp_mode = riscv64_get_satp_mode() << SATP_MODE_SHIFT;
- int i;
- switch (sz) {
- case 59:
- guest_mode_append(VM_MODE_P56V57_4K, satp_mode >= SATP_MODE_57);
- guest_mode_append(VM_MODE_P56V48_4K, satp_mode >= SATP_MODE_48);
- guest_mode_append(VM_MODE_P56V39_4K, satp_mode >= SATP_MODE_39);
- break;
- case 50:
- guest_mode_append(VM_MODE_P50V57_4K, satp_mode >= SATP_MODE_57);
- guest_mode_append(VM_MODE_P50V48_4K, satp_mode >= SATP_MODE_48);
- guest_mode_append(VM_MODE_P50V39_4K, satp_mode >= SATP_MODE_39);
- break;
- case 41:
- guest_mode_append(VM_MODE_P41V57_4K, satp_mode >= SATP_MODE_57);
- guest_mode_append(VM_MODE_P41V48_4K, satp_mode >= SATP_MODE_48);
- guest_mode_append(VM_MODE_P41V39_4K, satp_mode >= SATP_MODE_39);
- break;
- default:
- break;
- }
- /* set the first supported mode as default */
- vm_mode_default = NUM_VM_MODES;
- for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) {
- if (guest_modes[i].supported && guest_modes[i].enabled)
- vm_mode_default = i;
- }
- TEST_ASSERT(vm_mode_default != NUM_VM_MODES, "No supported mode!");
- }
- #endif
- }
- void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg)
- {
- int i;
- for (i = 0; i < NUM_VM_MODES; ++i) {
- if (!guest_modes[i].enabled)
- continue;
- TEST_ASSERT(guest_modes[i].supported,
- "Guest mode ID %d (%s) not supported.",
- i, vm_guest_mode_string(i));
- func(i, arg);
- }
- }
- void guest_modes_help(void)
- {
- int i;
- printf(" -m: specify the guest mode ID to test\n"
- " (default: test all supported modes)\n"
- " This option may be used multiple times.\n"
- " Guest mode IDs:\n");
- for (i = 0; i < NUM_VM_MODES; ++i) {
- printf(" %d: %s%s\n", i, vm_guest_mode_string(i),
- guest_modes[i].supported ? " (supported)" : "");
- }
- }
- void guest_modes_cmdline(const char *arg)
- {
- static bool mode_selected;
- unsigned int mode;
- int i;
- if (!mode_selected) {
- for (i = 0; i < NUM_VM_MODES; ++i)
- guest_modes[i].enabled = false;
- mode_selected = true;
- }
- mode = atoi_non_negative("Guest mode ID", arg);
- TEST_ASSERT(mode < NUM_VM_MODES, "Guest mode ID %d too big", mode);
- guest_modes[mode].enabled = true;
- }
|