summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3a4f417)
raw | patch | inline | side by side (parent: 3a4f417)
author | Jan Kiszka <jan.kiszka@siemens.com> | |
Sun, 27 Jan 2019 14:23:50 +0000 (15:23 +0100) | ||
committer | Jan Kiszka <jan.kiszka@siemens.com> | |
Sun, 27 Jan 2019 14:33:39 +0000 (15:33 +0100) |
If the guest sets the wait request status address to the top of the
page, we crossed the border to the next page and either wrote some bytes
into a guest page that was previously mapped at page 2 in the temporary
mapping range, or we crashed the hypervisor on a fault if nothing was
mapped before.
Fix this by masking out the two lowest bits of the status address which
are actually reserved according to the Intel manual.
Along that, replace the hard-coded shift value with the right symbolic
constant.
Fixes: 20b09b8625d5 ("x86: Emulate interrupt remapping support to enable x2APIC usage")
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
page, we crossed the border to the next page and either wrote some bytes
into a guest page that was previously mapped at page 2 in the temporary
mapping range, or we crashed the hypervisor on a fault if nothing was
mapped before.
Fix this by masking out the two lowest bits of the status address which
are actually reserved according to the Intel manual.
Along that, replace the hard-coded shift value with the right symbolic
constant.
Fixes: 20b09b8625d5 ("x86: Emulate interrupt remapping support to enable x2APIC usage")
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/x86/vtd.c | patch | blob | history |
index 34daa7fd8349ff08ccb7220fe3da864c9cbff816..acaf0e0356afb4efd454f099d7ca65fd47f80fa4 100644 (file)
struct vtd_entry inv_desc)
{
unsigned int start, count, n;
- void *status_page;
+ void *status_addr;
int result;
switch (inv_desc.lo_word & VTD_REQ_INV_MASK) {
!(inv_desc.lo_word & VTD_INV_WAIT_SW))
return -EINVAL;
- status_page = paging_get_guest_pages(NULL, inv_desc.hi_word, 1,
+ status_addr = paging_get_guest_pages(NULL, inv_desc.hi_word, 1,
PAGE_DEFAULT_FLAGS);
- if (!status_page)
+ if (!status_addr)
return -EINVAL;
- *(u32 *)(status_page + (inv_desc.hi_word & ~PAGE_MASK)) =
- inv_desc.lo_word >> 32;
+ status_addr += inv_desc.hi_word & PAGE_OFFS_MASK & ~3;
+ *(u32 *)status_addr =
+ inv_desc.lo_word >> VTD_INV_WAIT_SDATA_SHIFT;
return 0;
}