<commit_before>#=======================================================================
# bootstrap.py
#=======================================================================

from machine        import State
#from pydgin.storage import Memory

# Currently these constants are set to match gem5
memory_size = 2**27
page_size   = 8192

# MIPS stack starts at top of kuseg (0x7FFF.FFFF) and grows down
#stack_base = 0x7FFFFFFF
stack_base = memory_size-1   # TODO: set this correctly!

#-----------------------------------------------------------------------
# syscall_init
#-----------------------------------------------------------------------
#
# MIPS Memory Map (32-bit):
#
#   0xC000.0000 - Mapped            (kseg2) -   1GB
#   0xA000.0000 - Unmapped uncached (kseg1) - 512MB
#   0x8000.0000 - Unmapped cached   (kseg0) - 512MB
#   0x0000.0000 - 32-bit user space (kuseg) -   2GB
#
def syscall_init( mem, entrypoint, breakpoint, argv, debug ):

  #---------------------------------------------------------------------
  # memory map initialization
  #---------------------------------------------------------------------

  # TODO: for multicore allocate 8MB for each process
  #proc_stack_base[pid] = stack_base - pid * 8 * 1024 * 1024

  # top of heap (breakpoint)  # TODO: handled in load program

  # memory maps: 1GB above top of heap
  # mmap_start = mmap_end = break_point + 0x40000000

  #---------------------------------------------------------------------
  # stack argument initialization
  #---------------------------------------------------------------------
  # http://articles.manugarg.com/aboutelfauxiliaryvectors.html
  #
  #                contents         size
  #
  #   0x7FFF.FFFF  [ end marker ]               4    (NULL)
  #                [ environment str data ]   >=0
  #                [ arguments   str data ]   >=0
  #                [ padding ]               0-16
  #                [ auxv[n]  data ]            8    (AT_NULL Vector)
  #                                             8*x
  #                [ auxv[0]  data ]            8
  #                [ envp[n]  pointer ]         4    (NULL)
  #                                             4*x
  #                [ envp[0]  pointer ]         4
  #                [ argv[n]  pointer ]         4    (NULL)
  #                                             4*x
  #                [ argv[0]  pointer ]         4    (program name)
  #   stack ptr->  [ argc ]                     4    (size of argv)
  #
  #                (stack grows down!!!)
  #
  #   0x7F7F.FFFF  < stack limit for pid 0 >
  #

  # auxv variables initialized by gem5, are these needed?
  #
  # - PAGESZ:    system page size
  # - PHDR:      virtual addr of program header tables
  #              (for statically linked binaries)
  # - PHENT:     size of program header entries in elf file
  # - PHNUM:     number of program headers in elf file
  # - AT_ENRTY:  program entry point
  # - UID:       user ID
  # - EUID:      effective user ID
  # - GID:       group ID
  # - EGID:      effective group ID

  # TODO: handle auxv, envp variables
  auxv = []
  envp = []
  argv = argv[1:]
  argc = len( argv )

  def sum_( x ):
    val = 0
    for i in x:
      val += i
    return val

  # calculate sizes of sections
  # TODO: parameterize auxv/envp/argv calc for variable int size?
  stack_nbytes  = [ 4,                              # end mark nbytes (sentry)
                    sum_([len(x)+1 for x in envp]), # envp_str nbytes
                    sum_([len(x)+1 for x in argv]), # argv_str nbytes
                    0,                              # padding  nbytes
                    8*(len(auxv) + 1),              # auxv     nbytes
                    4*(len(envp) + 1),              # envp     nbytes
                    4*(len(argv) + 1),              # argv     nbytes
                    4 ]                             # argc     nbytes

  def round_up( val ):
    alignment = 16
    return (val + alignment - 1) & ~(alignment - 1)

  # calculate padding to align boundary
  # NOTE: MIPs approach (but ignored by gem5)
  #stack_nbytes[3] = 16 - (sum_(stack_nbytes[:3]) % 16)
  # NOTE: gem5 ARM approach
  stack_nbytes[3] = round_up( sum_(stack_nbytes) ) - sum_(stack_nbytes)

  def round_down( val ):
    alignment = 16
    return val & ~(alignment - 1)

  # calculate stack pointer based on size of storage needed for args
  # TODO: round to nearest page size?
  stack_ptr = round_down( stack_base - sum_( stack_nbytes ) )

  # FIXME: this offset seems really wrong, but this is how gem5 does it!
  #offset    = stack_ptr + sum_( stack_nbytes )
  offset    = stack_base

  stack_off = []
  for nbytes in stack_nbytes:
    offset -= nbytes
    stack_off.append( offset )
  # FIXME: this is fails for GEM5's hacky offset...
  #assert offset == stack_ptr

  if debug.enabled( 'bootstrap' ):
    print 'stack base', hex( stack_base )
    print 'stack min ', hex( stack_ptr )
    print 'stack size', stack_base - stack_ptr
    print
    print 'sentry ', stack_nbytes[0]
    print 'env d  ', stack_nbytes[1]
    print 'arg d  ', stack_nbytes[2]
    print 'padding', stack_nbytes[3]
    print 'auxv   ', stack_nbytes[4]
    print 'envp   ', stack_nbytes[5]
    print 'argv   ', stack_nbytes[6]
    print 'argc   ', stack_nbytes[7]

  # utility functions<commit_msg>[arm] fix bootstrap to handle cli args correctly (details)<commit_after>#=======================================================================
# bootstrap.py
#=======================================================================

from machine        import State
#from pydgin.storage import Memory

# Currently these constants are set to match gem5
memory_size = 2**27
page_size   = 8192

# MIPS stack starts at top of kuseg (0x7FFF.FFFF) and grows down
#stack_base = 0x7FFFFFFF
stack_base = memory_size-1   # TODO: set this correctly!

EMULATE_GEM5 = False

#-----------------------------------------------------------------------
# syscall_init
#-----------------------------------------------------------------------
#
# MIPS Memory Map (32-bit):
#
#   0xC000.0000 - Mapped            (kseg2) -   1GB
#   0xA000.0000 - Unmapped uncached (kseg1) - 512MB
#   0x8000.0000 - Unmapped cached   (kseg0) - 512MB
#   0x0000.0000 - 32-bit user space (kuseg) -   2GB
#
def syscall_init( mem, entrypoint, breakpoint, argv, debug ):

  #---------------------------------------------------------------------
  # memory map initialization
  #---------------------------------------------------------------------

  # TODO: for multicore allocate 8MB for each process
  #proc_stack_base[pid] = stack_base - pid * 8 * 1024 * 1024

  # top of heap (breakpoint)  # TODO: handled in load program

  # memory maps: 1GB above top of heap
  # mmap_start = mmap_end = break_point + 0x40000000

  #---------------------------------------------------------------------
  # stack argument initialization
  #---------------------------------------------------------------------
  # http://articles.manugarg.com/aboutelfauxiliaryvectors.html
  #
  #                contents         size
  #
  #   0x7FFF.FFFF  [ end marker ]               4    (NULL)
  #                [ environment str data ]   >=0
  #                [ arguments   str data ]   >=0
  #                [ padding ]               0-16
  #                [ auxv[n]  data ]            8    (AT_NULL Vector)
  #                                             8*x
  #                [ auxv[0]  data ]            8
  #                [ envp[n]  pointer ]         4    (NULL)
  #                                             4*x
  #                [ envp[0]  pointer ]         4
  #                [ argv[n]  pointer ]         4    (NULL)
  #                                             4*x
  #                [ argv[0]  pointer ]         4    (program name)
  #   stack ptr->  [ argc ]                     4    (size of argv)
  #
  #                (stack grows down!!!)
  #
  #   0x7F7F.FFFF  < stack limit for pid 0 >
  #

  # auxv variables initialized by gem5, are these needed?
  #
  # - PAGESZ:    system page size
  # - PHDR:      virtual addr of program header tables
  #              (for statically linked binaries)
  # - PHENT:     size of program header entries in elf file
  # - PHNUM:     number of program headers in elf file
  # - AT_ENRTY:  program entry point
  # - UID:       user ID
  # - EUID:      effective user ID
  # - GID:       group ID
  # - EGID:      effective group ID

  # TODO: handle auxv, envp variables
  auxv = []
  envp = []
  if EMULATE_GEM5:
    argv = argv[1:]
  argc = len( argv )

  def sum_( x ):
    val = 0
    for i in x:
      val += i
    return val

  # calculate sizes of sections
  # TODO: parameterize auxv/envp/argv calc for variable int size?
  stack_nbytes  = [ 4,                              # end mark nbytes (sentry)
                    sum_([len(x)+1 for x in envp]), # envp_str nbytes
                    sum_([len(x)+1 for x in argv]), # argv_str nbytes
                    0,                              # padding  nbytes
                    8*(len(auxv) + 1),              # auxv     nbytes
                    4*(len(envp) + 1),              # envp     nbytes
                    4*(len(argv) + 1),              # argv     nbytes
                    4 ]                             # argc     nbytes

  def round_up( val ):
    alignment = 16
    return (val + alignment - 1) & ~(alignment - 1)

  # calculate padding to align boundary
  # NOTE: MIPs approach (but ignored by gem5)
  #stack_nbytes[3] = 16 - (sum_(stack_nbytes[:3]) % 16)
  # NOTE: gem5 ARM approach
  stack_nbytes[3] = round_up( sum_(stack_nbytes) ) - sum_(stack_nbytes)

  def round_down( val ):
    alignment = 16
    return val & ~(alignment - 1)

  # calculate stack pointer based on size of storage needed for args
  # TODO: round to nearest page size?
  stack_ptr = round_down( stack_base - sum_( stack_nbytes ) )

  if EMULATE_GEM5:
    # FIXME: this offset seems really wrong, but this is how gem5 does it!
    offset  = stack_base
  else:
    offset  = stack_ptr + sum_( stack_nbytes )

  stack_off = []
  for nbytes in stack_nbytes:
    offset -= nbytes
    stack_off.append( offset )
  # FIXME: this is fails for GEM5's hacky offset...
  if not EMULATE_GEM5:
    assert offset == stack_ptr

  if debug.enabled( 'bootstrap' ):
    print 'stack base', hex( stack_base )
    print 'stack min ', hex( stack_ptr )
    print 'stack size', stack_base - stack_ptr
    print
    print 'sentry ', stack_nbytes[0]
    print 'env d  ', stack_nbytes[1]
    print 'arg d  ', stack_nbytes[2]
    print 'padding', stack_nbytes[3]
    print 'auxv   ', stack_nbytes[4]
    print 'envp   ', stack_nbytes[5]
    print 'argv   ', stack_nbytes[6]
    print 'argc   ', stack_nbytes[7]

  # utility functions
{'fraction_non_alphanumeric': 0.18897126969416125, 'fraction_numerical': 0.02761816496756256, 'mean_word_length': 1.4178803495406678, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5783645', 'n_tokens_mistral': 3330, 'n_tokens_neox': 3054, 'n_words': 935}