@@ -183,12 +183,12 @@ def round_down(val, align):
183183# access or set caching properties at leaf levels.
184184INT_FLAGS = FLAG_P | FLAG_RW | FLAG_US
185185
186+
186187class MMUTable :
187188 """Represents a particular table in a set of page tables, at any level"""
188189
189190 def __init__ (self ):
190- self .entries = array .array (self .type_code ,
191- [0 for i in range (self .num_entries )])
191+ self .entries = array .array (self .type_code , [0 for i in range (self .num_entries )])
192192
193193 def get_binary (self ):
194194 """Return a bytearray representation of this table"""
@@ -260,79 +260,107 @@ def map(self, virt_addr, phys_addr, entry_flags):
260260 this is the physical address of the next level table"""
261261 index = self .entry_index (virt_addr )
262262
263- verbose (f"{ self .__class__ .__name__ :s} : "
264- f"mapping 0x{ phys_addr :x} to 0x{ virt_addr :x} : "
265- f"{ dump_flags (entry_flags ):s} " )
263+ verbose (
264+ f"{ self .__class__ .__name__ :s} : "
265+ f"mapping 0x{ phys_addr :x} to 0x{ virt_addr :x} : "
266+ f"{ dump_flags (entry_flags ):s} "
267+ )
266268
267- self .entries [index ] = ((phys_addr & self .addr_mask ) |
268- (entry_flags & self .supported_flags ))
269+ self .entries [index ] = (phys_addr & self .addr_mask ) | (entry_flags & self .supported_flags )
269270
270271 def set_perms (self , virt_addr , entry_flags ):
271- """" For the table entry corresponding to the provided virtual address,
272+ """For the table entry corresponding to the provided virtual address,
272273 update just the flags, leaving the physical mapping alone.
273274 Unsupported flags will be filtered out."""
274275 index = self .entry_index (virt_addr )
275276
276- verbose (f"{ self .__class__ .__name__ :s} : "
277- f"changing perm at 0x{ virt_addr :x} : "
278- f"{ dump_flags (entry_flags ):s} " )
277+ verbose (
278+ f"{ self .__class__ .__name__ :s} : "
279+ f"changing perm at 0x{ virt_addr :x} : "
280+ f"{ dump_flags (entry_flags ):s} "
281+ )
279282
280- self .entries [index ] = ((self .entries [index ] & self .addr_mask ) |
281- (entry_flags & self .supported_flags ))
283+ self .entries [index ] = (self .entries [index ] & self .addr_mask ) | (
284+ entry_flags & self .supported_flags
285+ )
282286
283287
284288# Specific supported table types
285289class Pml4 (MMUTable ):
286290 """Page mapping level 4 for IA-32e"""
291+
287292 addr_shift = 39
288293 addr_mask = 0x7FFFFFFFFFFFF000
289294 type_code = 'Q'
290295 num_entries = 512
291296 supported_flags = INT_FLAGS
292297
298+
293299class Pdpt (MMUTable ):
294300 """Page directory pointer table for IA-32e"""
301+
295302 addr_shift = 30
296303 addr_mask = 0x7FFFFFFFFFFFF000
297304 type_code = 'Q'
298305 num_entries = 512
299306 supported_flags = INT_FLAGS | FLAG_SZ | FLAG_CD
300307
308+
301309class PdptPAE (Pdpt ):
302310 """Page directory pointer table for PAE"""
311+
303312 num_entries = 4
304313
314+
305315class Pd (MMUTable ):
306316 """Page directory for 32-bit"""
317+
307318 addr_shift = 22
308319 addr_mask = 0xFFFFF000
309320 type_code = 'I'
310321 num_entries = 1024
311322 supported_flags = INT_FLAGS | FLAG_SZ | FLAG_CD
312323
324+
313325class PdXd (Pd ):
314326 """Page directory for either PAE or IA-32e"""
327+
315328 addr_shift = 21
316329 addr_mask = 0x7FFFFFFFFFFFF000
317330 num_entries = 512
318331 type_code = 'Q'
319332
333+
320334class Pt (MMUTable ):
321335 """Page table for 32-bit"""
336+
322337 addr_shift = 12
323338 addr_mask = 0xFFFFF000
324339 type_code = 'I'
325340 num_entries = 1024
326- supported_flags = (FLAG_P | FLAG_RW | FLAG_US | FLAG_G | FLAG_CD | FLAG_D |
327- FLAG_IGNORED0 | FLAG_IGNORED1 )
341+ supported_flags = (
342+ FLAG_P | FLAG_RW | FLAG_US | FLAG_G | FLAG_CD | FLAG_D | FLAG_IGNORED0 | FLAG_IGNORED1
343+ )
344+
328345
329346class PtXd (Pt ):
330347 """Page table for either PAE or IA-32e"""
348+
331349 addr_mask = 0x07FFFFFFFFFFF000
332350 type_code = 'Q'
333351 num_entries = 512
334- supported_flags = (FLAG_P | FLAG_RW | FLAG_US | FLAG_G | FLAG_XD | FLAG_CD |
335- FLAG_D | FLAG_IGNORED0 | FLAG_IGNORED1 | FLAG_IGNORED2 )
352+ supported_flags = (
353+ FLAG_P
354+ | FLAG_RW
355+ | FLAG_US
356+ | FLAG_G
357+ | FLAG_XD
358+ | FLAG_CD
359+ | FLAG_D
360+ | FLAG_IGNORED0
361+ | FLAG_IGNORED1
362+ | FLAG_IGNORED2
363+ )
336364
337365
338366class PtableSet :
@@ -344,8 +372,7 @@ def __init__(self, pages_start):
344372 self .toplevel = self .levels [0 ]()
345373 self .page_pos = pages_start
346374
347- debug (f"{ self .__class__ .__name__ :s} "
348- f"starting at physical address 0x{ self .page_pos :x} " )
375+ debug (f"{ self .__class__ .__name__ :s} starting at physical address 0x{ self .page_pos :x} " )
349376
350377 # Database of page table pages. Maps physical memory address to
351378 # MMUTable objects, excluding the top-level table which is tracked
@@ -442,8 +469,9 @@ def reserve(self, virt_base, size, to_level=PT_LEVEL):
442469 scope = 1 << self .levels [PD_LEVEL ].addr_shift
443470
444471 if virt_base % scope != 0 :
445- error (f"misaligned virtual address space, 0x{ virt_base :x} "
446- f"not a multiple of 0x{ scope :x} " )
472+ error (
473+ f"misaligned virtual address space, 0x{ virt_base :x} not a multiple of 0x{ scope :x} "
474+ )
447475
448476 for addr in range (virt_base , virt_base + size , scope ):
449477 self .map_page (addr , 0 , 0 , True , to_level )
@@ -568,25 +596,33 @@ def write_output(self, filename):
568596 # in PAE, the top-level PDPT has only 4 entries and is not a
569597 # full page in size. We do not put it in the tables dictionary
570598 # and treat it as a special case.
571- debug (f"top-level { self .toplevel .__class__ .__name__ :s} at "
572- f"physical addr 0x{ self .get_new_mmutable_addr ():x} " )
599+ debug (
600+ f"top-level { self .toplevel .__class__ .__name__ :s} at "
601+ f"physical addr 0x{ self .get_new_mmutable_addr ():x} "
602+ )
573603 top_level_bin = self .toplevel .get_binary ()
574604 output_fp .write (top_level_bin )
575605 written_size += len (top_level_bin )
576606
577607 return written_size
578608
609+
579610# Paging mode classes, we'll use one depending on configuration
580611class Ptables32bit (PtableSet ):
581612 """32-bit Page Tables"""
613+
582614 levels = [Pd , Pt ]
583615
616+
584617class PtablesPAE (PtableSet ):
585618 """PAE Page Tables"""
619+
586620 levels = [PdptPAE , PdXd , PtXd ]
587621
622+
588623class PtablesIA32e (PtableSet ):
589624 """Page Tables under IA32e mode"""
625+
590626 levels = [Pml4 , Pdpt , PdXd , PtXd ]
591627
592628
@@ -596,14 +632,16 @@ def parse_args():
596632
597633 parser = argparse .ArgumentParser (
598634 description = __doc__ ,
599- formatter_class = argparse .RawDescriptionHelpFormatter , allow_abbrev = False )
600-
601- parser .add_argument ("-k" , "--kernel" , required = True ,
602- help = "path to prebuilt kernel ELF binary" )
603- parser .add_argument ("-o" , "--output" , required = True ,
604- help = "output file" )
605- parser .add_argument ("--map" , action = 'append' ,
606- help = textwrap .dedent ('''\
635+ formatter_class = argparse .RawDescriptionHelpFormatter ,
636+ allow_abbrev = False ,
637+ )
638+
639+ parser .add_argument ("-k" , "--kernel" , required = True , help = "path to prebuilt kernel ELF binary" )
640+ parser .add_argument ("-o" , "--output" , required = True , help = "output file" )
641+ parser .add_argument (
642+ "--map" ,
643+ action = 'append' ,
644+ help = textwrap .dedent ('''\
607645 Map extra memory:
608646 <physical address>,<size>[,<flags:LUWXD>[,<virtual address>]]
609647 where flags can be empty or combination of:
@@ -617,9 +655,9 @@ def parse_args():
617655 supervisor only,
618656 read only,
619657 and execution disabled.
620- ''' ))
621- parser . add_argument ( "-v" , "--verbose" , action = "count" ,
622- help = "Print extra debugging information" )
658+ ''' ),
659+ )
660+ parser . add_argument ( "-v" , "--verbose" , action = "count" , help = "Print extra debugging information" )
623661 args = parser .parse_args ()
624662 if "VERBOSE" in os .environ :
625663 args .verbose = 1
@@ -629,11 +667,11 @@ def get_symbols(elf_obj):
629667 """Get all symbols from the ELF file"""
630668 for section in elf_obj .iter_sections ():
631669 if isinstance (section , SymbolTableSection ):
632- return {sym .name : sym .entry .st_value
633- for sym in section .iter_symbols ()}
670+ return {sym .name : sym .entry .st_value for sym in section .iter_symbols ()}
634671
635672 raise LookupError ("Could not find symbol table" )
636673
674+
637675def isdef (sym_name ):
638676 """True if symbol is defined in ELF file"""
639677 return sym_name in syms
@@ -665,7 +703,7 @@ def map_extra_regions(pt):
665703
666704 one_map ['cmdline' ] = entry
667705 one_map ['phys' ] = int (elements [0 ], 0 )
668- one_map ['size' ]= int (elements [1 ], 0 )
706+ one_map ['size' ] = int (elements [1 ], 0 )
669707 one_map ['large_page' ] = False
670708
671709 flags = FLAG_P | ENTRY_XD
@@ -684,7 +722,7 @@ def map_extra_regions(pt):
684722 if 'U' in map_flags :
685723 flags |= ENTRY_US
686724 if 'L' in map_flags :
687- flags |= FLAG_SZ
725+ flags |= FLAG_SZ
688726 one_map ['large_page' ] = True
689727 if 'D' in map_flags :
690728 flags |= FLAG_CD
@@ -709,8 +747,9 @@ def map_extra_regions(pt):
709747 # Check if addresses have already been mapped.
710748 # Error out if so as they could override kernel mappings.
711749 if pt .is_region_mapped (virt , size , level ):
712- error (f"Region 0x{ virt :x} ({ size :d} ) already been mapped "
713- f"for --map { one_map ['cmdline' ]:x} " )
750+ error (
751+ f"Region 0x{ virt :x} ({ size :d} ) already been mapped for --map { one_map ['cmdline' ]:x} "
752+ )
714753
715754 # Reserve space in page table, and map the region
716755 pt .reserve_unaligned (virt , size , level )
@@ -773,12 +812,15 @@ def main():
773812
774813 debug (f"Address space: 0x{ vm_base :x} - 0x{ vm_base + vm_size - 1 :x} size 0x{ vm_size :x} " )
775814
776- debug (f"Zephyr image: 0x{ image_base :x} - 0x{ image_base + image_size - 1 :x} "
777- f"size 0x{ image_size :x} " )
815+ debug (
816+ f"Zephyr image: 0x{ image_base :x} - 0x{ image_base + image_size - 1 :x} size 0x{ image_size :x} "
817+ )
778818
779819 if virt_to_phys_offset != 0 :
780- debug (f"Physical address space: 0x{ sram_base :x} - 0x{ sram_base + sram_size - 1 :x} "
781- f"size 0x{ sram_size :x} " )
820+ debug (
821+ f"Physical address space: 0x{ sram_base :x} - 0x{ sram_base + sram_size - 1 :x} "
822+ f"size 0x{ sram_size :x} "
823+ )
782824
783825 is_perm_regions = isdef ("CONFIG_SRAM_REGION_PERMISSIONS" )
784826
@@ -819,8 +861,9 @@ def main():
819861 # Note that this only does the identity mapping
820862 # at the page directory level to minimize wasted space.
821863 pt .reserve_unaligned (image_base_phys , image_size , to_level = PD_LEVEL )
822- pt .identity_map_unaligned (image_base_phys , image_size ,
823- FLAG_P | FLAG_RW | FLAG_SZ , level = PD_LEVEL )
864+ pt .identity_map_unaligned (
865+ image_base_phys , image_size , FLAG_P | FLAG_RW | FLAG_SZ , level = PD_LEVEL
866+ )
824867
825868 if isdef ("CONFIG_X86_64" ):
826869 # 64-bit has a special region in the first 64K to bootstrap other CPUs
@@ -832,8 +875,12 @@ def main():
832875
833876 if isdef ("CONFIG_XIP" ):
834877 # Additionally identity-map all ROM as read-only
835- pt .map (syms ["CONFIG_FLASH_BASE_ADDRESS" ], None ,
836- syms ["CONFIG_FLASH_SIZE" ] * 1024 , map_flags | FLAG_P )
878+ pt .map (
879+ syms ["CONFIG_FLASH_BASE_ADDRESS" ],
880+ None ,
881+ syms ["CONFIG_FLASH_SIZE" ] * 1024 ,
882+ map_flags | FLAG_P ,
883+ )
837884
838885 if isdef ("CONFIG_LINKER_USE_BOOT_SECTION" ):
839886 pt .map_region ("lnkr_boot" , map_flags | FLAG_P | ENTRY_RW , virt_to_phys_offset )
@@ -884,8 +931,7 @@ def main():
884931 if isdef ("CONFIG_COVERAGE_GCOV" ) and isdef ("CONFIG_USERSPACE" ):
885932 # If GCOV is enabled, user mode must be able to write to its
886933 # common data area
887- pt .set_region_perms ("__gcov_bss" ,
888- FLAG_P | ENTRY_RW | ENTRY_US | ENTRY_XD )
934+ pt .set_region_perms ("__gcov_bss" , FLAG_P | ENTRY_RW | ENTRY_US | ENTRY_XD )
889935
890936 if isdef ("CONFIG_X86_64" ):
891937 # Set appropriate permissions for locore areas much like we did
@@ -926,8 +972,10 @@ def main():
926972
927973 reason = "big" if reserved_pt_size > written_size else "small"
928974
929- error (f"Reserved space for page table is too { reason :s} ."
930- f" Set CONFIG_X86_EXTRA_PAGE_TABLE_PAGES={ extra_pages_needed :d} " )
975+ error (
976+ f"Reserved space for page table is too { reason :s} ."
977+ f" Set CONFIG_X86_EXTRA_PAGE_TABLE_PAGES={ extra_pages_needed :d} "
978+ )
931979
932980
933981if __name__ == "__main__" :
0 commit comments