[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC 9/9] xen: arm: support for up to 48-bit IPA addressing on arm64
Hi Ian, On 07/30/2014 02:47 PM, Ian Campbell wrote: > Currently we support only 40-bits. This is insufficient on systems where > peripherals which need to be 1:1 mapped to dom0 are above the 40-bit limit. > > Unfortunately the hardware requirements are such that this means that the > number of levels in the P2M is not static and must vary with the number of > implemented physical address bits. This is described in ARM DDI 0487A.b Table > D4-5. In short there is no single p2m configuration which supports everything > from 40- to 48- bits. > > For example a system which supports up to 40-bit addressing will only support > 3 > level p2m (maximum SL0 is 1 == 3 levels), requiring a concatenated page table > root consisting of two pages to make the full 40-bits of addressing. > > A maximum of 16 pages can be concatenated meaning that a 3 level p2m can only > support up to 43-bit addreses. Therefore support for 48-bit addressing requres s/addreses/addresses/ s/requres/requires/ > SL0==2 (4 levels of paging). > > After the previous patches our various p2m lookup and manipulation functions > already support starting at arbitrary level and with arbitrary root > concatenation. All that remains is to determine the correct settings from > ID_AA64MMFR0_EL1.PARange for which we use a lookup table. > > As well as supporting 44 and 48 bit addressing we can also reduce the order of > the first level for systems which support only 32 or 36 physical address bits, > saving a page. > > Systems with 42-bits are an interesting case, since they only support 3 levels > of paging, implying that 8 pages are required at the root level. So far I am > not aware of any systems with peripheral located so high up (the only 42-bit > system I've seen has nothing above 40-bits), so such systems remain configured > for 40-bit IPA with a pair of pages at the root of the p2m. > > Switching to synbolic names for the VTCR_EL2 bits as we go improves the > clarity s/synbolic/symbolic/ > of the result. > > Parts of this are derived from "xen/arm: Add 4-level page table for > stage 2 translation" by Vijaya Kumar K. > > arm32 remains with the static 3-level, 2 page root configuration. > > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > --- > xen/arch/arm/p2m.c | 82 > +++++++++++++++++++++++++++++++-------- > xen/include/asm-arm/p2m.h | 2 +- > xen/include/asm-arm/processor.h | 28 +++++++++++++ > 3 files changed, 94 insertions(+), 18 deletions(-) > > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c > index e9938ae..0e8e8e0 100644 > --- a/xen/arch/arm/p2m.c > +++ b/xen/arch/arm/p2m.c > @@ -11,10 +11,17 @@ > #include <asm/hardirq.h> > #include <asm/page.h> > > -#define P2M_ROOT_LEVEL 1 > +#ifdef CONFIG_ARM_64 > +static int __read_mostly p2m_root_order; unsigned int? It might even be better to use uint8_t as we won't never have an order greater than 256. Even though I'm not sure if it will improve performance. > +static int __read_mostly p2m_root_level; same here. > +#define P2M_ROOT_ORDER p2m_root_order > +#define P2M_ROOT_LEVEL p2m_root_level > +#else > +/* First level P2M is alway 2 consecutive pages */ > +#define P2M_ROOT_LEVEL 1 > +#define P2M_ROOT_ORDER 1 > +#endif > > -/* First level P2M is 2 consecutive pages */ > -#define P2M_ROOT_ORDER 1 > #define P2M_ROOT_PAGES (1<<P2M_ROOT_ORDER) > > static bool_t p2m_valid(lpae_t pte) > @@ -164,6 +171,8 @@ paddr_t p2m_lookup(struct domain *d, paddr_t paddr, > p2m_type_t *t) > > map = __map_domain_page(p2m->root + root_table); > > + BUG_ON(P2M_ROOT_LEVEL >= 4); > + For ARM64, P2M_ROOT_LEVEL is set up once at startup and AFAIU should not change. Using BUG_ON seem excessive here. If you want to keep a test, I would use ASSERT to avoid impacting hypervisor in production mode. > for ( level = P2M_ROOT_LEVEL ; level < 4 ; level++ ) > { > mask = masks[level]; > @@ -883,6 +892,7 @@ int p2m_alloc_table(struct domain *d) > { > struct p2m_domain *p2m = &d->arch.p2m; > struct page_info *page; > + int i; unsigned int. [..] > #ifdef CONFIG_ARM_32 > - val = 0x80003558; > -#else > - val = 0x80023558; > + printk("P2M: 40-bit IPA\n"); > + val |= VTCR_T0SZ(0x18); /* 40 bit IPA */ > +#else /* CONFIG_ARM_64 */ > + const struct { > + unsigned pabits; /* Physical Address Size */ missing the unsigned int by mistake? Or maybe uint8_t. > + unsigned t0sz; /* Desired T0SZ, minimum in comment */ > + unsigned root_order; /* Page order of the root of the p2m */ > + unsigned sl0; /* Desired SL0, maximum in comment */ > + } pa_range_info[] = { > + /* T0SZ minimum and SL0 maximum from ARM DDI 0487A.b Table D4-5 */ > + /* PA size, t0sz(min), root-order, sl0(max) */ > + [0] = { 32, 32/*32*/, 0, 1 }, > + [1] = { 36, 28/*28*/, 0, 1 }, > + [2] = { 40, 24/*24*/, 1, 1 }, > + [3] = { 42, 24/*22*/, 1, 1 }, > + [4] = { 44, 20/*20*/, 0, 2 }, > + [5] = { 48, 16/*16*/, 0, 2 }, > + [6] = { 0 }, /* Invalid */ > + [7] = { 0 } /* Invalid */ > + }; > + > + int cpu; unsigned int > + int pa_range = 0x10; /* Larger than any possible value */ same here. > + > + for_each_online_cpu ( cpu ) > + { > + struct cpuinfo_arm *info = &cpu_data[cpu]; > + if ( info->mm64.pa_range < pa_range ) > + pa_range = info->mm64.pa_range; > + } > + > + /* pa_range is 4 bits, but the defined encodings are only 3 bits */ > + if ( pa_range&0x8 || !pa_range_info[pa_range].pabits ) I think a space is missing around & for clarity. > + panic("Unknown encoding of ID_AA64MMFR0_EL1.PARange %x\n", pa_range); > + > + val |= VTCR_PS(pa_range); > + val |= VTCR_TG0_4K; > + val |= VTCR_SL0(pa_range_info[pa_range].sl0); > + val |= VTCR_T0SZ(pa_range_info[pa_range].t0sz); > + > + p2m_root_order = pa_range_info[pa_range].root_order; > + p2m_root_level = 2 - pa_range_info[pa_range].sl0; Following my comment on BUG_ON earlier, I think you should check that we correctly support the values set in p2m_root_{order,level} and bail out if necessary. [..] > diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h > index 979a41d..a744a67 100644 > --- a/xen/include/asm-arm/processor.h > +++ b/xen/include/asm-arm/processor.h > @@ -116,6 +116,34 @@ > #define TCR_RES1 (_AC(1,UL)<<31) > #endif > > +/* VTCR: Stage 2 Translation Control */ > + > +#define VTCR_T0SZ(x) ((x)<<0) > + > +#define VTCR_SL0(x) ((x)<<6) > + > +#define VTCR_IRGN0_NC (_AC(0x0,UL)<<8) > +#define VTCR_IRGN0_WBWA (_AC(0x1,UL)<<8) > +#define VTCR_IRGN0_WT (_AC(0x2,UL)<<8) > +#define VTCR_IRGN0_WB (_AC(0x3,UL)<<8) > + > +#define VTCR_ORGN0_NC (_AC(0x0,UL)<<10) > +#define VTCR_ORGN0_WBWA (_AC(0x1,UL)<<10) > +#define VTCR_ORGN0_WT (_AC(0x2,UL)<<10) > +#define VTCR_ORGN0_WB (_AC(0x3,UL)<<10) > + > +#define VTCR_SH0_NS (_AC(0x0,UL)<<12) > +#define VTCR_SH0_OS (_AC(0x2,UL)<<12) > +#define VTCR_SH0_IS (_AC(0x3,UL)<<12) > + > +#define VTCR_TG0_4K (_AC(0x0,UL)<<14) /* arm64 only */ > +#define VTCR_TG0_64K (_AC(0x1,UL)<<14) > +#define VTCR_TG0_16K (_AC(0x2,UL)<<14) > + > +#define VTCR_PS(x) ((x)<<16) All the define from the "/* arm64 only */" up to here are arm64 only. With the comment at the end of the line it's no clear that it's actually the case. It might be worse to add an #ifdef CONFIG_ARM_64 Regards, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |