Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'kvm-s390-next-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: pvdump and selftest improvements

- add an interface to provide a hypervisor dump for secure guests
- improve selftests to show tests

+1052 -56
+160 -2
Documentation/virt/kvm/api.rst
··· 5127 5127 __u32 reserved[3]; 5128 5128 }; 5129 5129 5130 - cmd values: 5130 + **Ultravisor return codes** 5131 + The Ultravisor return (reason) codes are provided by the kernel if a 5132 + Ultravisor call has been executed to achieve the results expected by 5133 + the command. Therefore they are independent of the IOCTL return 5134 + code. If KVM changes `rc`, its value will always be greater than 0 5135 + hence setting it to 0 before issuing a PV command is advised to be 5136 + able to detect a change of `rc`. 5137 + 5138 + **cmd values:** 5131 5139 5132 5140 KVM_PV_ENABLE 5133 5141 Allocate memory and register the VM with the Ultravisor, thereby ··· 5151 5143 ===== ============================= 5152 5144 5153 5145 KVM_PV_DISABLE 5154 - 5155 5146 Deregister the VM from the Ultravisor and reclaim the memory that 5156 5147 had been donated to the Ultravisor, making it usable by the kernel 5157 5148 again. All registered VCPUs are converted back to non-protected ··· 5166 5159 KVM_PV_VM_VERIFY 5167 5160 Verify the integrity of the unpacked image. Only if this succeeds, 5168 5161 KVM is allowed to start protected VCPUs. 5162 + 5163 + KVM_PV_INFO 5164 + :Capability: KVM_CAP_S390_PROTECTED_DUMP 5165 + 5166 + Presents an API that provides Ultravisor related data to userspace 5167 + via subcommands. len_max is the size of the user space buffer, 5168 + len_written is KVM's indication of how much bytes of that buffer 5169 + were actually written to. len_written can be used to determine the 5170 + valid fields if more response fields are added in the future. 5171 + 5172 + :: 5173 + 5174 + enum pv_cmd_info_id { 5175 + KVM_PV_INFO_VM, 5176 + KVM_PV_INFO_DUMP, 5177 + }; 5178 + 5179 + struct kvm_s390_pv_info_header { 5180 + __u32 id; 5181 + __u32 len_max; 5182 + __u32 len_written; 5183 + __u32 reserved; 5184 + }; 5185 + 5186 + struct kvm_s390_pv_info { 5187 + struct kvm_s390_pv_info_header header; 5188 + struct kvm_s390_pv_info_dump dump; 5189 + struct kvm_s390_pv_info_vm vm; 5190 + }; 5191 + 5192 + **subcommands:** 5193 + 5194 + KVM_PV_INFO_VM 5195 + This subcommand provides basic Ultravisor information for PV 5196 + hosts. These values are likely also exported as files in the sysfs 5197 + firmware UV query interface but they are more easily available to 5198 + programs in this API. 5199 + 5200 + The installed calls and feature_indication members provide the 5201 + installed UV calls and the UV's other feature indications. 5202 + 5203 + The max_* members provide information about the maximum number of PV 5204 + vcpus, PV guests and PV guest memory size. 5205 + 5206 + :: 5207 + 5208 + struct kvm_s390_pv_info_vm { 5209 + __u64 inst_calls_list[4]; 5210 + __u64 max_cpus; 5211 + __u64 max_guests; 5212 + __u64 max_guest_addr; 5213 + __u64 feature_indication; 5214 + }; 5215 + 5216 + 5217 + KVM_PV_INFO_DUMP 5218 + This subcommand provides information related to dumping PV guests. 5219 + 5220 + :: 5221 + 5222 + struct kvm_s390_pv_info_dump { 5223 + __u64 dump_cpu_buffer_len; 5224 + __u64 dump_config_mem_buffer_per_1m; 5225 + __u64 dump_config_finalize_len; 5226 + }; 5227 + 5228 + KVM_PV_DUMP 5229 + :Capability: KVM_CAP_S390_PROTECTED_DUMP 5230 + 5231 + Presents an API that provides calls which facilitate dumping a 5232 + protected VM. 5233 + 5234 + :: 5235 + 5236 + struct kvm_s390_pv_dmp { 5237 + __u64 subcmd; 5238 + __u64 buff_addr; 5239 + __u64 buff_len; 5240 + __u64 gaddr; /* For dump storage state */ 5241 + }; 5242 + 5243 + **subcommands:** 5244 + 5245 + KVM_PV_DUMP_INIT 5246 + Initializes the dump process of a protected VM. If this call does 5247 + not succeed all other subcommands will fail with -EINVAL. This 5248 + subcommand will return -EINVAL if a dump process has not yet been 5249 + completed. 5250 + 5251 + Not all PV vms can be dumped, the owner needs to set `dump 5252 + allowed` PCF bit 34 in the SE header to allow dumping. 5253 + 5254 + KVM_PV_DUMP_CONFIG_STOR_STATE 5255 + Stores `buff_len` bytes of tweak component values starting with 5256 + the 1MB block specified by the absolute guest address 5257 + (`gaddr`). `buff_len` needs to be `conf_dump_storage_state_len` 5258 + aligned and at least >= the `conf_dump_storage_state_len` value 5259 + provided by the dump uv_info data. buff_user might be written to 5260 + even if an error rc is returned. For instance if we encounter a 5261 + fault after writing the first page of data. 5262 + 5263 + KVM_PV_DUMP_COMPLETE 5264 + If the subcommand succeeds it completes the dump process and lets 5265 + KVM_PV_DUMP_INIT be called again. 5266 + 5267 + On success `conf_dump_finalize_len` bytes of completion data will be 5268 + stored to the `buff_addr`. The completion data contains a key 5269 + derivation seed, IV, tweak nonce and encryption keys as well as an 5270 + authentication tag all of which are needed to decrypt the dump at a 5271 + later time. 5272 + 5169 5273 5170 5274 4.126 KVM_X86_SET_MSR_FILTER 5171 5275 ---------------------------- ··· 5919 5801 }; 5920 5802 5921 5803 This ioctl injects an event channel interrupt directly to the guest vCPU. 5804 + 5805 + 4.136 KVM_S390_PV_CPU_COMMAND 5806 + ----------------------------- 5807 + 5808 + :Capability: KVM_CAP_S390_PROTECTED_DUMP 5809 + :Architectures: s390 5810 + :Type: vcpu ioctl 5811 + :Parameters: none 5812 + :Returns: 0 on success, < 0 on error 5813 + 5814 + This ioctl closely mirrors `KVM_S390_PV_COMMAND` but handles requests 5815 + for vcpus. It re-uses the kvm_s390_pv_dmp struct and hence also shares 5816 + the command ids. 5817 + 5818 + **command:** 5819 + 5820 + KVM_PV_DUMP 5821 + Presents an API that provides calls which facilitate dumping a vcpu 5822 + of a protected VM. 5823 + 5824 + **subcommand:** 5825 + 5826 + KVM_PV_DUMP_CPU 5827 + Provides encrypted dump data like register values. 5828 + The length of the returned data is provided by uv_info.guest_cpu_stor_len. 5829 + 5922 5830 5923 5831 5. The kvm_run structure 5924 5832 ======================== ··· 8099 7955 8100 7956 When enabled, KVM will exit to userspace with KVM_EXIT_SYSTEM_EVENT of 8101 7957 type KVM_SYSTEM_EVENT_SUSPEND to process the guest suspend request. 7958 + 7959 + 8.37 KVM_CAP_S390_PROTECTED_DUMP 7960 + -------------------------------- 7961 + 7962 + :Capability: KVM_CAP_S390_PROTECTED_DUMP 7963 + :Architectures: s390 7964 + :Type: vm 7965 + 7966 + This capability indicates that KVM and the Ultravisor support dumping 7967 + PV guests. The `KVM_PV_DUMP` command is available for the 7968 + `KVM_S390_PV_COMMAND` ioctl and the `KVM_PV_INFO` command provides 7969 + dump related UV data. Also the vcpu ioctl `KVM_S390_PV_CPU_COMMAND` is 7970 + available and supports the `KVM_PV_DUMP_CPU` subcommand. 7971 + 8102 7972 8103 7973 9. Known KVM API problems 8104 7974 =========================
+1
Documentation/virt/kvm/s390/index.rst
··· 10 10 s390-diag 11 11 s390-pv 12 12 s390-pv-boot 13 + s390-pv-dump
+64
Documentation/virt/kvm/s390/s390-pv-dump.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + =========================================== 4 + s390 (IBM Z) Protected Virtualization dumps 5 + =========================================== 6 + 7 + Summary 8 + ------- 9 + 10 + Dumping a VM is an essential tool for debugging problems inside 11 + it. This is especially true when a protected VM runs into trouble as 12 + there's no way to access its memory and registers from the outside 13 + while it's running. 14 + 15 + However when dumping a protected VM we need to maintain its 16 + confidentiality until the dump is in the hands of the VM owner who 17 + should be the only one capable of analysing it. 18 + 19 + The confidentiality of the VM dump is ensured by the Ultravisor who 20 + provides an interface to KVM over which encrypted CPU and memory data 21 + can be requested. The encryption is based on the Customer 22 + Communication Key which is the key that's used to encrypt VM data in a 23 + way that the customer is able to decrypt. 24 + 25 + 26 + Dump process 27 + ------------ 28 + 29 + A dump is done in 3 steps: 30 + 31 + **Initiation** 32 + 33 + This step initializes the dump process, generates cryptographic seeds 34 + and extracts dump keys with which the VM dump data will be encrypted. 35 + 36 + **Data gathering** 37 + 38 + Currently there are two types of data that can be gathered from a VM: 39 + the memory and the vcpu state. 40 + 41 + The vcpu state contains all the important registers, general, floating 42 + point, vector, control and tod/timers of a vcpu. The vcpu dump can 43 + contain incomplete data if a vcpu is dumped while an instruction is 44 + emulated with help of the hypervisor. This is indicated by a flag bit 45 + in the dump data. For the same reason it is very important to not only 46 + write out the encrypted vcpu state, but also the unencrypted state 47 + from the hypervisor. 48 + 49 + The memory state is further divided into the encrypted memory and its 50 + metadata comprised of the encryption tweaks and status flags. The 51 + encrypted memory can simply be read once it has been exported. The 52 + time of the export does not matter as no re-encryption is 53 + needed. Memory that has been swapped out and hence was exported can be 54 + read from the swap and written to the dump target without need for any 55 + special actions. 56 + 57 + The tweaks / status flags for the exported pages need to be requested 58 + from the Ultravisor. 59 + 60 + **Finalization** 61 + 62 + The finalization step will provide the data needed to be able to 63 + decrypt the vcpu and memory data and end the dump process. When this 64 + step completes successfully a new dump initiation can be started.
+4
arch/s390/boot/uv.c
··· 41 41 uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; 42 42 uv_info.max_guest_cpu_id = uvcb.max_guest_cpu_id; 43 43 uv_info.uv_feature_indications = uvcb.uv_feature_indications; 44 + uv_info.supp_se_hdr_ver = uvcb.supp_se_hdr_versions; 45 + uv_info.supp_se_hdr_pcf = uvcb.supp_se_hdr_pcf; 46 + uv_info.conf_dump_storage_state_len = uvcb.conf_dump_storage_state_len; 47 + uv_info.conf_dump_finalize_len = uvcb.conf_dump_finalize_len; 44 48 } 45 49 46 50 #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
+1
arch/s390/include/asm/kvm_host.h
··· 923 923 u64 guest_len; 924 924 unsigned long stor_base; 925 925 void *stor_var; 926 + bool dumping; 926 927 }; 927 928 928 929 struct kvm_arch{
+44 -1
arch/s390/include/asm/uv.h
··· 50 50 #define UVC_CMD_SET_UNSHARE_ALL 0x0340 51 51 #define UVC_CMD_PIN_PAGE_SHARED 0x0341 52 52 #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 53 + #define UVC_CMD_DUMP_INIT 0x0400 54 + #define UVC_CMD_DUMP_CONF_STOR_STATE 0x0401 55 + #define UVC_CMD_DUMP_CPU 0x0402 56 + #define UVC_CMD_DUMP_COMPLETE 0x0403 53 57 #define UVC_CMD_SET_SHARED_ACCESS 0x1000 54 58 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 55 59 #define UVC_CMD_RETR_ATTEST 0x1020 ··· 81 77 BIT_UVC_CMD_UNSHARE_ALL = 20, 82 78 BIT_UVC_CMD_PIN_PAGE_SHARED = 21, 83 79 BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, 80 + BIT_UVC_CMD_DUMP_INIT = 24, 81 + BIT_UVC_CMD_DUMP_CONFIG_STOR_STATE = 25, 82 + BIT_UVC_CMD_DUMP_CPU = 26, 83 + BIT_UVC_CMD_DUMP_COMPLETE = 27, 84 84 BIT_UVC_CMD_RETR_ATTEST = 28, 85 85 }; 86 86 ··· 118 110 u8 reserved88[158 - 136]; /* 0x0088 */ 119 111 u16 max_guest_cpu_id; /* 0x009e */ 120 112 u64 uv_feature_indications; /* 0x00a0 */ 121 - u8 reserveda8[200 - 168]; /* 0x00a8 */ 113 + u64 reserveda8; /* 0x00a8 */ 114 + u64 supp_se_hdr_versions; /* 0x00b0 */ 115 + u64 supp_se_hdr_pcf; /* 0x00b8 */ 116 + u64 reservedc0; /* 0x00c0 */ 117 + u64 conf_dump_storage_state_len; /* 0x00c8 */ 118 + u64 conf_dump_finalize_len; /* 0x00d0 */ 119 + u8 reservedd8[256 - 216]; /* 0x00d8 */ 122 120 } __packed __aligned(8); 123 121 124 122 /* Initialize Ultravisor */ ··· 254 240 u64 reserved168[4]; /* 0x0168 */ 255 241 } __packed __aligned(8); 256 242 243 + struct uv_cb_dump_cpu { 244 + struct uv_cb_header header; 245 + u64 reserved08[2]; 246 + u64 cpu_handle; 247 + u64 dump_area_origin; 248 + u64 reserved28[5]; 249 + } __packed __aligned(8); 250 + 251 + struct uv_cb_dump_stor_state { 252 + struct uv_cb_header header; 253 + u64 reserved08[2]; 254 + u64 config_handle; 255 + u64 dump_area_origin; 256 + u64 gaddr; 257 + u64 reserved28[4]; 258 + } __packed __aligned(8); 259 + 260 + struct uv_cb_dump_complete { 261 + struct uv_cb_header header; 262 + u64 reserved08[2]; 263 + u64 config_handle; 264 + u64 dump_area_origin; 265 + u64 reserved30[5]; 266 + } __packed __aligned(8); 267 + 257 268 static inline int __uv_call(unsigned long r1, unsigned long r2) 258 269 { 259 270 int cc; ··· 346 307 unsigned int max_num_sec_conf; 347 308 unsigned short max_guest_cpu_id; 348 309 unsigned long uv_feature_indications; 310 + unsigned long supp_se_hdr_ver; 311 + unsigned long supp_se_hdr_pcf; 312 + unsigned long conf_dump_storage_state_len; 313 + unsigned long conf_dump_finalize_len; 349 314 }; 350 315 351 316 extern struct uv_info uv_info;
+53
arch/s390/kernel/uv.c
··· 392 392 static struct kobj_attribute uv_query_facilities_attr = 393 393 __ATTR(facilities, 0444, uv_query_facilities, NULL); 394 394 395 + static ssize_t uv_query_supp_se_hdr_ver(struct kobject *kobj, 396 + struct kobj_attribute *attr, char *buf) 397 + { 398 + return sysfs_emit(buf, "%lx\n", uv_info.supp_se_hdr_ver); 399 + } 400 + 401 + static struct kobj_attribute uv_query_supp_se_hdr_ver_attr = 402 + __ATTR(supp_se_hdr_ver, 0444, uv_query_supp_se_hdr_ver, NULL); 403 + 404 + static ssize_t uv_query_supp_se_hdr_pcf(struct kobject *kobj, 405 + struct kobj_attribute *attr, char *buf) 406 + { 407 + return sysfs_emit(buf, "%lx\n", uv_info.supp_se_hdr_pcf); 408 + } 409 + 410 + static struct kobj_attribute uv_query_supp_se_hdr_pcf_attr = 411 + __ATTR(supp_se_hdr_pcf, 0444, uv_query_supp_se_hdr_pcf, NULL); 412 + 413 + static ssize_t uv_query_dump_cpu_len(struct kobject *kobj, 414 + struct kobj_attribute *attr, char *page) 415 + { 416 + return scnprintf(page, PAGE_SIZE, "%lx\n", 417 + uv_info.guest_cpu_stor_len); 418 + } 419 + 420 + static struct kobj_attribute uv_query_dump_cpu_len_attr = 421 + __ATTR(uv_query_dump_cpu_len, 0444, uv_query_dump_cpu_len, NULL); 422 + 423 + static ssize_t uv_query_dump_storage_state_len(struct kobject *kobj, 424 + struct kobj_attribute *attr, char *page) 425 + { 426 + return scnprintf(page, PAGE_SIZE, "%lx\n", 427 + uv_info.conf_dump_storage_state_len); 428 + } 429 + 430 + static struct kobj_attribute uv_query_dump_storage_state_len_attr = 431 + __ATTR(dump_storage_state_len, 0444, uv_query_dump_storage_state_len, NULL); 432 + 433 + static ssize_t uv_query_dump_finalize_len(struct kobject *kobj, 434 + struct kobj_attribute *attr, char *page) 435 + { 436 + return scnprintf(page, PAGE_SIZE, "%lx\n", 437 + uv_info.conf_dump_finalize_len); 438 + } 439 + 440 + static struct kobj_attribute uv_query_dump_finalize_len_attr = 441 + __ATTR(dump_finalize_len, 0444, uv_query_dump_finalize_len, NULL); 442 + 395 443 static ssize_t uv_query_feature_indications(struct kobject *kobj, 396 444 struct kobj_attribute *attr, char *buf) 397 445 { ··· 485 437 &uv_query_max_guest_cpus_attr.attr, 486 438 &uv_query_max_guest_vms_attr.attr, 487 439 &uv_query_max_guest_addr_attr.attr, 440 + &uv_query_supp_se_hdr_ver_attr.attr, 441 + &uv_query_supp_se_hdr_pcf_attr.attr, 442 + &uv_query_dump_storage_state_len_attr.attr, 443 + &uv_query_dump_finalize_len_attr.attr, 444 + &uv_query_dump_cpu_len_attr.attr, 488 445 NULL, 489 446 }; 490 447
+269
arch/s390/kvm/kvm-s390.c
··· 606 606 case KVM_CAP_S390_PROTECTED: 607 607 r = is_prot_virt_host(); 608 608 break; 609 + case KVM_CAP_S390_PROTECTED_DUMP: { 610 + u64 pv_cmds_dump[] = { 611 + BIT_UVC_CMD_DUMP_INIT, 612 + BIT_UVC_CMD_DUMP_CONFIG_STOR_STATE, 613 + BIT_UVC_CMD_DUMP_CPU, 614 + BIT_UVC_CMD_DUMP_COMPLETE, 615 + }; 616 + int i; 617 + 618 + r = is_prot_virt_host(); 619 + 620 + for (i = 0; i < ARRAY_SIZE(pv_cmds_dump); i++) { 621 + if (!test_bit_inv(pv_cmds_dump[i], 622 + (unsigned long *)&uv_info.inst_calls_list)) { 623 + r = 0; 624 + break; 625 + } 626 + } 627 + break; 628 + } 609 629 default: 610 630 r = 0; 611 631 } ··· 2240 2220 return r; 2241 2221 } 2242 2222 2223 + /* 2224 + * Here we provide user space with a direct interface to query UV 2225 + * related data like UV maxima and available features as well as 2226 + * feature specific data. 2227 + * 2228 + * To facilitate future extension of the data structures we'll try to 2229 + * write data up to the maximum requested length. 2230 + */ 2231 + static ssize_t kvm_s390_handle_pv_info(struct kvm_s390_pv_info *info) 2232 + { 2233 + ssize_t len_min; 2234 + 2235 + switch (info->header.id) { 2236 + case KVM_PV_INFO_VM: { 2237 + len_min = sizeof(info->header) + sizeof(info->vm); 2238 + 2239 + if (info->header.len_max < len_min) 2240 + return -EINVAL; 2241 + 2242 + memcpy(info->vm.inst_calls_list, 2243 + uv_info.inst_calls_list, 2244 + sizeof(uv_info.inst_calls_list)); 2245 + 2246 + /* It's max cpuid not max cpus, so it's off by one */ 2247 + info->vm.max_cpus = uv_info.max_guest_cpu_id + 1; 2248 + info->vm.max_guests = uv_info.max_num_sec_conf; 2249 + info->vm.max_guest_addr = uv_info.max_sec_stor_addr; 2250 + info->vm.feature_indication = uv_info.uv_feature_indications; 2251 + 2252 + return len_min; 2253 + } 2254 + case KVM_PV_INFO_DUMP: { 2255 + len_min = sizeof(info->header) + sizeof(info->dump); 2256 + 2257 + if (info->header.len_max < len_min) 2258 + return -EINVAL; 2259 + 2260 + info->dump.dump_cpu_buffer_len = uv_info.guest_cpu_stor_len; 2261 + info->dump.dump_config_mem_buffer_per_1m = uv_info.conf_dump_storage_state_len; 2262 + info->dump.dump_config_finalize_len = uv_info.conf_dump_finalize_len; 2263 + return len_min; 2264 + } 2265 + default: 2266 + return -EINVAL; 2267 + } 2268 + } 2269 + 2270 + static int kvm_s390_pv_dmp(struct kvm *kvm, struct kvm_pv_cmd *cmd, 2271 + struct kvm_s390_pv_dmp dmp) 2272 + { 2273 + int r = -EINVAL; 2274 + void __user *result_buff = (void __user *)dmp.buff_addr; 2275 + 2276 + switch (dmp.subcmd) { 2277 + case KVM_PV_DUMP_INIT: { 2278 + if (kvm->arch.pv.dumping) 2279 + break; 2280 + 2281 + /* 2282 + * Block SIE entry as concurrent dump UVCs could lead 2283 + * to validities. 2284 + */ 2285 + kvm_s390_vcpu_block_all(kvm); 2286 + 2287 + r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm), 2288 + UVC_CMD_DUMP_INIT, &cmd->rc, &cmd->rrc); 2289 + KVM_UV_EVENT(kvm, 3, "PROTVIRT DUMP INIT: rc %x rrc %x", 2290 + cmd->rc, cmd->rrc); 2291 + if (!r) { 2292 + kvm->arch.pv.dumping = true; 2293 + } else { 2294 + kvm_s390_vcpu_unblock_all(kvm); 2295 + r = -EINVAL; 2296 + } 2297 + break; 2298 + } 2299 + case KVM_PV_DUMP_CONFIG_STOR_STATE: { 2300 + if (!kvm->arch.pv.dumping) 2301 + break; 2302 + 2303 + /* 2304 + * gaddr is an output parameter since we might stop 2305 + * early. As dmp will be copied back in our caller, we 2306 + * don't need to do it ourselves. 2307 + */ 2308 + r = kvm_s390_pv_dump_stor_state(kvm, result_buff, &dmp.gaddr, dmp.buff_len, 2309 + &cmd->rc, &cmd->rrc); 2310 + break; 2311 + } 2312 + case KVM_PV_DUMP_COMPLETE: { 2313 + if (!kvm->arch.pv.dumping) 2314 + break; 2315 + 2316 + r = -EINVAL; 2317 + if (dmp.buff_len < uv_info.conf_dump_finalize_len) 2318 + break; 2319 + 2320 + r = kvm_s390_pv_dump_complete(kvm, result_buff, 2321 + &cmd->rc, &cmd->rrc); 2322 + break; 2323 + } 2324 + default: 2325 + r = -ENOTTY; 2326 + break; 2327 + } 2328 + 2329 + return r; 2330 + } 2331 + 2243 2332 static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) 2244 2333 { 2245 2334 int r = 0; ··· 2483 2354 UVC_CMD_SET_UNSHARE_ALL, &cmd->rc, &cmd->rrc); 2484 2355 KVM_UV_EVENT(kvm, 3, "PROTVIRT UNSHARE: rc %x rrc %x", 2485 2356 cmd->rc, cmd->rrc); 2357 + break; 2358 + } 2359 + case KVM_PV_INFO: { 2360 + struct kvm_s390_pv_info info = {}; 2361 + ssize_t data_len; 2362 + 2363 + /* 2364 + * No need to check the VM protection here. 2365 + * 2366 + * Maybe user space wants to query some of the data 2367 + * when the VM is still unprotected. If we see the 2368 + * need to fence a new data command we can still 2369 + * return an error in the info handler. 2370 + */ 2371 + 2372 + r = -EFAULT; 2373 + if (copy_from_user(&info, argp, sizeof(info.header))) 2374 + break; 2375 + 2376 + r = -EINVAL; 2377 + if (info.header.len_max < sizeof(info.header)) 2378 + break; 2379 + 2380 + data_len = kvm_s390_handle_pv_info(&info); 2381 + if (data_len < 0) { 2382 + r = data_len; 2383 + break; 2384 + } 2385 + /* 2386 + * If a data command struct is extended (multiple 2387 + * times) this can be used to determine how much of it 2388 + * is valid. 2389 + */ 2390 + info.header.len_written = data_len; 2391 + 2392 + r = -EFAULT; 2393 + if (copy_to_user(argp, &info, data_len)) 2394 + break; 2395 + 2396 + r = 0; 2397 + break; 2398 + } 2399 + case KVM_PV_DUMP: { 2400 + struct kvm_s390_pv_dmp dmp; 2401 + 2402 + r = -EINVAL; 2403 + if (!kvm_s390_pv_is_protected(kvm)) 2404 + break; 2405 + 2406 + r = -EFAULT; 2407 + if (copy_from_user(&dmp, argp, sizeof(dmp))) 2408 + break; 2409 + 2410 + r = kvm_s390_pv_dmp(kvm, cmd, dmp); 2411 + if (r) 2412 + break; 2413 + 2414 + if (copy_to_user(argp, &dmp, sizeof(dmp))) { 2415 + r = -EFAULT; 2416 + break; 2417 + } 2418 + 2486 2419 break; 2487 2420 } 2488 2421 default: ··· 4664 4473 struct kvm_run *kvm_run = vcpu->run; 4665 4474 int rc; 4666 4475 4476 + /* 4477 + * Running a VM while dumping always has the potential to 4478 + * produce inconsistent dump data. But for PV vcpus a SIE 4479 + * entry while dumping could also lead to a fatal validity 4480 + * intercept which we absolutely want to avoid. 4481 + */ 4482 + if (vcpu->kvm->arch.pv.dumping) 4483 + return -EINVAL; 4484 + 4667 4485 if (kvm_run->immediate_exit) 4668 4486 return -EINTR; 4669 4487 ··· 5112 4912 return -ENOIOCTLCMD; 5113 4913 } 5114 4914 4915 + static int kvm_s390_handle_pv_vcpu_dump(struct kvm_vcpu *vcpu, 4916 + struct kvm_pv_cmd *cmd) 4917 + { 4918 + struct kvm_s390_pv_dmp dmp; 4919 + void *data; 4920 + int ret; 4921 + 4922 + /* Dump initialization is a prerequisite */ 4923 + if (!vcpu->kvm->arch.pv.dumping) 4924 + return -EINVAL; 4925 + 4926 + if (copy_from_user(&dmp, (__u8 __user *)cmd->data, sizeof(dmp))) 4927 + return -EFAULT; 4928 + 4929 + /* We only handle this subcmd right now */ 4930 + if (dmp.subcmd != KVM_PV_DUMP_CPU) 4931 + return -EINVAL; 4932 + 4933 + /* CPU dump length is the same as create cpu storage donation. */ 4934 + if (dmp.buff_len != uv_info.guest_cpu_stor_len) 4935 + return -EINVAL; 4936 + 4937 + data = kvzalloc(uv_info.guest_cpu_stor_len, GFP_KERNEL); 4938 + if (!data) 4939 + return -ENOMEM; 4940 + 4941 + ret = kvm_s390_pv_dump_cpu(vcpu, data, &cmd->rc, &cmd->rrc); 4942 + 4943 + VCPU_EVENT(vcpu, 3, "PROTVIRT DUMP CPU %d rc %x rrc %x", 4944 + vcpu->vcpu_id, cmd->rc, cmd->rrc); 4945 + 4946 + if (ret) 4947 + ret = -EINVAL; 4948 + 4949 + /* On success copy over the dump data */ 4950 + if (!ret && copy_to_user((__u8 __user *)dmp.buff_addr, data, uv_info.guest_cpu_stor_len)) 4951 + ret = -EFAULT; 4952 + 4953 + kvfree(data); 4954 + return ret; 4955 + } 4956 + 5115 4957 long kvm_arch_vcpu_ioctl(struct file *filp, 5116 4958 unsigned int ioctl, unsigned long arg) 5117 4959 { ··· 5316 5074 r = kvm_s390_get_irq_state(vcpu, 5317 5075 (__u8 __user *) irq_state.buf, 5318 5076 irq_state.len); 5077 + break; 5078 + } 5079 + case KVM_S390_PV_CPU_COMMAND: { 5080 + struct kvm_pv_cmd cmd; 5081 + 5082 + r = -EINVAL; 5083 + if (!is_prot_virt_host()) 5084 + break; 5085 + 5086 + r = -EFAULT; 5087 + if (copy_from_user(&cmd, argp, sizeof(cmd))) 5088 + break; 5089 + 5090 + r = -EINVAL; 5091 + if (cmd.flags) 5092 + break; 5093 + 5094 + /* We only handle this cmd right now */ 5095 + if (cmd.cmd != KVM_PV_DUMP) 5096 + break; 5097 + 5098 + r = kvm_s390_handle_pv_vcpu_dump(vcpu, &cmd); 5099 + 5100 + /* Always copy over UV rc / rrc data */ 5101 + if (copy_to_user((__u8 __user *)argp, &cmd.rc, 5102 + sizeof(cmd.rc) + sizeof(cmd.rrc))) 5103 + r = -EFAULT; 5319 5104 break; 5320 5105 } 5321 5106 default:
+5
arch/s390/kvm/kvm-s390.h
··· 250 250 int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size, 251 251 unsigned long tweak, u16 *rc, u16 *rrc); 252 252 int kvm_s390_pv_set_cpu_state(struct kvm_vcpu *vcpu, u8 state); 253 + int kvm_s390_pv_dump_cpu(struct kvm_vcpu *vcpu, void *buff, u16 *rc, u16 *rrc); 254 + int kvm_s390_pv_dump_stor_state(struct kvm *kvm, void __user *buff_user, 255 + u64 *gaddr, u64 buff_user_len, u16 *rc, u16 *rrc); 256 + int kvm_s390_pv_dump_complete(struct kvm *kvm, void __user *buff_user, 257 + u16 *rc, u16 *rrc); 253 258 254 259 static inline u64 kvm_s390_pv_get_handle(struct kvm *kvm) 255 260 {
+198
arch/s390/kvm/pv.c
··· 7 7 */ 8 8 #include <linux/kvm.h> 9 9 #include <linux/kvm_host.h> 10 + #include <linux/minmax.h> 10 11 #include <linux/pagemap.h> 11 12 #include <linux/sched/signal.h> 12 13 #include <asm/gmap.h> ··· 298 297 if (cc) 299 298 return -EINVAL; 300 299 return 0; 300 + } 301 + 302 + int kvm_s390_pv_dump_cpu(struct kvm_vcpu *vcpu, void *buff, u16 *rc, u16 *rrc) 303 + { 304 + struct uv_cb_dump_cpu uvcb = { 305 + .header.cmd = UVC_CMD_DUMP_CPU, 306 + .header.len = sizeof(uvcb), 307 + .cpu_handle = vcpu->arch.pv.handle, 308 + .dump_area_origin = (u64)buff, 309 + }; 310 + int cc; 311 + 312 + cc = uv_call_sched(0, (u64)&uvcb); 313 + *rc = uvcb.header.rc; 314 + *rrc = uvcb.header.rrc; 315 + return cc; 316 + } 317 + 318 + /* Size of the cache for the storage state dump data. 1MB for now */ 319 + #define DUMP_BUFF_LEN HPAGE_SIZE 320 + 321 + /** 322 + * kvm_s390_pv_dump_stor_state 323 + * 324 + * @kvm: pointer to the guest's KVM struct 325 + * @buff_user: Userspace pointer where we will write the results to 326 + * @gaddr: Starting absolute guest address for which the storage state 327 + * is requested. 328 + * @buff_user_len: Length of the buff_user buffer 329 + * @rc: Pointer to where the uvcb return code is stored 330 + * @rrc: Pointer to where the uvcb return reason code is stored 331 + * 332 + * Stores buff_len bytes of tweak component values to buff_user 333 + * starting with the 1MB block specified by the absolute guest address 334 + * (gaddr). The gaddr pointer will be updated with the last address 335 + * for which data was written when returning to userspace. buff_user 336 + * might be written to even if an error rc is returned. For instance 337 + * if we encounter a fault after writing the first page of data. 338 + * 339 + * Context: kvm->lock needs to be held 340 + * 341 + * Return: 342 + * 0 on success 343 + * -ENOMEM if allocating the cache fails 344 + * -EINVAL if gaddr is not aligned to 1MB 345 + * -EINVAL if buff_user_len is not aligned to uv_info.conf_dump_storage_state_len 346 + * -EINVAL if the UV call fails, rc and rrc will be set in this case 347 + * -EFAULT if copying the result to buff_user failed 348 + */ 349 + int kvm_s390_pv_dump_stor_state(struct kvm *kvm, void __user *buff_user, 350 + u64 *gaddr, u64 buff_user_len, u16 *rc, u16 *rrc) 351 + { 352 + struct uv_cb_dump_stor_state uvcb = { 353 + .header.cmd = UVC_CMD_DUMP_CONF_STOR_STATE, 354 + .header.len = sizeof(uvcb), 355 + .config_handle = kvm->arch.pv.handle, 356 + .gaddr = *gaddr, 357 + .dump_area_origin = 0, 358 + }; 359 + const u64 increment_len = uv_info.conf_dump_storage_state_len; 360 + size_t buff_kvm_size; 361 + size_t size_done = 0; 362 + u8 *buff_kvm = NULL; 363 + int cc, ret; 364 + 365 + ret = -EINVAL; 366 + /* UV call processes 1MB guest storage chunks at a time */ 367 + if (!IS_ALIGNED(*gaddr, HPAGE_SIZE)) 368 + goto out; 369 + 370 + /* 371 + * We provide the storage state for 1MB chunks of guest 372 + * storage. The buffer will need to be aligned to 373 + * conf_dump_storage_state_len so we don't end on a partial 374 + * chunk. 375 + */ 376 + if (!buff_user_len || 377 + !IS_ALIGNED(buff_user_len, increment_len)) 378 + goto out; 379 + 380 + /* 381 + * Allocate a buffer from which we will later copy to the user 382 + * process. We don't want userspace to dictate our buffer size 383 + * so we limit it to DUMP_BUFF_LEN. 384 + */ 385 + ret = -ENOMEM; 386 + buff_kvm_size = min_t(u64, buff_user_len, DUMP_BUFF_LEN); 387 + buff_kvm = vzalloc(buff_kvm_size); 388 + if (!buff_kvm) 389 + goto out; 390 + 391 + ret = 0; 392 + uvcb.dump_area_origin = (u64)buff_kvm; 393 + /* We will loop until the user buffer is filled or an error occurs */ 394 + do { 395 + /* Get 1MB worth of guest storage state data */ 396 + cc = uv_call_sched(0, (u64)&uvcb); 397 + 398 + /* All or nothing */ 399 + if (cc) { 400 + ret = -EINVAL; 401 + break; 402 + } 403 + 404 + size_done += increment_len; 405 + uvcb.dump_area_origin += increment_len; 406 + buff_user_len -= increment_len; 407 + uvcb.gaddr += HPAGE_SIZE; 408 + 409 + /* KVM Buffer full, time to copy to the process */ 410 + if (!buff_user_len || size_done == DUMP_BUFF_LEN) { 411 + if (copy_to_user(buff_user, buff_kvm, size_done)) { 412 + ret = -EFAULT; 413 + break; 414 + } 415 + 416 + buff_user += size_done; 417 + size_done = 0; 418 + uvcb.dump_area_origin = (u64)buff_kvm; 419 + } 420 + } while (buff_user_len); 421 + 422 + /* Report back where we ended dumping */ 423 + *gaddr = uvcb.gaddr; 424 + 425 + /* Lets only log errors, we don't want to spam */ 426 + out: 427 + if (ret) 428 + KVM_UV_EVENT(kvm, 3, 429 + "PROTVIRT DUMP STORAGE STATE: addr %llx ret %d, uvcb rc %x rrc %x", 430 + uvcb.gaddr, ret, uvcb.header.rc, uvcb.header.rrc); 431 + *rc = uvcb.header.rc; 432 + *rrc = uvcb.header.rrc; 433 + vfree(buff_kvm); 434 + 435 + return ret; 436 + } 437 + 438 + /** 439 + * kvm_s390_pv_dump_complete 440 + * 441 + * @kvm: pointer to the guest's KVM struct 442 + * @buff_user: Userspace pointer where we will write the results to 443 + * @rc: Pointer to where the uvcb return code is stored 444 + * @rrc: Pointer to where the uvcb return reason code is stored 445 + * 446 + * Completes the dumping operation and writes the completion data to 447 + * user space. 448 + * 449 + * Context: kvm->lock needs to be held 450 + * 451 + * Return: 452 + * 0 on success 453 + * -ENOMEM if allocating the completion buffer fails 454 + * -EINVAL if the UV call fails, rc and rrc will be set in this case 455 + * -EFAULT if copying the result to buff_user failed 456 + */ 457 + int kvm_s390_pv_dump_complete(struct kvm *kvm, void __user *buff_user, 458 + u16 *rc, u16 *rrc) 459 + { 460 + struct uv_cb_dump_complete complete = { 461 + .header.len = sizeof(complete), 462 + .header.cmd = UVC_CMD_DUMP_COMPLETE, 463 + .config_handle = kvm_s390_pv_get_handle(kvm), 464 + }; 465 + u64 *compl_data; 466 + int ret; 467 + 468 + /* Allocate dump area */ 469 + compl_data = vzalloc(uv_info.conf_dump_finalize_len); 470 + if (!compl_data) 471 + return -ENOMEM; 472 + complete.dump_area_origin = (u64)compl_data; 473 + 474 + ret = uv_call_sched(0, (u64)&complete); 475 + *rc = complete.header.rc; 476 + *rrc = complete.header.rrc; 477 + KVM_UV_EVENT(kvm, 3, "PROTVIRT DUMP COMPLETE: rc %x rrc %x", 478 + complete.header.rc, complete.header.rrc); 479 + 480 + if (!ret) { 481 + /* 482 + * kvm_s390_pv_dealloc_vm() will also (mem)set 483 + * this to false on a reboot or other destroy 484 + * operation for this vm. 485 + */ 486 + kvm->arch.pv.dumping = false; 487 + kvm_s390_vcpu_unblock_all(kvm); 488 + ret = copy_to_user(buff_user, compl_data, uv_info.conf_dump_finalize_len); 489 + if (ret) 490 + ret = -EFAULT; 491 + } 492 + vfree(compl_data); 493 + /* If the UVC returned an error, translate it to -EINVAL */ 494 + if (ret > 0) 495 + ret = -EINVAL; 496 + return ret; 301 497 }
+55
include/uapi/linux/kvm.h
··· 1157 1157 #define KVM_CAP_VM_TSC_CONTROL 214 1158 1158 #define KVM_CAP_SYSTEM_EVENT_DATA 215 1159 1159 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216 1160 + #define KVM_CAP_S390_PROTECTED_DUMP 217 1160 1161 1161 1162 #ifdef KVM_CAP_IRQ_ROUTING 1162 1163 ··· 1661 1660 __u64 tweak; 1662 1661 }; 1663 1662 1663 + enum pv_cmd_dmp_id { 1664 + KVM_PV_DUMP_INIT, 1665 + KVM_PV_DUMP_CONFIG_STOR_STATE, 1666 + KVM_PV_DUMP_COMPLETE, 1667 + KVM_PV_DUMP_CPU, 1668 + }; 1669 + 1670 + struct kvm_s390_pv_dmp { 1671 + __u64 subcmd; 1672 + __u64 buff_addr; 1673 + __u64 buff_len; 1674 + __u64 gaddr; /* For dump storage state */ 1675 + __u64 reserved[4]; 1676 + }; 1677 + 1678 + enum pv_cmd_info_id { 1679 + KVM_PV_INFO_VM, 1680 + KVM_PV_INFO_DUMP, 1681 + }; 1682 + 1683 + struct kvm_s390_pv_info_dump { 1684 + __u64 dump_cpu_buffer_len; 1685 + __u64 dump_config_mem_buffer_per_1m; 1686 + __u64 dump_config_finalize_len; 1687 + }; 1688 + 1689 + struct kvm_s390_pv_info_vm { 1690 + __u64 inst_calls_list[4]; 1691 + __u64 max_cpus; 1692 + __u64 max_guests; 1693 + __u64 max_guest_addr; 1694 + __u64 feature_indication; 1695 + }; 1696 + 1697 + struct kvm_s390_pv_info_header { 1698 + __u32 id; 1699 + __u32 len_max; 1700 + __u32 len_written; 1701 + __u32 reserved; 1702 + }; 1703 + 1704 + struct kvm_s390_pv_info { 1705 + struct kvm_s390_pv_info_header header; 1706 + union { 1707 + struct kvm_s390_pv_info_dump dump; 1708 + struct kvm_s390_pv_info_vm vm; 1709 + }; 1710 + }; 1711 + 1664 1712 enum pv_cmd_id { 1665 1713 KVM_PV_ENABLE, 1666 1714 KVM_PV_DISABLE, ··· 1718 1668 KVM_PV_VERIFY, 1719 1669 KVM_PV_PREP_RESET, 1720 1670 KVM_PV_UNSHARE_ALL, 1671 + KVM_PV_INFO, 1672 + KVM_PV_DUMP, 1721 1673 }; 1722 1674 1723 1675 struct kvm_pv_cmd { ··· 2169 2117 2170 2118 /* Available with KVM_CAP_XSAVE2 */ 2171 2119 #define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) 2120 + 2121 + /* Available with KVM_CAP_S390_PROTECTED_DUMP */ 2122 + #define KVM_S390_PV_CPU_COMMAND _IOWR(KVMIO, 0xd0, struct kvm_pv_cmd) 2172 2123 2173 2124 #endif /* __LINUX_KVM_H */
+78 -19
tools/testing/selftests/kvm/s390x/memop.c
··· 14 14 15 15 #include "test_util.h" 16 16 #include "kvm_util.h" 17 + #include "kselftest.h" 17 18 18 19 enum mop_target { 19 20 LOGICAL, ··· 692 691 kvm_vm_free(t.kvm_vm); 693 692 } 694 693 694 + struct testdef { 695 + const char *name; 696 + void (*test)(void); 697 + int extension; 698 + } testlist[] = { 699 + { 700 + .name = "simple copy", 701 + .test = test_copy, 702 + }, 703 + { 704 + .name = "generic error checks", 705 + .test = test_errors, 706 + }, 707 + { 708 + .name = "copy with storage keys", 709 + .test = test_copy_key, 710 + .extension = 1, 711 + }, 712 + { 713 + .name = "copy with key storage protection override", 714 + .test = test_copy_key_storage_prot_override, 715 + .extension = 1, 716 + }, 717 + { 718 + .name = "copy with key fetch protection", 719 + .test = test_copy_key_fetch_prot, 720 + .extension = 1, 721 + }, 722 + { 723 + .name = "copy with key fetch protection override", 724 + .test = test_copy_key_fetch_prot_override, 725 + .extension = 1, 726 + }, 727 + { 728 + .name = "error checks with key", 729 + .test = test_errors_key, 730 + .extension = 1, 731 + }, 732 + { 733 + .name = "termination", 734 + .test = test_termination, 735 + .extension = 1, 736 + }, 737 + { 738 + .name = "error checks with key storage protection override", 739 + .test = test_errors_key_storage_prot_override, 740 + .extension = 1, 741 + }, 742 + { 743 + .name = "error checks without key fetch prot override", 744 + .test = test_errors_key_fetch_prot_override_not_enabled, 745 + .extension = 1, 746 + }, 747 + { 748 + .name = "error checks with key fetch prot override", 749 + .test = test_errors_key_fetch_prot_override_enabled, 750 + .extension = 1, 751 + }, 752 + }; 753 + 695 754 int main(int argc, char *argv[]) 696 755 { 697 - int memop_cap, extension_cap; 756 + int memop_cap, extension_cap, idx; 698 757 699 758 setbuf(stdout, NULL); /* Tell stdout not to buffer its content */ 759 + 760 + ksft_print_header(); 700 761 701 762 memop_cap = kvm_check_cap(KVM_CAP_S390_MEM_OP); 702 763 extension_cap = kvm_check_cap(KVM_CAP_S390_MEM_OP_EXTENSION); 703 764 if (!memop_cap) { 704 - print_skip("CAP_S390_MEM_OP not supported"); 705 - exit(KSFT_SKIP); 765 + ksft_exit_skip("CAP_S390_MEM_OP not supported.\n"); 706 766 } 707 767 708 - test_copy(); 709 - if (extension_cap > 0) { 710 - test_copy_key(); 711 - test_copy_key_storage_prot_override(); 712 - test_copy_key_fetch_prot(); 713 - test_copy_key_fetch_prot_override(); 714 - test_errors_key(); 715 - test_termination(); 716 - test_errors_key_storage_prot_override(); 717 - test_errors_key_fetch_prot_override_not_enabled(); 718 - test_errors_key_fetch_prot_override_enabled(); 719 - } else { 720 - print_skip("storage key memop extension not supported"); 721 - } 722 - test_errors(); 768 + ksft_set_plan(ARRAY_SIZE(testlist)); 723 769 724 - return 0; 770 + for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) { 771 + if (testlist[idx].extension >= extension_cap) { 772 + testlist[idx].test(); 773 + ksft_test_result_pass("%s\n", testlist[idx].name); 774 + } else { 775 + ksft_test_result_skip("%s - extension level %d not supported\n", 776 + testlist[idx].name, 777 + testlist[idx].extension); 778 + } 779 + } 780 + 781 + ksft_finished(); /* Print results and exit() accordingly */ 725 782 }
+30 -8
tools/testing/selftests/kvm/s390x/resets.c
··· 12 12 13 13 #include "test_util.h" 14 14 #include "kvm_util.h" 15 + #include "kselftest.h" 15 16 16 17 #define VCPU_ID 3 17 18 #define LOCAL_IRQS 32 ··· 203 202 204 203 static void test_normal(void) 205 204 { 206 - pr_info("Testing normal reset\n"); 205 + ksft_print_msg("Testing normal reset\n"); 207 206 /* Create VM */ 208 207 vm = vm_create_default(VCPU_ID, 0, guest_code_initial); 209 208 run = vcpu_state(vm, VCPU_ID); ··· 226 225 227 226 static void test_initial(void) 228 227 { 229 - pr_info("Testing initial reset\n"); 228 + ksft_print_msg("Testing initial reset\n"); 230 229 vm = vm_create_default(VCPU_ID, 0, guest_code_initial); 231 230 run = vcpu_state(vm, VCPU_ID); 232 231 sync_regs = &run->s.regs; ··· 248 247 249 248 static void test_clear(void) 250 249 { 251 - pr_info("Testing clear reset\n"); 250 + ksft_print_msg("Testing clear reset\n"); 252 251 vm = vm_create_default(VCPU_ID, 0, guest_code_initial); 253 252 run = vcpu_state(vm, VCPU_ID); 254 253 sync_regs = &run->s.regs; ··· 267 266 kvm_vm_free(vm); 268 267 } 269 268 269 + struct testdef { 270 + const char *name; 271 + void (*test)(void); 272 + bool needs_cap; 273 + } testlist[] = { 274 + { "initial", test_initial, false }, 275 + { "normal", test_normal, true }, 276 + { "clear", test_clear, true }, 277 + }; 278 + 270 279 int main(int argc, char *argv[]) 271 280 { 281 + bool has_s390_vcpu_resets = kvm_check_cap(KVM_CAP_S390_VCPU_RESETS); 282 + int idx; 283 + 272 284 setbuf(stdout, NULL); /* Tell stdout not to buffer its content */ 273 285 274 - test_initial(); 275 - if (kvm_check_cap(KVM_CAP_S390_VCPU_RESETS)) { 276 - test_normal(); 277 - test_clear(); 286 + ksft_print_header(); 287 + ksft_set_plan(ARRAY_SIZE(testlist)); 288 + 289 + for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) { 290 + if (!testlist[idx].needs_cap || has_s390_vcpu_resets) { 291 + testlist[idx].test(); 292 + ksft_test_result_pass("%s\n", testlist[idx].name); 293 + } else { 294 + ksft_test_result_skip("%s - no VCPU_RESETS capability\n", 295 + testlist[idx].name); 296 + } 278 297 } 279 - return 0; 298 + 299 + ksft_finished(); /* Print results and exit() accordingly */ 280 300 }
+66 -21
tools/testing/selftests/kvm/s390x/sync_regs_test.c
··· 21 21 #include "test_util.h" 22 22 #include "kvm_util.h" 23 23 #include "diag318_test_handler.h" 24 + #include "kselftest.h" 24 25 25 26 #define VCPU_ID 5 26 27 ··· 75 74 #define TEST_SYNC_FIELDS (KVM_SYNC_GPRS|KVM_SYNC_ACRS|KVM_SYNC_CRS|KVM_SYNC_DIAG318) 76 75 #define INVALID_SYNC_FIELD 0x80000000 77 76 78 - int main(int argc, char *argv[]) 77 + void test_read_invalid(struct kvm_vm *vm, struct kvm_run *run) 79 78 { 80 - struct kvm_vm *vm; 81 - struct kvm_run *run; 82 - struct kvm_regs regs; 83 - struct kvm_sregs sregs; 84 - int rv, cap; 85 - 86 - /* Tell stdout not to buffer its content */ 87 - setbuf(stdout, NULL); 88 - 89 - cap = kvm_check_cap(KVM_CAP_SYNC_REGS); 90 - if (!cap) { 91 - print_skip("CAP_SYNC_REGS not supported"); 92 - exit(KSFT_SKIP); 93 - } 94 - 95 - /* Create VM */ 96 - vm = vm_create_default(VCPU_ID, 0, guest_code); 97 - 98 - run = vcpu_state(vm, VCPU_ID); 79 + int rv; 99 80 100 81 /* Request reading invalid register set from VCPU. */ 101 82 run->kvm_valid_regs = INVALID_SYNC_FIELD; ··· 93 110 "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", 94 111 rv); 95 112 vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0; 113 + } 114 + 115 + void test_set_invalid(struct kvm_vm *vm, struct kvm_run *run) 116 + { 117 + int rv; 96 118 97 119 /* Request setting invalid register set into VCPU. */ 98 120 run->kvm_dirty_regs = INVALID_SYNC_FIELD; ··· 113 125 "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", 114 126 rv); 115 127 vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0; 128 + } 129 + 130 + void test_req_and_verify_all_valid_regs(struct kvm_vm *vm, struct kvm_run *run) 131 + { 132 + struct kvm_sregs sregs; 133 + struct kvm_regs regs; 134 + int rv; 116 135 117 136 /* Request and verify all valid register sets. */ 118 137 run->kvm_valid_regs = TEST_SYNC_FIELDS; ··· 141 146 142 147 vcpu_sregs_get(vm, VCPU_ID, &sregs); 143 148 compare_sregs(&sregs, &run->s.regs); 149 + } 150 + 151 + void test_set_and_verify_various_reg_values(struct kvm_vm *vm, struct kvm_run *run) 152 + { 153 + struct kvm_sregs sregs; 154 + struct kvm_regs regs; 155 + int rv; 144 156 145 157 /* Set and verify various register values */ 146 158 run->s.regs.gprs[11] = 0xBAD1DEA; ··· 182 180 183 181 vcpu_sregs_get(vm, VCPU_ID, &sregs); 184 182 compare_sregs(&sregs, &run->s.regs); 183 + } 184 + 185 + void test_clear_kvm_dirty_regs_bits(struct kvm_vm *vm, struct kvm_run *run) 186 + { 187 + int rv; 185 188 186 189 /* Clear kvm_dirty_regs bits, verify new s.regs values are 187 190 * overwritten with existing guest values. ··· 207 200 TEST_ASSERT(run->s.regs.diag318 != 0x4B1D, 208 201 "diag318 sync regs value incorrect 0x%llx.", 209 202 run->s.regs.diag318); 203 + } 204 + 205 + struct testdef { 206 + const char *name; 207 + void (*test)(struct kvm_vm *vm, struct kvm_run *run); 208 + } testlist[] = { 209 + { "read invalid", test_read_invalid }, 210 + { "set invalid", test_set_invalid }, 211 + { "request+verify all valid regs", test_req_and_verify_all_valid_regs }, 212 + { "set+verify various regs", test_set_and_verify_various_reg_values }, 213 + { "clear kvm_dirty_regs bits", test_clear_kvm_dirty_regs_bits }, 214 + }; 215 + 216 + int main(int argc, char *argv[]) 217 + { 218 + static struct kvm_run *run; 219 + static struct kvm_vm *vm; 220 + int idx; 221 + 222 + /* Tell stdout not to buffer its content */ 223 + setbuf(stdout, NULL); 224 + 225 + ksft_print_header(); 226 + 227 + if (!kvm_check_cap(KVM_CAP_SYNC_REGS)) 228 + ksft_exit_skip("CAP_SYNC_REGS not supported"); 229 + 230 + ksft_set_plan(ARRAY_SIZE(testlist)); 231 + 232 + /* Create VM */ 233 + vm = vm_create_default(VCPU_ID, 0, guest_code); 234 + 235 + run = vcpu_state(vm, VCPU_ID); 236 + 237 + for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) { 238 + testlist[idx].test(vm, run); 239 + ksft_test_result_pass("%s\n", testlist[idx].name); 240 + } 210 241 211 242 kvm_vm_free(vm); 212 243 213 - return 0; 244 + ksft_finished(); /* Print results and exit() accordingly */ 214 245 }
+24 -5
tools/testing/selftests/kvm/s390x/tprot.c
··· 8 8 #include <sys/mman.h> 9 9 #include "test_util.h" 10 10 #include "kvm_util.h" 11 + #include "kselftest.h" 11 12 12 13 #define PAGE_SHIFT 12 13 14 #define PAGE_SIZE (1 << PAGE_SHIFT) ··· 64 63 } 65 64 66 65 enum stage { 67 - STAGE_END, 68 66 STAGE_INIT_SIMPLE, 69 67 TEST_SIMPLE, 70 68 STAGE_INIT_FETCH_PROT_OVERRIDE, 71 69 TEST_FETCH_PROT_OVERRIDE, 72 70 TEST_STORAGE_PROT_OVERRIDE, 71 + STAGE_END /* must be the last entry (it's the amount of tests) */ 73 72 }; 74 73 75 74 struct test { ··· 183 182 GUEST_SYNC(perform_next_stage(&i, mapped_0)); 184 183 } 185 184 186 - #define HOST_SYNC(vmp, stage) \ 185 + #define HOST_SYNC_NO_TAP(vmp, stage) \ 187 186 ({ \ 188 187 struct kvm_vm *__vm = (vmp); \ 189 188 struct ucall uc; \ ··· 199 198 ASSERT_EQ(uc.args[1], __stage); \ 200 199 }) 201 200 201 + #define HOST_SYNC(vmp, stage) \ 202 + ({ \ 203 + HOST_SYNC_NO_TAP(vmp, stage); \ 204 + ksft_test_result_pass("" #stage "\n"); \ 205 + }) 206 + 202 207 int main(int argc, char *argv[]) 203 208 { 204 209 struct kvm_vm *vm; 205 210 struct kvm_run *run; 206 211 vm_vaddr_t guest_0_page; 212 + 213 + ksft_print_header(); 214 + ksft_set_plan(STAGE_END); 207 215 208 216 vm = vm_create_default(VCPU_ID, 0, guest_code); 209 217 run = vcpu_state(vm, VCPU_ID); ··· 222 212 HOST_SYNC(vm, TEST_SIMPLE); 223 213 224 214 guest_0_page = vm_vaddr_alloc(vm, PAGE_SIZE, 0); 225 - if (guest_0_page != 0) 226 - print_skip("Did not allocate page at 0 for fetch protection override tests"); 227 - HOST_SYNC(vm, STAGE_INIT_FETCH_PROT_OVERRIDE); 215 + if (guest_0_page != 0) { 216 + /* Use NO_TAP so we don't get a PASS print */ 217 + HOST_SYNC_NO_TAP(vm, STAGE_INIT_FETCH_PROT_OVERRIDE); 218 + ksft_test_result_skip("STAGE_INIT_FETCH_PROT_OVERRIDE - " 219 + "Did not allocate page at 0\n"); 220 + } else { 221 + HOST_SYNC(vm, STAGE_INIT_FETCH_PROT_OVERRIDE); 222 + } 228 223 if (guest_0_page == 0) 229 224 mprotect(addr_gva2hva(vm, (vm_vaddr_t)0), PAGE_SIZE, PROT_READ); 230 225 run->s.regs.crs[0] |= CR0_FETCH_PROTECTION_OVERRIDE; ··· 239 224 run->s.regs.crs[0] |= CR0_STORAGE_PROTECTION_OVERRIDE; 240 225 run->kvm_dirty_regs = KVM_SYNC_CRS; 241 226 HOST_SYNC(vm, TEST_STORAGE_PROT_OVERRIDE); 227 + 228 + kvm_vm_free(vm); 229 + 230 + ksft_finished(); /* Print results and exit() accordingly */ 242 231 }