|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 4/4] arm/mem_access: Add software guest-page-table walk
Hi Sergej, On 30/04/17 20:48, Sergej Proskurin wrote: I don't think this function belongs to mem_access.c. It would be better in p2m.c. Also, the name is a bit confusing, a user would not know the difference between p2m_gva_to_ipa and gva_to_ipa. Coding style level = 0. Also please use unsigned int for level. t0_sz and t1_sz should be stay signed. + unsigned long t0_max, t1_min; + lpae_t pte, *table; + mfn_t root_mfn; + uint64_t ttbr; + uint32_t sctlr = READ_SYSREG(SCTLR_EL1); + register_t ttbcr = READ_SYSREG(TCR_EL1); So you are assuming that the current vCPU is running, right? If so, this should be clarified in the commit message and in a comment above the function. Also s/ttbcr/tcr/ Offsets are based on the granularity of Xen (currently 4KB). However the guests can support 4KB, 16KB, 64KB. Please handle everything correctly. Debian ARM 32bit is using short-descriptor translation table. So are you suggesting that memaccess will not correctly with Debian guest? + if ( !(ttbcr & TTBCR_EAE) ) See my comment on patch #2 about the naming convention. + return -EFAULT; + +#ifdef CONFIG_ARM_64 + level = 1; This sounds wrong to me. The first lookup level is determined by the value of T0SZ and T1SZ (see B3-1352 in ARM DDI 0406C.c). For the AArch64 version see D4.2.5 in ARM DDI 0487A.k_iss10775. See my comment on patch #2 for the naming convention. + t0_max = (1U << (32 - t0_sz)) - 1; + + /* Get the min GVA that can be translated by TTBR1. */ + t1_sz = (ttbcr >> TCR_T1SZ_SHIFT) & TTBCR_SZ_MASK; + t1_min = ~0U - (1U << (32 - t1_sz)) + 1; 1U << (32 - t1_sz) will not fit in an unsigned long if t1_sz = 0.Also, this code looks wrong to me. Looking at B3.6.4 in DDI 0406C.c, you don't handle properly t0_max and t1_min when T0SZ or T1SZ is 0. I think it would be worth for you to have a look to the pseudo-code in the ARM ARM for TranslationTableWalk (see B3.19.3 in ARM DDI 0406C.c and J1-5295 in ARM DDI 0487A.k_iss10775) which gives you all the details for doing properly translation table walk. + } + + if ( t0_max >= gva ) + /* Use TTBR0 for GVA to IPA translation. */ + ttbr = READ_SYSREG64(TTBR0_EL1); + else if ( t1_min <= gva ) + /* Use TTBR1 for GVA to IPA translation. */ + ttbr = READ_SYSREG64(TTBR1_EL1); + else + /* GVA out of bounds of TTBR(0|1). */ + return -EFAULT; + + /* Bits [63..48] might be used by an ASID. */ + root_mfn = p2m_lookup(d, _gfn(paddr_to_pfn(ttbr & ((1ULL<<48)-1))), NULL); Please don't hardcode the mask. + + /* Check, whether TTBR holds a valid address. */ + if ( mfn_eq(root_mfn, INVALID_MFN) ) + return -EFAULT; + + table = map_domain_page(root_mfn); Nothing prevents the guest to give back the page table whilst you browsing it. You may want to have a look to patch "ARM: introduce vgic_access_guest_memory()" [1] to generalize the function and avoid re-inventing the wheel. You likely want to use ACCESS_ONCE here to prevent the compiler to read the pte twice from the memory. + + if ( level == 3 || !pte.walk.valid || !pte.walk.table ) + break; + + unmap_domain_page(table); + + root_mfn = p2m_lookup(d, _gfn(pte.walk.base), NULL); No check on root_mfn? + table = map_domain_page(root_mfn); + } + + unmap_domain_page(table); + + if ( !pte.walk.valid ) + return -EFAULT; + + /* Make sure the entry holds the requested access attributes. */ + if ( ((flags & GV2M_WRITE) == GV2M_WRITE) && pte.pt.ro ) + return -EFAULT; IHMO, this function should return the access attribute of the page and let the caller decides what to do. This would make this function more generic. Why this ASSERT has been added? Rather falling back, why don't we do software page table walk every time? Cheers, [1] https://patchwork.kernel.org/patch/9676291/ -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |