1 #include <err.h>
2 #include <errno.h>
3 #include <inttypes.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <sys/mman.h>
7
8 #include <xenctrl.h>
9 #include <xenforeignmemory.h>
10 #include <xengnttab.h>
11 #include <xen-tools/common-macros.h>
12
13 static unsigned int nr_failures;
14 #define fail(fmt, ...) \
15 ({ \
16 nr_failures++; \
17 (void)printf(fmt, ##__VA_ARGS__); \
18 })
19
20 static xc_interface *xch;
21 static uint32_t domid;
22
23 static struct xen_domctl_createdomain create = {
24 .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap,
25 .max_vcpus = 1,
26 .max_grant_frames = 1,
27 .grant_opts = XEN_DOMCTL_GRANT_version(1),
28
29 .arch = {
30 #if defined(__x86_64__) || defined(__i386__)
31 .emulation_flags = XEN_X86_EMU_LAPIC,
32 #endif
33 },
34 };
35
36 static uint64_t default_mempool_size_bytes =
37 #if defined(__x86_64__) || defined(__i386__)
38 256 << 12; /* Only x86 HAP for now. x86 Shadow needs more work. */
39 #elif defined (__arm__) || defined(__aarch64__)
40 16 << 12;
41 #endif
42
run_tests(void)43 static void run_tests(void)
44 {
45 xen_pfn_t physmap[] = { 0 };
46 uint64_t size_bytes, old_size_bytes;
47 int rc;
48
49 printf("Test default mempool size\n");
50
51 rc = xc_get_paging_mempool_size(xch, domid, &size_bytes);
52 if ( rc )
53 return fail(" Fail: get mempool size: %d - %s\n",
54 errno, strerror(errno));
55
56 printf("mempool size %"PRIu64" bytes (%"PRIu64"kB, %"PRIu64"MB)\n",
57 size_bytes, size_bytes >> 10, size_bytes >> 20);
58
59
60 /*
61 * Check that the domain has the expected default allocation size. This
62 * will fail if the logic in Xen is altered without an equivalent
63 * adjustment here.
64 */
65 if ( size_bytes != default_mempool_size_bytes )
66 return fail(" Fail: size %"PRIu64" != expected size %"PRIu64"\n",
67 size_bytes, default_mempool_size_bytes);
68
69
70 printf("Test that allocate doesn't alter pool size\n");
71
72 /*
73 * Populate the domain with some RAM. This will cause more of the mempool
74 * to be used.
75 */
76 old_size_bytes = size_bytes;
77
78 rc = xc_domain_setmaxmem(xch, domid, -1);
79 if ( rc )
80 return fail(" Fail: setmaxmem: : %d - %s\n",
81 errno, strerror(errno));
82
83 rc = xc_domain_populate_physmap_exact(xch, domid, 1, 0, 0, physmap);
84 if ( rc )
85 return fail(" Fail: populate physmap: %d - %s\n",
86 errno, strerror(errno));
87
88 /*
89 * Re-get the p2m size. Should not have changed as a consequence of
90 * populate physmap.
91 */
92 rc = xc_get_paging_mempool_size(xch, domid, &size_bytes);
93 if ( rc )
94 return fail(" Fail: get mempool size: %d - %s\n",
95 errno, strerror(errno));
96
97 if ( old_size_bytes != size_bytes )
98 return fail(" Fail: mempool size changed %"PRIu64" => %"PRIu64"\n",
99 old_size_bytes, size_bytes);
100
101
102
103 printf("Test bad set size\n");
104
105 /*
106 * Check that setting a non-page size results in failure.
107 */
108 rc = xc_set_paging_mempool_size(xch, domid, size_bytes + 1);
109 if ( rc != -1 || errno != EINVAL )
110 return fail(" Fail: Bad set size: expected -1/EINVAL, got %d/%d - %s\n",
111 rc, errno, strerror(errno));
112
113
114 printf("Test set continuation\n");
115
116 /*
117 * Check that setting a large P2M size succeeds. This is expecting to
118 * trigger continuations.
119 */
120 rc = xc_set_paging_mempool_size(xch, domid, 64 << 20);
121 if ( rc )
122 return fail(" Fail: Set size 64MB: %d - %s\n",
123 errno, strerror(errno));
124
125
126 /*
127 * Check that the reported size matches what set consumed.
128 */
129 rc = xc_get_paging_mempool_size(xch, domid, &size_bytes);
130 if ( rc )
131 return fail(" Fail: get p2m mempool size: %d - %s\n",
132 errno, strerror(errno));
133
134 if ( size_bytes != 64 << 20 )
135 return fail(" Fail: expected mempool size %u, got %"PRIu64"\n",
136 64 << 20, size_bytes);
137 }
138
main(int argc,char ** argv)139 int main(int argc, char **argv)
140 {
141 int rc;
142
143 printf("Paging mempool tests\n");
144
145 xch = xc_interface_open(NULL, NULL, 0);
146
147 if ( !xch )
148 err(1, "xc_interface_open");
149
150 rc = xc_domain_create(xch, &domid, &create);
151 if ( rc )
152 {
153 if ( errno == EINVAL || errno == EOPNOTSUPP )
154 printf(" Skip: %d - %s\n", errno, strerror(errno));
155 else
156 fail(" Domain create failure: %d - %s\n",
157 errno, strerror(errno));
158 goto out;
159 }
160
161 printf(" Created d%u\n", domid);
162
163 run_tests();
164
165 rc = xc_domain_destroy(xch, domid);
166 if ( rc )
167 fail(" Failed to destroy domain: %d - %s\n",
168 errno, strerror(errno));
169 out:
170 return !!nr_failures;
171 }
172
173 /*
174 * Local variables:
175 * mode: C
176 * c-file-style: "BSD"
177 * c-basic-offset: 4
178 * tab-width: 4
179 * indent-tabs-mode: nil
180 * End:
181 */
182