|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 1/2] xen/arm: Rework the way to compute dom0 DTB base address
On 05/31/2013 12:45 PM, Ian Campbell wrote:
> On Thu, 2013-05-30 at 15:05 +0100, Julien Grall wrote:
>> If the DTB is loading right the after the kernel, on some setup, Linux will
>> overwrite the DTB during the decompression step.
>>
>> To be sure the DTB won't be overwritten by the decompression stage, load
>> the DTB near the end of the first memory bank and below 4Gib (if memory
>> range is
>> greater).
>>
>> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
>>
>> Changes in v2:
>> - Align the DTB base address to 2Mib
>> - Add dtb_check_overlap to check if the kernel will overlap the DTB
>> - Fix typo
>> ---
>> xen/arch/arm/domain_build.c | 51
>> ++++++++++++++++++++++++++++++++++++++-----
>> xen/arch/arm/kernel.c | 2 ++
>> xen/arch/arm/kernel.h | 7 ++++++
>> 3 files changed, 54 insertions(+), 6 deletions(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index b92c64b..515fabe 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -477,6 +477,7 @@ static int prepare_dtb(struct domain *d, struct
>> kernel_info *kinfo)
>> void *fdt;
>> int new_size;
>> int ret;
>> + paddr_t end;
>>
>> kinfo->unassigned_mem = dom0_mem;
>>
>> @@ -502,17 +503,25 @@ static int prepare_dtb(struct domain *d, struct
>> kernel_info *kinfo)
>> goto err;
>>
>> /*
>> - * Put the device tree at the beginning of the first bank. It
>> - * must be below 4 GiB.
>> + * DTB must be load below 4GiB and far enough to linux (Linux use
> ^from ^uses
>
>> + * the space after it to decompress)
>> + * Load the DTB at the end of the first bank or below 4Gib
> and below?
>
> Perhaps clearer to write "Load the DTB at the end of the first bank,
> while ensure it is also below 4G"
>
Sound goods. I will send a new patch with this change.
>> */
>> - kinfo->dtb_paddr = kinfo->mem.bank[0].start + 0x100;
>> - if ( kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt) > (1ull << 32) )
>> + end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size;
>> + end = MIN(1ull << 32, end);
>> + kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt);
>> + /* Linux requires the address to be aligned to 2Mb */
>
> Does it? I don't disagree with aligning it to 2MB but I'm sure that e.g.
> CONFIG_APPENDED_DTB handles the unaligned case (perhaps that is
> special)?
I didn't pay attention when I have replaced 4 bytes by 2Mb. Linux only
requires to have an address aligned to 4 bytes.
>
>> + kinfo->dtb_paddr &= ~((2 << 20) - 1);
>> +
>> + if ( fdt_totalsize(kinfo->fdt) > end )
>> {
>> - printk("Not enough memory below 4 GiB for the device tree.");
>> + printk(XENLOG_ERR "Not enough memory in the first bank for "
>> + "the device tree.");
>> ret = -FDT_ERR_XEN(EINVAL);
>> goto err;
>> }
>>
>> +
>> return 0;
>>
>> err:
>> @@ -521,9 +530,36 @@ static int prepare_dtb(struct domain *d, struct
>> kernel_info *kinfo)
>> return -EINVAL;
>> }
>>
>> +static int dtb_check_overlap(struct kernel_info *kinfo)
>> +{
>> + paddr_t zimage_start = kinfo->zimage.load_addr;
>> + paddr_t zimage_end = kinfo->zimage.load_addr + kinfo->zimage.len;
>> + paddr_t dtb_start = kinfo->dtb_paddr;
>> + paddr_t dtb_end = kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt);
>> +
>> + /*
>> + * Check the kernel won't overlap the kernel
>> + * Only when it's a ZIMAGE
>> + */
>> + if ( kinfo->type != KERNEL_ZIMAGE )
>> + return 0;
>> +
>> + if ( !(MAX(zimage_start, dtb_end) < MIN(zimage_end, dtb_start)) )
>> + return 0;
>
> I had to draw quite a few pictures to convince myself this was right,
> and I'm still not entirely sure ;-)
In fact it's totally wrong :/. What about this check?
if ( (dtb_start < zimage_end) || (dtb_end < zimage_start) )
>
>> +
>> + printk(XENLOG_ERR "The kernel(0x%"PRIpaddr"-0x%"PRIpaddr
>> + ") is overlapping the DTB(0x%"PRIpaddr"-0x%"PRIpaddr":\n",
>
> Missing a closing ) on the DTB range. Also why the trailing ":"?
I planned to have a different sentence. I will replace the ":" by ")".
>
>> + zimage_start, zimage_end, dtb_start, dtb_end);
>> + xfree(kinfo->fdt);
>
> This seems like an odd place to free this.
>
> Returning an error here is only going to cause us to give up and panic
> anyway. I'd suggest to just panic here directly and not bother
> propagating an error code.
>
> Not really sure why construct_dom0 has a return code at all, instead of
> it (or the functions it calls) just panicing. But lets not worry about
> that now.
>
>> +
>> + return -EINVAL;
>> +}
>> +
>> static void dtb_load(struct kernel_info *kinfo)
>> {
>> void * __user dtb_virt = (void * __user)(register_t)kinfo->dtb_paddr;
>
> Blank line here please.
>
>> + printk("Loading dom0 DTB to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
>> + kinfo->dtb_paddr, kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt));
>
>>
>> raw_copy_to_guest(dtb_virt, kinfo->fdt, fdt_totalsize(kinfo->fdt));
>> xfree(kinfo->fdt);
>> @@ -559,10 +595,13 @@ int construct_dom0(struct domain *d)
>> if ( rc < 0 )
>> return rc;
>>
>> + rc = dtb_check_overlap(&kinfo);
>> + if ( rc < 0 )
>> + return rc;
>> +
>> /* The following loads use the domain's p2m */
>> p2m_load_VTTBR(d);
>>
>> - kinfo.dtb_paddr = kinfo.zimage.load_addr + kinfo.zimage.len;
>> kernel_load(&kinfo);
>> dtb_load(&kinfo);
>>
>> diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
>> index 8f4a60d..f8c8850 100644
>> --- a/xen/arch/arm/kernel.c
>> +++ b/xen/arch/arm/kernel.c
>> @@ -152,6 +152,7 @@ static int kernel_try_zimage_prepare(struct kernel_info
>> *info,
>>
>> info->entry = info->zimage.load_addr;
>> info->load = kernel_zimage_load;
>> + info->type = KERNEL_ZIMAGE;
>>
>> return 0;
>> }
>> @@ -193,6 +194,7 @@ static int kernel_try_elf_prepare(struct kernel_info
>> *info,
>> */
>> info->entry = info->elf.parms.virt_entry;
>> info->load = kernel_elf_load;
>> + info->type = KERNEL_ELF;
>>
>> return 0;
>> err:
>> diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
>> index 1776a4d..b4ecd30 100644
>> --- a/xen/arch/arm/kernel.h
>> +++ b/xen/arch/arm/kernel.h
>> @@ -9,6 +9,12 @@
>> #include <xen/libelf.h>
>> #include <xen/device_tree.h>
>>
>> +enum kernel_type
>> +{
>> + KERNEL_ELF,
>> + KERNEL_ZIMAGE,
>> +};
>> +
>> struct kernel_info {
>> #ifdef CONFIG_ARM_64
>> enum domain_type type;
>> @@ -23,6 +29,7 @@ struct kernel_info {
>>
>> void *kernel_img;
>> unsigned kernel_order;
>> + enum kernel_type type;
>>
>> union {
>> struct {
>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |