[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [[PATCH for-4.13]] xen/arm: mm: Allow generic xen page-tables helpers to be called early



On Tue, 8 Oct 2019, Julien Grall wrote:
> On 10/8/19 1:18 AM, Stefano Stabellini wrote:
> > On Mon, 7 Oct 2019, Julien Grall wrote:
> > > Hi,
> > > 
> > > On 03/10/2019 02:02, Stefano Stabellini wrote:
> > > > On Fri, 20 Sep 2019, Julien Grall wrote:
> > > > > That's not correct. alloc_boot_pages() is actually here to allow
> > > > > dynamic
> > > > > allocation before the memory subsystem (and therefore the runtime
> > > > > allocator)
> > > > > is initialized.
> > > > 
> > > > Let me change the question then: is the system_state ==
> > > > SYS_STATE_early_boot check strictly necessary? It looks like it is not:
> > > > the patch would work even if it was just:
> > > 
> > > I had a few thoughts about it. On Arm32, this only really works for
> > > 32-bits machine address (it can go up to 40-bits). I haven't really
> > > fully investigated what could go wrong, but it would be best to keep it
> > > only for early boot.
> > > 
> > > Also, I don't really want to rely on this "workaround" after boot. Maybe
> > > we would want to keep them unmapped in the future.
> > 
> > Yes, no problems, we agree on that. I am not asking in regards to the
> > check system_state == SYS_STATE_early_boot with the goal of asking you
> > to get rid of it. I am fine with keeping the check. (Maybe we want to add
> > an `unlikely()' around the check.)
> > 
> > I am trying to understand whether the code actually relies on
> > system_state == SYS_STATE_early_boot, and, if so, why. The goal is to
> > make sure that if there are some limitations that they are documented,
> > or just to double-check that there are no limitations.
> 
> The check is not strictly necessary.
> 
> > 
> > In regards to your comment about only working for 32-bit addresses on
> > Arm32, you have a point. At least we should be careful with the mfn to
> > vaddr conversion because mfn_to_maddr returns a paddr_t which is 64-bit
> > and vaddr_t is 32-bit. I imagine that theoretically, even with
> > system_state == SYS_STATE_early_boot, it could get truncated with the
> > wrong combination of mfn and phys_offset.
> > 
> > If nothing else, maybe we should add a truncation check for safety?
> 
> Except that phys_offset is not defined correctly, so your check below will
> break some setup :(. Let's take the following example:
> 
>    Xen is loaded at PA 0x100000
> 
> The boot offset is computed using 32-bit address (see head.S):
>     PA - VA = 0x100000 - 0x200000
>             = 0xfff00000
> 
> This value will be passed to C code as an unsigned long. But then we will
> store it in a uint64_t/paddr_t (see phys_offset which is set in
> setup_page_tables). Because this is a conversion from unsigned to unsigned,
> the "sign bit" will not be propagated.
>
> This means that phys_offset will be equal to 0xfff00000 and not
> 0xfffffffffff00000!
> 
> Therefore if we try to convert 0x100000 (where Xen has been loaded) back to
> its VA, the resulting value will be 0xffffffff00200100.
>
> Looking at the code, I think pte_of_xenaddr() has also the exact problem. :(

One way to fix it would be to change phys_offset to register_t (or just
declare it as unsigned long on arm32 and unsigned long long on arm64):

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index be23acfe26..c7ead39654 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -170,7 +170,7 @@ static DEFINE_PAGE_TABLE(xen_xenmap);
 /* Non-boot CPUs use this to find the correct pagetables. */
 uint64_t init_ttbr;
 
-static paddr_t phys_offset;
+static register_t phys_offset;
 
 /* Limits of the Xen heap */
 mfn_t xenheap_mfn_start __read_mostly = INVALID_MFN_INITIALIZER;

It would work OK for virtual to physical conversions. Physical to
virtual is more challenging because physical could go up to 40bits.
Fortunately, it doesn't look like we are using phys_offset to do many
phys-to-virt conversions. The only example is the one in this patch,
and dump_hyp_walk.


> I guess nobody tried to load Xen that low in memory on Arm32? But that's going
> to be definitely an issues with the memory rework I have in mind.
> 
> I have some other important work to finish for Xen 4.13. So I am thinking to
> defer the problem I mention above for post Xen 4.13. Although, the GRUB issues
> would still need to be fix. Any opinions?

I think for Xen 4.13 I would like to get in your patch to fix GRUB
booting, with a little bit more attention to integer issues. Something
like the following:

    paddr_t pa_end = _end + phys_offset;
    paddr_t pa_start = _start + phys_offset;
    paddr_t pa = mfn_to_maddr(mfn);

    if ( pa < pa_end && pa >= pa_start )
        return (lpae_t *)(vaddr_t)(pa - pa_start + XEN_VIRT_ADDR);

I think it should work if phys_offset is register_t. Or we could have a
check on pa >= 4G, something like:

    paddr_t pa = (register_t)mfn_to_maddr(mfn) - phys_offset;

    if ( mfn_to_maddr(mfn) <= UINT32_MAX &&
         pa < _end &&
         is_kernel((vaddr_t)pa) )
        return (lpae_t *)(vaddr_t)pa;


> Note that this is also more reasons to limit the use of "MA - phys_offset". So
> the mess is kept to boot code.
> 
> > Something like the following but that ideally would be applicable to
> > arm64 too without having to add an #ifdef:
> > 
> >      paddr_t pa = mfn_to_maddr(mfn) - phys_offset;
> > 
> >      if ( pa < _end && is_kernel((vaddr_t)pa) )
> >          return (lpae_t *)(vaddr_t)pa;

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.