|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH v2 6/8] arm/mem_access: Add long-descriptor based gpt
Hi Sergej, On 06/01/2017 04:18 PM, Sergej Proskurin wrote: This commit adds functionality to walk the guest's page tables using the long-descriptor translation table format for both ARMv7 and ARMv8. Similar to the hardware architecture, the implementation supports different page granularities (4K, 16K, and 64K). The implementation is based on ARM DDI 0487A-g J11-5608, J11-5679, and ARM DDI 0406C-b B3-1510. Please use the most recent ARM ARM. Looking at the way you use t0_sz and t1_sz, they will never be < 0 so I thin should be unsigned. Also, I think disabled is always 0 or 1. If that is true, please use bool/true/false. Please define them as static. It is not necessary to have them on the stack everytime. Ditto. Ditto. Also, the stride can be found from the page shift. So I am not convinced you need that. + + t0_sz = (tcr >> TCR_T0SZ_SHIFT) & TCR_SZ_MASK; + t1_sz = (tcr >> TCR_T1SZ_SHIFT) & TCR_SZ_MASK; + + /* + * Get the MSB number of the gva, according to "AddrTop" pseudocode That's a call to have a separate helper for AddrTop rather than open-coding in this function. I think this function could be split in multiple part, making easier the review. For instance, you have a lot of "if is_*bit_domain". I think checking 32-bit EL0 is straigh-forward enough to get it done now. Have a look at psr_most_is_32bit.+ * implementation in ARM DDI 0487A-g J11-5739. + * + * XXX: We do not check whether the 64bit domain uses a 32-bit EL0. In this + * case, we need to set topbit to 31, as well. Please use BIT(...) instead of (1UL << ...). + (!(gva & (1UL << TCR_TB_55)) && (tcr & TCR_TBI0)) ) Ditto. + topbit = TCR_TB_55; This is really confusing. You define TCR_TB_* to * but it is not even part of the register TCR_. TBH, I don't think they hence the code and would just hardcoded the 55 here. Afterall it is in the name :). + else + topbit = TCR_TB_63 Ditto. Likely a comment is missing here to explain what you are doing below. My understand is you are selecting TTBR*_EL1. And looking at the code, this could be abstracted as both branches are nearly the same. + if ( (gva & (1UL << topbit)) == 0 ) BIT(...) like this could be simplified by using min/max. But I think we should bail out here. Likely something in the page table is wrong and ignoring is the worst thing to do. For instance ARMv8.2 has extended the input size to 52 bits. It would be difficult to catch what is missing because of that, not mentioning that the only caller today will be memaccess that is not enabled by default. + + /* Normalize granule size. */ I think 0, 1, 2 is more confusing to read. It would be better to use directly TCR_TG0_*. Coding style, the brace should be on a newline. + case TCR_TG0_16K: + gran = 1; + break; + case TCR_TG0_64K: + gran = 2; + break; + default: + gran = 0; + } > + + /* Use TTBR0 for GVA to IPA translation. */ + ttbr = READ_SYSREG64(TTBR0_EL1); + + /* If TCR.EPD0 is set, translations using TTBR0 are disabled. */ + disabled = ( tcr & TCR_EPD0 ) ? 1 : 0; disabled = !!(tcr & TCR_EPD0); or if you are using bool as requested above: disabled = tcr & TCR_EPD0; Coding style. If you shift your tcr by TCR_TG1_SHIFT then all this code can become generic. Avoiding duplication, reviewing twice similar code and potential bug.+ case TCR_TG1_16K: + gran = 1; + break; + case TCR_TG1_64K: + gran = 2; + break; + default: + gran = 0; + } + + /* Use TTBR1 for GVA to IPA translation. */ + ttbr = READ_SYSREG64(TTBR1_EL1); + + /* If TCR.EPD1 is set, translations using TTBR1 are disabled. */ + disabled = ( tcr & TCR_EPD1 ) ? 1 : 0; Same as above. NIT: It is not necessarily to mention ARMv7. ARMv7 is always AArch32. Also s/Aarch32/Aarch32/ + gran = 0; + + mask = ((1ULL << REGISTER_WIDTH_32_BIT) - 1) & + ~((1ULL << (REGISTER_WIDTH_32_BIT - t0_sz)) - 1); I don't understand this mask. Why do you need it? As for the AArch64, there is a call to abstract here. Ditto. + } + } + + if ( disabled ) + return -EFAULT; + + level = 4 - DIV_ROUND_UP((input_size - grainsizes[gran]), strides[gran]); It took me a bit to understand this. The comment in the ARM ARM pseudo-code would be useful to keep it here. + + /* XXX: We do not consider 32bit EL0 running on Aarch64, yet. */ See my comment above about 32bit EL0 support. Please comment this line. + break; + + page = get_page_from_gfn(d, pte.walk.base, NULL, P2M_ALLOC); It is a bit confusing. You care about the output_size for the when getting the TBBR but not the rest of the tables. Is it normal? + if ( !page ) + return -EFAULT; + + table = __map_domain_page(page); + } + + if ( !pte.walk.valid || ((level == 3) & !pte.walk.table) ) There is a call to leverage the p2m_table/p2m_valid helpers here. + return -EFAULT; + + *ipa = pfn_to_paddr(pte.walk.base) | (gva & masks[level][gran]); + + *perm_ro = pte.pt.ro; + + /* Return the entire pte so that the caller can check flags by herself. */ Hmmm? You don't return the entire pte but the only whether the page is writable or readable-only. In general we want to have more information back such as execute-never bit... + return 0; }int p2m_walk_gpt(struct p2m_domain *p2m, vaddr_t gva, Cheers, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |