xref: /linux/tools/testing/selftests/kvm/lib/guest_modes.c (revision 1b53b581d4e8de0e48e33f19f131ab88987c4eac)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020, Red Hat, Inc.
4  */
5 #include "guest_modes.h"
6 
7 #if defined(__aarch64__) || defined(__riscv) || defined(__powerpc64__)
8 #include "processor.h"
9 enum vm_guest_mode vm_mode_default;
10 #endif
11 
12 #if defined(__powerpc64__)
13 #include <unistd.h>
14 #endif
15 
16 struct guest_mode guest_modes[NUM_VM_MODES];
17 
18 void guest_modes_append_default(void)
19 {
20 #if !defined(__aarch64__) && !defined(__riscv) && !defined(__powerpc64__)
21 	guest_mode_append(VM_MODE_DEFAULT, true);
22 #endif
23 
24 #ifdef __aarch64__
25 	{
26 		unsigned int limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
27 		u32 ipa4k, ipa16k, ipa64k;
28 		int i;
29 
30 		aarch64_get_supported_page_sizes(limit, &ipa4k, &ipa16k, &ipa64k);
31 
32 		guest_mode_append(VM_MODE_P52V48_4K, ipa4k >= 52);
33 		guest_mode_append(VM_MODE_P52V48_16K, ipa16k >= 52);
34 		guest_mode_append(VM_MODE_P52V48_64K, ipa64k >= 52);
35 
36 		guest_mode_append(VM_MODE_P48V48_4K, ipa4k >= 48);
37 		guest_mode_append(VM_MODE_P48V48_16K, ipa16k >= 48);
38 		guest_mode_append(VM_MODE_P48V48_64K, ipa64k >= 48);
39 
40 		guest_mode_append(VM_MODE_P40V48_4K, ipa4k >= 40);
41 		guest_mode_append(VM_MODE_P40V48_16K, ipa16k >= 40);
42 		guest_mode_append(VM_MODE_P40V48_64K, ipa64k >= 40);
43 
44 		guest_mode_append(VM_MODE_P36V48_4K, ipa4k >= 36);
45 		guest_mode_append(VM_MODE_P36V48_16K, ipa16k >= 36);
46 		guest_mode_append(VM_MODE_P36V48_64K, ipa64k >= 36);
47 		guest_mode_append(VM_MODE_P36V47_16K, ipa16k >= 36);
48 
49 		vm_mode_default = ipa4k >= 40 ? VM_MODE_P40V48_4K : NUM_VM_MODES;
50 
51 		/*
52 		 * Pick the first supported IPA size if the default
53 		 * isn't available.
54 		 */
55 		for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) {
56 			if (guest_modes[i].supported && guest_modes[i].enabled)
57 				vm_mode_default = i;
58 		}
59 
60 		TEST_ASSERT(vm_mode_default != NUM_VM_MODES,
61 			    "No supported mode!");
62 	}
63 #endif
64 #ifdef __s390x__
65 	{
66 		int kvm_fd, vm_fd;
67 		struct kvm_s390_vm_cpu_processor info;
68 
69 		kvm_fd = open_kvm_dev_path_or_exit();
70 		vm_fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, NULL);
71 		kvm_device_attr_get(vm_fd, KVM_S390_VM_CPU_MODEL,
72 				    KVM_S390_VM_CPU_PROCESSOR, &info);
73 		close(vm_fd);
74 		close(kvm_fd);
75 		/* Starting with z13 we have 47bits of physical address */
76 		if (info.ibc >= 0x30)
77 			guest_mode_append(VM_MODE_P47V64_4K, true);
78 	}
79 #endif
80 #ifdef __riscv
81 	{
82 		unsigned int sz = kvm_check_cap(KVM_CAP_VM_GPA_BITS);
83 		unsigned long satp_mode = riscv64_get_satp_mode() << SATP_MODE_SHIFT;
84 		int i;
85 
86 		switch (sz) {
87 		case 59:
88 			guest_mode_append(VM_MODE_P56V57_4K, satp_mode >= SATP_MODE_57);
89 			guest_mode_append(VM_MODE_P56V48_4K, satp_mode >= SATP_MODE_48);
90 			guest_mode_append(VM_MODE_P56V39_4K, satp_mode >= SATP_MODE_39);
91 			break;
92 		case 50:
93 			guest_mode_append(VM_MODE_P50V57_4K, satp_mode >= SATP_MODE_57);
94 			guest_mode_append(VM_MODE_P50V48_4K, satp_mode >= SATP_MODE_48);
95 			guest_mode_append(VM_MODE_P50V39_4K, satp_mode >= SATP_MODE_39);
96 			break;
97 		case 41:
98 			guest_mode_append(VM_MODE_P41V57_4K, satp_mode >= SATP_MODE_57);
99 			guest_mode_append(VM_MODE_P41V48_4K, satp_mode >= SATP_MODE_48);
100 			guest_mode_append(VM_MODE_P41V39_4K, satp_mode >= SATP_MODE_39);
101 			break;
102 		default:
103 			break;
104 		}
105 
106 		/* set the first supported mode as default */
107 		vm_mode_default = NUM_VM_MODES;
108 		for (i = 0; vm_mode_default == NUM_VM_MODES && i < NUM_VM_MODES; i++) {
109 			if (guest_modes[i].supported && guest_modes[i].enabled)
110 				vm_mode_default = i;
111 		}
112 		TEST_ASSERT(vm_mode_default != NUM_VM_MODES, "No supported mode!");
113 	}
114 #endif
115 #ifdef __powerpc64__
116 	{
117 		TEST_REQUIRE(kvm_has_cap(KVM_CAP_PPC_MMU_RADIX));
118 		/* Radix guest EA and RA are 52-bit on POWER9 and POWER10 */
119 		if (sysconf(_SC_PAGESIZE) == 4096)
120 			vm_mode_default = VM_MODE_P52V52_4K;
121 		else
122 			vm_mode_default = VM_MODE_P52V52_64K;
123 		guest_mode_append(VM_MODE_P52V52_4K, true);
124 		guest_mode_append(VM_MODE_P52V52_64K, true);
125 	}
126 #endif
127 }
128 
129 void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg)
130 {
131 	int i;
132 
133 	for (i = 0; i < NUM_VM_MODES; ++i) {
134 		if (!guest_modes[i].enabled)
135 			continue;
136 		TEST_ASSERT(guest_modes[i].supported,
137 			    "Guest mode ID %d (%s) not supported.",
138 			    i, vm_guest_mode_string(i));
139 		func(i, arg);
140 	}
141 }
142 
143 void guest_modes_help(void)
144 {
145 	int i;
146 
147 	printf(" -m: specify the guest mode ID to test\n"
148 	       "     (default: test all supported modes)\n"
149 	       "     This option may be used multiple times.\n"
150 	       "     Guest mode IDs:\n");
151 	for (i = 0; i < NUM_VM_MODES; ++i) {
152 		printf("         %d:    %s%s\n", i, vm_guest_mode_string(i),
153 		       guest_modes[i].supported ? " (supported)" : "");
154 	}
155 }
156 
157 void guest_modes_cmdline(const char *arg)
158 {
159 	static bool mode_selected;
160 	unsigned int mode;
161 	int i;
162 
163 	if (!mode_selected) {
164 		for (i = 0; i < NUM_VM_MODES; ++i)
165 			guest_modes[i].enabled = false;
166 		mode_selected = true;
167 	}
168 
169 	mode = atoi_non_negative("Guest mode ID", arg);
170 	TEST_ASSERT(mode < NUM_VM_MODES, "Guest mode ID %d too big", mode);
171 	guest_modes[mode].enabled = true;
172 }
173