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