I am working on writing a static paging setup for a custom bare-metal ARM system. ARMv7a uses two-level paging, where entries in a top-level page table can point to a second-level table. I have a top-level table and a couple of second-level tables that I need to link together, both implemented in the same .S file and same section.
The "link entry" in the top-level table should have this value:
(second_level_table_addr & 0xfffffc00) | 0x9
-- this takes the base address of the second-level table, and clears the low bits and replaces them with some configuration bits (see ARMv7a manual B3.5.1 for details).
My question is: can I use the symbol for the second-level table to generate the link entry in the top-level table, after relocation? If I try to write an expression like .word (second_level_table_sym & 0xfffffc00) | 0x9
, I get the following error: invalid operands (.boot_data and *ABS* sections) for &
.
Right now what I'm doing is manually setting absolute addresses for the second-level tables and hard-coding them in the link entries. This works, but I feel like it will be difficult to maintain as the mappings become more complicated, and in general I would like to leave binary layout to the toolchain as much as possible. This would also be pretty easy to fix up at runtime, but unfortunately the tables will be stored in read-only memory and so that isn't possible.
As I understand it, the address of second_level_table_sym
is not known when assembling the individual file (the point where I get the error), but it is known at final link time after relocation. Is there a way to get the assembler (GNU arm-eabi-none-as) to use that knowledge to generate the table entry I want?
second_level_table_sym
aligned to 1k then the& 0xfffffc00
would not be needed and the| 0x9
could be done with+ 0x9
which can be relocated.