1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020, Red Hat, Inc. 4 */ 5 #include "guest_modes.h" 6 7 #ifdef __aarch64__ 8 enum vm_guest_mode vm_mode_default; 9 #endif 10 11 struct guest_mode guest_modes[NUM_VM_MODES]; 12 13 void guest_modes_append_default(void) 14 { 15 #ifndef __aarch64__ 16 guest_mode_append(VM_MODE_DEFAULT, true, true); 17 #else 18 { 19 unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE); 20 int i; 21 22 vm_mode_default = NUM_VM_MODES; 23 24 if (limit >= 52) 25 guest_mode_append(VM_MODE_P52V48_64K, true, true); 26 if (limit >= 48) { 27 guest_mode_append(VM_MODE_P48V48_4K, true, true); 28 guest_mode_append(VM_MODE_P48V48_64K, true, true); 29 } 30 if (limit >= 40) { 31 guest_mode_append(VM_MODE_P40V48_4K, true, true); 32 guest_mode_append(VM_MODE_P40V48_64K, true, true); 33 vm_mode_default = VM_MODE_P40V48_4K; 34 } 35 36 /* 37 * Pick the first supported IPA size if the default 38 * isn't available. 39 */ 40 for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) { 41 if (guest_modes[i].supported && guest_modes[i].enabled) 42 vm_mode_default = i; 43 } 44 45 TEST_ASSERT(vm_mode_default != NUM_VM_MODES, 46 "No supported mode!"); 47 } 48 #endif 49 #ifdef __s390x__ 50 { 51 int kvm_fd, vm_fd; 52 struct kvm_s390_vm_cpu_processor info; 53 54 kvm_fd = open_kvm_dev_path_or_exit(); 55 vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0); 56 kvm_device_access(vm_fd, KVM_S390_VM_CPU_MODEL, 57 KVM_S390_VM_CPU_PROCESSOR, &info, false); 58 close(vm_fd); 59 close(kvm_fd); 60 /* Starting with z13 we have 47bits of physical address */ 61 if (info.ibc >= 0x30) 62 guest_mode_append(VM_MODE_P47V64_4K, true, true); 63 } 64 #endif 65 } 66 67 void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg) 68 { 69 int i; 70 71 for (i = 0; i < NUM_VM_MODES; ++i) { 72 if (!guest_modes[i].enabled) 73 continue; 74 TEST_ASSERT(guest_modes[i].supported, 75 "Guest mode ID %d (%s) not supported.", 76 i, vm_guest_mode_string(i)); 77 func(i, arg); 78 } 79 } 80 81 void guest_modes_help(void) 82 { 83 int i; 84 85 printf(" -m: specify the guest mode ID to test\n" 86 " (default: test all supported modes)\n" 87 " This option may be used multiple times.\n" 88 " Guest mode IDs:\n"); 89 for (i = 0; i < NUM_VM_MODES; ++i) { 90 printf(" %d: %s%s\n", i, vm_guest_mode_string(i), 91 guest_modes[i].supported ? " (supported)" : ""); 92 } 93 } 94 95 void guest_modes_cmdline(const char *arg) 96 { 97 static bool mode_selected; 98 unsigned int mode; 99 int i; 100 101 if (!mode_selected) { 102 for (i = 0; i < NUM_VM_MODES; ++i) 103 guest_modes[i].enabled = false; 104 mode_selected = true; 105 } 106 107 mode = strtoul(optarg, NULL, 10); 108 TEST_ASSERT(mode < NUM_VM_MODES, "Guest mode ID %d too big", mode); 109 guest_modes[mode].enabled = true; 110 } 111