9
9
*/
10
10
#include "kselftest_harness.h"
11
11
#include "kvm_util.h"
12
+ #include "processor.h"
13
+ #include "sie.h"
12
14
13
15
#include <linux/capability.h>
14
16
#include <linux/sizes.h>
15
17
18
+ #define VM_MEM_SIZE (4 * SZ_1M)
19
+
16
20
/* so directly declare capget to check caps without libcap */
17
21
int capget (cap_user_header_t header , cap_user_data_t data );
18
22
@@ -36,6 +40,133 @@ void require_ucontrol_admin(void)
36
40
TEST_REQUIRE (kvm_has_cap (KVM_CAP_S390_UCONTROL ));
37
41
}
38
42
43
+ FIXTURE (uc_kvm )
44
+ {
45
+ struct kvm_s390_sie_block * sie_block ;
46
+ struct kvm_run * run ;
47
+ uintptr_t base_gpa ;
48
+ uintptr_t code_gpa ;
49
+ uintptr_t base_hva ;
50
+ uintptr_t code_hva ;
51
+ int kvm_run_size ;
52
+ void * vm_mem ;
53
+ int vcpu_fd ;
54
+ int kvm_fd ;
55
+ int vm_fd ;
56
+ };
57
+
58
+ /**
59
+ * create VM with single vcpu, map kvm_run and SIE control block for easy access
60
+ */
61
+ FIXTURE_SETUP (uc_kvm )
62
+ {
63
+ struct kvm_s390_vm_cpu_processor info ;
64
+ int rc ;
65
+
66
+ require_ucontrol_admin ();
67
+
68
+ self -> kvm_fd = open_kvm_dev_path_or_exit ();
69
+ self -> vm_fd = ioctl (self -> kvm_fd , KVM_CREATE_VM , KVM_VM_S390_UCONTROL );
70
+ ASSERT_GE (self -> vm_fd , 0 );
71
+
72
+ kvm_device_attr_get (self -> vm_fd , KVM_S390_VM_CPU_MODEL ,
73
+ KVM_S390_VM_CPU_PROCESSOR , & info );
74
+ TH_LOG ("create VM 0x%llx" , info .cpuid );
75
+
76
+ self -> vcpu_fd = ioctl (self -> vm_fd , KVM_CREATE_VCPU , 0 );
77
+ ASSERT_GE (self -> vcpu_fd , 0 );
78
+
79
+ self -> kvm_run_size = ioctl (self -> kvm_fd , KVM_GET_VCPU_MMAP_SIZE , NULL );
80
+ ASSERT_GE (self -> kvm_run_size , sizeof (struct kvm_run ))
81
+ TH_LOG (KVM_IOCTL_ERROR (KVM_GET_VCPU_MMAP_SIZE , self -> kvm_run_size ));
82
+ self -> run = (struct kvm_run * )mmap (NULL , self -> kvm_run_size ,
83
+ PROT_READ | PROT_WRITE , MAP_SHARED , self -> vcpu_fd , 0 );
84
+ ASSERT_NE (self -> run , MAP_FAILED );
85
+ /**
86
+ * For virtual cpus that have been created with S390 user controlled
87
+ * virtual machines, the resulting vcpu fd can be memory mapped at page
88
+ * offset KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of
89
+ * the virtual cpu's hardware control block.
90
+ */
91
+ self -> sie_block = (struct kvm_s390_sie_block * )mmap (NULL , PAGE_SIZE ,
92
+ PROT_READ | PROT_WRITE , MAP_SHARED ,
93
+ self -> vcpu_fd , KVM_S390_SIE_PAGE_OFFSET << PAGE_SHIFT );
94
+ ASSERT_NE (self -> sie_block , MAP_FAILED );
95
+
96
+ TH_LOG ("VM created %p %p" , self -> run , self -> sie_block );
97
+
98
+ self -> base_gpa = 0 ;
99
+ self -> code_gpa = self -> base_gpa + (3 * SZ_1M );
100
+
101
+ self -> vm_mem = aligned_alloc (SZ_1M , VM_MEM_SIZE );
102
+ ASSERT_NE (NULL , self -> vm_mem ) TH_LOG ("malloc failed %u" , errno );
103
+ self -> base_hva = (uintptr_t )self -> vm_mem ;
104
+ self -> code_hva = self -> base_hva - self -> base_gpa + self -> code_gpa ;
105
+ struct kvm_s390_ucas_mapping map = {
106
+ .user_addr = self -> base_hva ,
107
+ .vcpu_addr = self -> base_gpa ,
108
+ .length = VM_MEM_SIZE ,
109
+ };
110
+ TH_LOG ("ucas map %p %p 0x%llx" ,
111
+ (void * )map .user_addr , (void * )map .vcpu_addr , map .length );
112
+ rc = ioctl (self -> vcpu_fd , KVM_S390_UCAS_MAP , & map );
113
+ ASSERT_EQ (0 , rc ) TH_LOG ("ucas map result %d not expected, %s" ,
114
+ rc , strerror (errno ));
115
+
116
+ TH_LOG ("page in %p" , (void * )self -> base_gpa );
117
+ rc = ioctl (self -> vcpu_fd , KVM_S390_VCPU_FAULT , self -> base_gpa );
118
+ ASSERT_EQ (0 , rc ) TH_LOG ("vcpu fault (%p) result %d not expected, %s" ,
119
+ (void * )self -> base_hva , rc , strerror (errno ));
120
+
121
+ self -> sie_block -> cpuflags &= ~CPUSTAT_STOPPED ;
122
+ }
123
+
124
+ FIXTURE_TEARDOWN (uc_kvm )
125
+ {
126
+ munmap (self -> sie_block , PAGE_SIZE );
127
+ munmap (self -> run , self -> kvm_run_size );
128
+ close (self -> vcpu_fd );
129
+ close (self -> vm_fd );
130
+ close (self -> kvm_fd );
131
+ free (self -> vm_mem );
132
+ }
133
+
134
+ TEST_F (uc_kvm , uc_sie_assertions )
135
+ {
136
+ /* assert interception of Code 08 (Program Interruption) is set */
137
+ EXPECT_EQ (0 , self -> sie_block -> ecb & ECB_SPECI );
138
+ }
139
+
140
+ TEST_F (uc_kvm , uc_attr_mem_limit )
141
+ {
142
+ u64 limit ;
143
+ struct kvm_device_attr attr = {
144
+ .group = KVM_S390_VM_MEM_CTRL ,
145
+ .attr = KVM_S390_VM_MEM_LIMIT_SIZE ,
146
+ .addr = (unsigned long )& limit ,
147
+ };
148
+ int rc ;
149
+
150
+ rc = ioctl (self -> vm_fd , KVM_GET_DEVICE_ATTR , & attr );
151
+ EXPECT_EQ (0 , rc );
152
+ EXPECT_EQ (~0UL , limit );
153
+
154
+ /* assert set not supported */
155
+ rc = ioctl (self -> vm_fd , KVM_SET_DEVICE_ATTR , & attr );
156
+ EXPECT_EQ (-1 , rc );
157
+ EXPECT_EQ (EINVAL , errno );
158
+ }
159
+
160
+ TEST_F (uc_kvm , uc_no_dirty_log )
161
+ {
162
+ struct kvm_dirty_log dlog ;
163
+ int rc ;
164
+
165
+ rc = ioctl (self -> vm_fd , KVM_GET_DIRTY_LOG , & dlog );
166
+ EXPECT_EQ (-1 , rc );
167
+ EXPECT_EQ (EINVAL , errno );
168
+ }
169
+
39
170
/**
40
171
* Assert HPAGE CAP cannot be enabled on UCONTROL VM
41
172
*/
0 commit comments