Skip to content

Commit 11eedbb

Browse files
Kevin Stefanovjbeulich
authored andcommitted
tools/libxl: Correctly align the ACPI tables
The memory allocator currently calculates alignment in libxl's virtual address space, rather than guest physical address space. This results in the FACS being commonly misaligned. Furthermore, the allocator has several other bugs. The opencoded align-up calculation is currently susceptible to a bug that occurs in the corner case that the buffer is already aligned to begin with. In that case, an align-sized memory hole is introduced. The while loop is dead logic because its effects are entirely and unconditionally overwritten immediately after it. Rework the memory allocator to align in guest physical address space instead of libxl's virtual memory and improve the calculation, drop errant extra page in allocated buffer for ACPI tables, and give some of the variables better names/types. Fixes: 14c0d32 ("libxl/acpi: Build ACPI tables for HVMlite guests") Signed-off-by: Kevin Stefanov <[email protected]> Reviewed-by: Jan Beulich <[email protected]> Acked-by: Ian Jackson <[email protected]> master commit: dd6c062 master date: 2021-09-24 11:07:50 +0100
1 parent 124b801 commit 11eedbb

File tree

1 file changed

+19
-30
lines changed

1 file changed

+19
-30
lines changed

tools/libs/light/libxl_x86_acpi.c

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
/* Number of pages holding ACPI tables */
2222
#define NUM_ACPI_PAGES 16
23+
#define ALIGN(p, a) (((p) + ((a) - 1)) & ~((a) - 1))
2324

2425
struct libxl_acpi_ctxt {
2526
struct acpi_ctxt c;
@@ -28,10 +29,10 @@ struct libxl_acpi_ctxt {
2829
unsigned int page_shift;
2930

3031
/* Memory allocator */
31-
unsigned long alloc_base_paddr;
32-
unsigned long alloc_base_vaddr;
33-
unsigned long alloc_currp;
34-
unsigned long alloc_end;
32+
unsigned long guest_start;
33+
unsigned long guest_curr;
34+
unsigned long guest_end;
35+
void *buf;
3536
};
3637

3738
extern const unsigned char dsdt_pvh[];
@@ -43,8 +44,7 @@ static unsigned long virt_to_phys(struct acpi_ctxt *ctxt, void *v)
4344
struct libxl_acpi_ctxt *libxl_ctxt =
4445
CONTAINER_OF(ctxt, struct libxl_acpi_ctxt, c);
4546

46-
return (((unsigned long)v - libxl_ctxt->alloc_base_vaddr) +
47-
libxl_ctxt->alloc_base_paddr);
47+
return libxl_ctxt->guest_start + (v - libxl_ctxt->buf);
4848
}
4949

5050
static void *mem_alloc(struct acpi_ctxt *ctxt,
@@ -58,20 +58,16 @@ static void *mem_alloc(struct acpi_ctxt *ctxt,
5858
if (align < 16)
5959
align = 16;
6060

61-
s = (libxl_ctxt->alloc_currp + align) & ~((unsigned long)align - 1);
61+
s = ALIGN(libxl_ctxt->guest_curr, align);
6262
e = s + size - 1;
6363

6464
/* TODO: Reallocate memory */
65-
if ((e < s) || (e >= libxl_ctxt->alloc_end))
65+
if ((e < s) || (e >= libxl_ctxt->guest_end))
6666
return NULL;
6767

68-
while (libxl_ctxt->alloc_currp >> libxl_ctxt->page_shift !=
69-
e >> libxl_ctxt->page_shift)
70-
libxl_ctxt->alloc_currp += libxl_ctxt->page_size;
68+
libxl_ctxt->guest_curr = e;
7169

72-
libxl_ctxt->alloc_currp = e;
73-
74-
return (void *)s;
70+
return libxl_ctxt->buf + (s - libxl_ctxt->guest_start);
7571
}
7672

7773
static void acpi_mem_free(struct acpi_ctxt *ctxt,
@@ -163,15 +159,12 @@ int libxl__dom_load_acpi(libxl__gc *gc,
163159
struct acpi_config config = {0};
164160
struct libxl_acpi_ctxt libxl_ctxt;
165161
int rc = 0, acpi_pages_num;
166-
void *acpi_pages;
167-
unsigned long page_mask;
168162

169163
if (b_info->type != LIBXL_DOMAIN_TYPE_PVH)
170164
goto out;
171165

172166
libxl_ctxt.page_size = XC_DOM_PAGE_SIZE(dom);
173167
libxl_ctxt.page_shift = XC_DOM_PAGE_SHIFT(dom);
174-
page_mask = (1UL << libxl_ctxt.page_shift) - 1;
175168

176169
libxl_ctxt.c.mem_ops.alloc = mem_alloc;
177170
libxl_ctxt.c.mem_ops.v2p = virt_to_phys;
@@ -186,19 +179,17 @@ int libxl__dom_load_acpi(libxl__gc *gc,
186179
config.rsdp = (unsigned long)libxl__malloc(gc, libxl_ctxt.page_size);
187180
config.infop = (unsigned long)libxl__malloc(gc, libxl_ctxt.page_size);
188181
/* Pages to hold ACPI tables */
189-
acpi_pages = libxl__malloc(gc, (NUM_ACPI_PAGES + 1) *
190-
libxl_ctxt.page_size);
182+
libxl_ctxt.buf = libxl__malloc(gc, NUM_ACPI_PAGES *
183+
libxl_ctxt.page_size);
191184

192185
/*
193186
* Set up allocator memory.
194187
* Start next to acpi_info page to avoid fracturing e820.
195188
*/
196-
libxl_ctxt.alloc_base_paddr = ACPI_INFO_PHYSICAL_ADDRESS +
197-
libxl_ctxt.page_size;
198-
libxl_ctxt.alloc_base_vaddr = libxl_ctxt.alloc_currp =
199-
(unsigned long)acpi_pages;
200-
libxl_ctxt.alloc_end = (unsigned long)acpi_pages +
201-
(NUM_ACPI_PAGES * libxl_ctxt.page_size);
189+
libxl_ctxt.guest_start = libxl_ctxt.guest_curr = libxl_ctxt.guest_end =
190+
ACPI_INFO_PHYSICAL_ADDRESS + libxl_ctxt.page_size;
191+
192+
libxl_ctxt.guest_end += NUM_ACPI_PAGES * libxl_ctxt.page_size;
202193

203194
/* Build the tables. */
204195
rc = acpi_build_tables(&libxl_ctxt.c, &config);
@@ -208,10 +199,8 @@ int libxl__dom_load_acpi(libxl__gc *gc,
208199
}
209200

210201
/* Calculate how many pages are needed for the tables. */
211-
acpi_pages_num =
212-
((libxl_ctxt.alloc_currp - (unsigned long)acpi_pages)
213-
>> libxl_ctxt.page_shift) +
214-
((libxl_ctxt.alloc_currp & page_mask) ? 1 : 0);
202+
acpi_pages_num = (ALIGN(libxl_ctxt.guest_curr, libxl_ctxt.page_size) -
203+
libxl_ctxt.guest_start) >> libxl_ctxt.page_shift;
215204

216205
dom->acpi_modules[0].data = (void *)config.rsdp;
217206
dom->acpi_modules[0].length = 64;
@@ -231,7 +220,7 @@ int libxl__dom_load_acpi(libxl__gc *gc,
231220
dom->acpi_modules[1].length = 4096;
232221
dom->acpi_modules[1].guest_addr_out = ACPI_INFO_PHYSICAL_ADDRESS;
233222

234-
dom->acpi_modules[2].data = acpi_pages;
223+
dom->acpi_modules[2].data = libxl_ctxt.buf;
235224
dom->acpi_modules[2].length = acpi_pages_num << libxl_ctxt.page_shift;
236225
dom->acpi_modules[2].guest_addr_out = ACPI_INFO_PHYSICAL_ADDRESS +
237226
libxl_ctxt.page_size;

0 commit comments

Comments
 (0)