@@ -1063,8 +1063,23 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
prot = full->prot;
asidx = cpu_asidx_from_attrs(cpu, full->attrs);
- section = address_space_translate_for_iotlb(cpu, asidx, paddr_page,
+ section = address_space_translate_for_iotlb(cpu, asidx, full->phys_addr,
&xlat, &sz, full->attrs, &prot);
+ /* Update page size */
+ full->lg_page_size = ctz64(sz);
+ if (full->lg_page_size > TARGET_PAGE_BITS) {
+ full->lg_page_size = TARGET_PAGE_BITS;
+ } else {
+ sz = TARGET_PAGE_SIZE;
+ }
+
+ is_ram = memory_region_is_ram(section->mr);
+ is_romd = memory_region_is_romd(section->mr);
+ /* If the translated mr is ram/rom, make xlat align the TARGET_PAGE */
+ if (is_ram || is_romd) {
+ xlat &= TARGET_PAGE_MASK;
+ }
+
assert(sz >= TARGET_PAGE_SIZE);
tlb_debug("vaddr=%016" VADDR_PRIx " paddr=0x" HWADDR_FMT_plx
@@ -1077,9 +1092,6 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
read_flags |= TLB_INVALID_MASK;
}
- is_ram = memory_region_is_ram(section->mr);
- is_romd = memory_region_is_romd(section->mr);
-
if (is_ram || is_romd) {
/* RAM and ROMD both have associated host memory. */
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
@@ -702,6 +702,10 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr orig_addr,
iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, iommu_idx);
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask));
+ /* Update size */
+ if (iotlb.addr_mask != -1 && *plen > iotlb.addr_mask + 1) {
+ *plen = iotlb.addr_mask + 1;
+ }
/* Update the caller's prot bits to remove permissions the IOMMU
* is giving us a failure response for. If we get down to no
* permissions left at all we can give up now.