[PATCH] arm64: relax Image placement requirement

Ard Biesheuvel ard.biesheuvel at linaro.org
Sun Mar 22 08:36:37 PDT 2015


On 20 March 2015 at 18:49, Ard Biesheuvel <ard.biesheuvel at linaro.org> wrote:
> On 20 March 2015 at 18:02, Ard Biesheuvel <ard.biesheuvel at linaro.org> wrote:
>> Hi all,
>>
>> This is another possible approach to fixing the current, flawed
>> EFI Image placement logic: instead of fixing that logic and the
>> documentation, why not relax the requirement that the kernel
>> Image not be placed across a 512 MB boundary?
>>
>
> Hmm, it seems this still needs a pinch of refinement, but we could at
> least discuss the general idea.
>

Replying to self again:
it appears that, in order to relax the restriction that no 512 MB
alignment boundary may be crossed, it would be sufficient to shrink
the ID mapping to a single page, containing only the couple of
instructions we execute between enabling the MMU and jumping into the
virtually remapped kernel text. Since mapping a single page can never
cross such a boundary, no extended translation tables are needed.

-- 
Ard.



>> ---------------->8-----------------
>>
>> This patch changes the early page table code so that two adjacent
>> entries are used to map two pages worth of block entries at the
>> lowest level, both for idmap_pg_dir and swapper_pg_dir.
>>
>> The purpose is to allow the kernel Image to cross a 512 MB or 1 GB
>> alignment boundary (depending on page size), which is something that
>> is not specifically banned by the current wording of the boot protocol.
>> (The boot protocol stipulates that the kernel must be placed within
>> 512 MB if the beginning of RAM. However, the beginning of RAM is not
>> necessarily aligned to 512 MB)
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> ---
>>  arch/arm64/include/asm/page.h |  4 ++--
>>  arch/arm64/kernel/head.S      | 17 +++++++++++++----
>>  2 files changed, 15 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
>> index 3d02b1869eb8..d2189c359364 100644
>> --- a/arch/arm64/include/asm/page.h
>> +++ b/arch/arm64/include/asm/page.h
>> @@ -43,8 +43,8 @@
>>  #define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS - 1)
>>  #endif
>>
>> -#define SWAPPER_DIR_SIZE       (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
>> -#define IDMAP_DIR_SIZE         (3 * PAGE_SIZE)
>> +#define SWAPPER_DIR_SIZE       ((SWAPPER_PGTABLE_LEVELS + 1) * PAGE_SIZE)
>> +#define IDMAP_DIR_SIZE         (4 * PAGE_SIZE)
>>
>>  #ifndef __ASSEMBLY__
>>
>> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
>> index 0dbdb4f3634f..9c3f95f30421 100644
>> --- a/arch/arm64/kernel/head.S
>> +++ b/arch/arm64/kernel/head.S
>> @@ -274,18 +274,21 @@ ENDPROC(preserve_boot_args)
>>   *     virt:   virtual address
>>   *     shift:  #imm page table shift
>>   *     ptrs:   #imm pointers per table page
>> + *     offset: #imm offset into the lowest translation level, in pages
>>   *
>>   * Preserves:  virt
>>   * Corrupts:   tmp1, tmp2
>>   * Returns:    tbl -> next level table page address
>>   */
>> -       .macro  create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
>> +       .macro  create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2, offset=0
>>         lsr     \tmp1, \virt, #\shift
>> +       .if     \offset
>> +       add     \tmp1, \tmp1, #\offset
>> +       .endif
>>         and     \tmp1, \tmp1, #\ptrs - 1        // table index
>> -       add     \tmp2, \tbl, #PAGE_SIZE
>> +       add     \tmp2, \tbl, #(\offset + 1) * PAGE_SIZE
>>         orr     \tmp2, \tmp2, #PMD_TYPE_TABLE   // address of next table and entry type
>>         str     \tmp2, [\tbl, \tmp1, lsl #3]
>> -       add     \tbl, \tbl, #PAGE_SIZE          // next level table page
>>         .endm
>>
>>  /*
>> @@ -297,9 +300,14 @@ ENDPROC(preserve_boot_args)
>>   */
>>         .macro  create_pgd_entry, tbl, virt, tmp1, tmp2
>>         create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2
>> -#if SWAPPER_PGTABLE_LEVELS == 3
>> +#if SWAPPER_PGTABLE_LEVELS != 3
>> +       create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2, 1
>> +#else
>> +       add     \tbl, \tbl, #PAGE_SIZE          // next level table page
>>         create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2
>> +       create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2, 1
>>  #endif
>> +       add     \tbl, \tbl, #PAGE_SIZE          // next level table page
>>         .endm
>>
>>  /*
>> @@ -396,6 +404,7 @@ __create_page_tables:
>>         str_l   x5, idmap_t0sz, x6
>>
>>         create_table_entry x0, x3, EXTRA_SHIFT, EXTRA_PTRS, x5, x6
>> +       add     x0, x0, #PAGE_SIZE              // next level table page
>>  1:
>>  #endif
>>
>> --
>> 1.8.3.2
>>



More information about the linux-arm-kernel mailing list