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 <[email protected]>
---
hypervisor/arch/x86/vtd.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c
index 34daa7fd..acaf0e03 100644
--- a/hypervisor/arch/x86/vtd.c
+++ b/hypervisor/arch/x86/vtd.c
@@ -411,7 +411,7 @@ static int vtd_emulate_qi_request(unsigned int unit_no,
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) {
@@ -437,13 +437,14 @@ static int vtd_emulate_qi_request(unsigned int unit_no,
!(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;
}
--
2.16.4
--
You received this message because you are subscribed to the Google Groups
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.