Fix two issues related to leaf address lookups in VT-d:
* When translating an address that falls inside of a superpage in the
IOMMU page tables the fetching of the PTE value wasn't masking of the
contiguous related data, which caused the returned data to be
corrupt as it would contain bits that the caller would interpret as
part of the address.
* When the requested leaf address wasn't mapped by a superpage the
returned value wouldn't have any of the low 12 bits set, thus missing
the permission bits expected by the caller.
Take the opportunity to also adjust the function comment to note that
when returning the full PTE the bits above PADDR_BITS are removed.
Fixes: c71e55501a61 ('VT-d: have callers specify the target level for page table walks')
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
* failure,
* - for target > 0 the physical address of the page table holding the leaf
* PTE for the requested address,
- * - for target == 0 the full PTE.
+ * - for target == 0 the full PTE contents below PADDR_BITS limit.
*/
static uint64_t addr_to_dma_page_maddr(struct domain *domain, daddr_t addr,
unsigned int target,
* with the address adjusted to account for the residual of
* the walk.
*/
- pte_maddr = pte->val +
+ pte_maddr = (pte->val & PADDR_MASK) +
(addr & ((1UL << level_to_offset_bits(level)) - 1) &
PAGE_MASK);
if ( !target )
}
if ( --level == target )
+ {
+ if ( !target )
+ pte_maddr = pte->val & PADDR_MASK;
break;
+ }
unmap_vtd_domain_page(parent);
parent = map_vtd_domain_page(pte_maddr);