Home | History | Annotate | Line # | Download | only in ppc
      1      1.1  christos /*  This file is part of the program psim.
      2      1.1  christos 
      3      1.1  christos     Copyright 1994, 1995, 1996, 2003, 2004 Andrew Cagney
      4      1.1  christos 
      5      1.1  christos     This program is free software; you can redistribute it and/or modify
      6      1.1  christos     it under the terms of the GNU General Public License as published by
      7  1.1.1.2  christos     the Free Software Foundation; either version 3 of the License, or
      8      1.1  christos     (at your option) any later version.
      9      1.1  christos 
     10      1.1  christos     This program is distributed in the hope that it will be useful,
     11      1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13      1.1  christos     GNU General Public License for more details.
     14      1.1  christos 
     15      1.1  christos     You should have received a copy of the GNU General Public License
     16  1.1.1.2  christos     along with this program; if not, see <http://www.gnu.org/licenses/>.
     17      1.1  christos 
     18      1.1  christos     */
     19      1.1  christos 
     20      1.1  christos 
     21      1.1  christos #ifndef _HW_HTAB_C_
     22      1.1  christos #define _HW_HTAB_C_
     23      1.1  christos 
     24      1.1  christos #include "device_table.h"
     25  1.1.1.3  christos #include "device.h"
     26      1.1  christos 
     27      1.1  christos #include "bfd.h"
     28      1.1  christos 
     29      1.1  christos 
     30      1.1  christos /* DEVICE
     31      1.1  christos 
     32      1.1  christos 
     33      1.1  christos    htab - pseudo-device describing a PowerPC hash table
     34      1.1  christos 
     35      1.1  christos 
     36      1.1  christos    DESCRIPTION
     37      1.1  christos 
     38      1.1  christos 
     39      1.1  christos    During the initialization of the device tree, the pseudo-device
     40      1.1  christos    <<htab>>, in conjunction with any child <<pte>> pseudo-devices,
     41      1.1  christos    will create a PowerPC hash table in memory.  The hash table values
     42      1.1  christos    are written using dma transfers.
     43      1.1  christos 
     44      1.1  christos    The size and address of the hash table are determined by properties
     45      1.1  christos    of the htab node.
     46      1.1  christos 
     47      1.1  christos    By convention, the htab device is made a child of the
     48      1.1  christos    <</openprom/init>> node.
     49      1.1  christos 
     50      1.1  christos    By convention, the real address of the htab is used as the htab
     51      1.1  christos    nodes unit address.
     52      1.1  christos 
     53      1.1  christos 
     54      1.1  christos    PROPERTIES
     55      1.1  christos 
     56      1.1  christos 
     57      1.1  christos    real-address = <address> (required)
     58      1.1  christos 
     59      1.1  christos    The physical address of the hash table.  The PowerPC architecture
     60      1.1  christos    places limitations on what is a valid hash table real-address.
     61      1.1  christos 
     62      1.1  christos 
     63      1.1  christos    nr-bytes = <size> (required)
     64      1.1  christos 
     65      1.1  christos    The size of the hash table (in bytes) that is to be created at
     66      1.1  christos    <<real-address>>.  The PowerPC architecture places limitations on
     67      1.1  christos    what is a valid hash table size.
     68      1.1  christos 
     69      1.1  christos 
     70      1.1  christos    claim = <anything> (optional)
     71      1.1  christos 
     72      1.1  christos    If this property is present, the memory used to construct the hash
     73      1.1  christos    table will be claimed from the memory device.  The memory device
     74      1.1  christos    being specified by the <</chosen/memory>> ihandle property.
     75      1.1  christos 
     76      1.1  christos 
     77      1.1  christos    EXAMPLES
     78      1.1  christos 
     79      1.1  christos    Enable tracing.
     80      1.1  christos 
     81      1.1  christos    |  $  psim -t htab-device \
     82      1.1  christos 
     83      1.1  christos 
     84      1.1  christos    Create a htab specifying the base address and minimum size.
     85      1.1  christos 
     86      1.1  christos    |    -o '/openprom/init/htab@0x10000/real-address 0x10000' \
     87      1.1  christos    |    -o '/openprom/init/htab@0x10000/claim 0' \
     88      1.1  christos    |    -o '/openprom/init/htab@0x10000/nr-bytes 65536' \
     89      1.1  christos 
     90      1.1  christos 
     91      1.1  christos    BUGS
     92      1.1  christos 
     93      1.1  christos 
     94      1.1  christos    See the <<pte>> device.
     95      1.1  christos 
     96      1.1  christos 
     97      1.1  christos    */
     98      1.1  christos 
     99      1.1  christos 
    100      1.1  christos /* DEVICE
    101      1.1  christos 
    102      1.1  christos 
    103      1.1  christos    pte - pseudo-device describing a htab entry
    104      1.1  christos 
    105      1.1  christos 
    106      1.1  christos    DESCRIPTION
    107      1.1  christos 
    108      1.1  christos 
    109      1.1  christos    The <<pte>> pseudo-device, which must be a child of a <<htabl>>
    110      1.1  christos    node, describes a virtual to physical mapping that is to be entered
    111      1.1  christos    into the parents hash table.
    112      1.1  christos 
    113      1.1  christos    Two alternative specifications of the mapping are allowed.  Either
    114      1.1  christos    a section of physical memory can be mapped to a virtual address, or
    115      1.1  christos    the header of an executible image can be used to define the
    116      1.1  christos    mapping.
    117      1.1  christos 
    118      1.1  christos    By convention, the real address of the map is specified as the pte
    119      1.1  christos    devices unit address.
    120      1.1  christos 
    121      1.1  christos 
    122      1.1  christos    PROPERTIES
    123      1.1  christos 
    124      1.1  christos 
    125      1.1  christos    real-address = <address> (required)
    126      1.1  christos 
    127      1.1  christos    The starting physical address that is to be mapped by the hash
    128      1.1  christos    table.
    129      1.1  christos 
    130      1.1  christos 
    131      1.1  christos    wimg = <int> (required)
    132      1.1  christos    pp = <int> (required)
    133      1.1  christos 
    134      1.1  christos    The value of hash table protection bits that are to be used when
    135      1.1  christos    creating the virtual to physical address map.
    136      1.1  christos 
    137      1.1  christos 
    138      1.1  christos    claim = <anything> (optional)
    139      1.1  christos 
    140      1.1  christos    If this property is present, the real memory that is being mapped by the
    141      1.1  christos    hash table will be claimed from the memory node (specified by the
    142      1.1  christos    ihandle <</chosen/memory>>).
    143      1.1  christos 
    144      1.1  christos 
    145      1.1  christos    virtual-address = <integer> [ <integer> ]  (option A)
    146      1.1  christos    nr-bytes = <size>  (option A)
    147      1.1  christos 
    148      1.1  christos    Option A - Virtual virtual address (and size) at which the physical
    149      1.1  christos    address is to be mapped.  If multiple values are specified for the
    150      1.1  christos    virtual address then they are concatenated to gether to form a
    151      1.1  christos    longer virtual address.
    152      1.1  christos 
    153      1.1  christos 
    154      1.1  christos    file-name = <string>  (option B)
    155      1.1  christos 
    156      1.1  christos    Option B - An executable image that is to be loaded (starting at
    157      1.1  christos    the physical address specified above) and then mapped in using
    158      1.1  christos    informatioin taken from the executables header.  information found
    159      1.1  christos    in the files header.
    160      1.1  christos 
    161      1.1  christos 
    162      1.1  christos    EXAMPLES
    163      1.1  christos 
    164      1.1  christos 
    165      1.1  christos    Enable tracing (note that both the <<htab>> and <<pte>> device use the
    166      1.1  christos    same trace option).
    167      1.1  christos 
    168      1.1  christos    |   -t htab-device \
    169      1.1  christos 
    170      1.1  christos 
    171      1.1  christos    Map a block of physical memory into a specified virtual address:
    172      1.1  christos 
    173      1.1  christos    |  -o '/openprom/init/htab/pte@0x0/real-address 0' \
    174      1.1  christos    |  -o '/openprom/init/htab/pte@0x0/nr-bytes 4096' \
    175      1.1  christos    |  -o '/openprom/init/htab/pte@0x0/virtual-address 0x1000000' \
    176      1.1  christos    |  -o '/openprom/init/htab/pte@0x0/claim 0' \
    177      1.1  christos    |  -o '/openprom/init/htab/pte@0x0/wimg 0x7' \
    178      1.1  christos    |  -o '/openprom/init/htab/pte@0x0/pp 0x2' \
    179      1.1  christos 
    180      1.1  christos 
    181      1.1  christos    Map a file into memory.
    182      1.1  christos 
    183      1.1  christos    |  -o '/openprom/init/htab/pte@0x10000/real-address 0x10000' \
    184      1.1  christos    |  -o '/openprom/init/htab/pte@0x10000/file-name "netbsd.elf' \
    185      1.1  christos    |  -o '/openprom/init/htab/pte@0x10000/wimg 0x7' \
    186      1.1  christos    |  -o '/openprom/init/htab/pte@0x10000/pp 0x2' \
    187      1.1  christos 
    188      1.1  christos 
    189      1.1  christos    BUGS
    190      1.1  christos 
    191      1.1  christos 
    192      1.1  christos    For an ELF executable, the header defines both the virtual and real
    193      1.1  christos    address at which each file section should be loaded.  At present, the
    194      1.1  christos    real addresses that are specified in the header are ignored, the file
    195      1.1  christos    instead being loaded in to physical memory in a linear fashion.
    196      1.1  christos 
    197      1.1  christos    When claiming memory, this device assumes that the #address-cells
    198      1.1  christos    and #size-cells is one.  For future implementations, this may not
    199      1.1  christos    be the case.
    200      1.1  christos 
    201      1.1  christos    */
    202      1.1  christos 
    203      1.1  christos 
    204      1.1  christos 
    205      1.1  christos static void
    206      1.1  christos htab_decode_hash_table(device *me,
    207  1.1.1.6  christos 		       uint32_t *htaborg,
    208  1.1.1.6  christos 		       uint32_t *htabmask)
    209      1.1  christos {
    210      1.1  christos   unsigned_word htab_ra;
    211      1.1  christos   unsigned htab_nr_bytes;
    212      1.1  christos   unsigned n;
    213      1.1  christos   device *parent = device_parent(me);
    214      1.1  christos   /* determine the location/size of the hash table */
    215      1.1  christos   if (parent == NULL
    216      1.1  christos       || strcmp(device_name(parent), "htab") != 0)
    217      1.1  christos     device_error(parent, "must be a htab device");
    218      1.1  christos   htab_ra = device_find_integer_property(parent, "real-address");
    219      1.1  christos   htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
    220      1.1  christos   if (htab_nr_bytes < 0x10000) {
    221      1.1  christos     device_error(parent, "htab size 0x%x less than 0x1000",
    222      1.1  christos 		 htab_nr_bytes);
    223      1.1  christos   }
    224      1.1  christos   for (n = htab_nr_bytes; n > 1; n = n / 2) {
    225      1.1  christos     if (n % 2 != 0)
    226      1.1  christos       device_error(parent, "htab size 0x%x not a power of two",
    227      1.1  christos 		   htab_nr_bytes);
    228      1.1  christos   }
    229      1.1  christos   *htaborg = htab_ra;
    230      1.1  christos   /* Position the HTABMASK ready for use against a hashed address and
    231      1.1  christos      not ready for insertion into SDR1.HTABMASK.  */
    232      1.1  christos   *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
    233      1.1  christos   /* Check that the MASK and ADDRESS do not overlap.  */
    234      1.1  christos   if ((htab_ra & (*htabmask)) != 0) {
    235      1.1  christos     device_error(parent, "htaborg 0x%lx not aligned to htabmask 0x%lx",
    236      1.1  christos 		 (unsigned long)*htaborg, (unsigned long)*htabmask);
    237      1.1  christos   }
    238      1.1  christos   DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
    239      1.1  christos 		(unsigned long)*htaborg, (unsigned long)*htabmask));
    240      1.1  christos }
    241      1.1  christos 
    242      1.1  christos static void
    243      1.1  christos htab_map_page(device *me,
    244      1.1  christos 	      unsigned_word ra,
    245  1.1.1.6  christos 	      uint64_t va,
    246      1.1  christos 	      unsigned wimg,
    247      1.1  christos 	      unsigned pp,
    248  1.1.1.6  christos 	      uint32_t htaborg,
    249  1.1.1.6  christos 	      uint32_t htabmask)
    250      1.1  christos {
    251      1.1  christos   /* keep everything left shifted so that the numbering is easier */
    252  1.1.1.6  christos   uint64_t vpn = va << 12;
    253  1.1.1.6  christos   uint32_t vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
    254  1.1.1.6  christos   uint32_t vpage = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
    255  1.1.1.6  christos   uint32_t hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
    256      1.1  christos 			       ^ EXTRACTED32(vpage, 0, 15),
    257      1.1  christos 			       7, 31-6);
    258      1.1  christos   int h;
    259      1.1  christos   for (h = 0; h < 2; h++) {
    260  1.1.1.6  christos     uint32_t pteg = (htaborg | (hash & htabmask));
    261      1.1  christos     int pti;
    262      1.1  christos     for (pti = 0; pti < 8; pti++) {
    263  1.1.1.6  christos       uint32_t pte = pteg + 8 * pti;
    264  1.1.1.6  christos       uint32_t current_target_pte0;
    265  1.1.1.6  christos       uint32_t current_pte0;
    266      1.1  christos       if (device_dma_read_buffer(device_parent(me),
    267      1.1  christos 				 &current_target_pte0,
    268      1.1  christos 				 0, /*space*/
    269      1.1  christos 				 pte,
    270      1.1  christos 				 sizeof(current_target_pte0)) != 4)
    271      1.1  christos 	device_error(me, "failed to read a pte at 0x%lx", (unsigned long)pte);
    272      1.1  christos       current_pte0 = T2H_4(current_target_pte0);
    273      1.1  christos       if (MASKED32(current_pte0, 0, 0)) {
    274      1.1  christos 	/* full pte, check it isn't already mapping the same virtual
    275      1.1  christos            address */
    276  1.1.1.6  christos 	uint32_t curr_vsid = INSERTED32(EXTRACTED32(current_pte0, 1, 24), 0, 23);
    277  1.1.1.6  christos 	uint32_t curr_api = INSERTED32(EXTRACTED32(current_pte0, 26, 31), 0, 5);
    278  1.1.1.6  christos 	uint32_t curr_h = EXTRACTED32(current_pte0, 25, 25);
    279      1.1  christos 	if (curr_h == h
    280      1.1  christos 	    && curr_vsid == vsid
    281      1.1  christos 	    && curr_api == MASKED32(vpage, 0, 5))
    282      1.1  christos 	  device_error(me, "duplicate map - va=0x%08lx ra=0x%lx vsid=0x%lx h=%d vpage=0x%lx hash=0x%lx pteg=0x%lx+%2d pte0=0x%lx",
    283      1.1  christos 		       (unsigned long)va,
    284      1.1  christos 		       (unsigned long)ra,
    285      1.1  christos 		       (unsigned long)vsid,
    286      1.1  christos 		       h,
    287      1.1  christos 		       (unsigned long)vpage,
    288      1.1  christos 		       (unsigned long)hash,
    289      1.1  christos 		       (unsigned long)pteg,
    290      1.1  christos 		       pti * 8,
    291      1.1  christos 		       (unsigned long)current_pte0);
    292      1.1  christos       }
    293      1.1  christos       else {
    294      1.1  christos 	/* empty pte fill it */
    295  1.1.1.6  christos 	uint32_t pte0 = (MASK32(0, 0)
    296      1.1  christos 			   | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
    297      1.1  christos 			   | INSERTED32(h, 25, 25)
    298      1.1  christos 			   | INSERTED32(EXTRACTED32(vpage, 0, 5), 26, 31));
    299  1.1.1.6  christos 	uint32_t target_pte0 = H2T_4(pte0);
    300  1.1.1.6  christos 	uint32_t pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
    301      1.1  christos 			   | INSERTED32(wimg, 25, 28)
    302      1.1  christos 			   | INSERTED32(pp, 30, 31));
    303  1.1.1.6  christos 	uint32_t target_pte1 = H2T_4(pte1);
    304      1.1  christos 	if (device_dma_write_buffer(device_parent(me),
    305      1.1  christos 				    &target_pte0,
    306      1.1  christos 				    0, /*space*/
    307      1.1  christos 				    pte,
    308      1.1  christos 				    sizeof(target_pte0),
    309      1.1  christos 				    1/*ro?*/) != 4
    310      1.1  christos 	    || device_dma_write_buffer(device_parent(me),
    311      1.1  christos 				       &target_pte1,
    312      1.1  christos 				       0, /*space*/
    313      1.1  christos 				       pte + 4,
    314      1.1  christos 				       sizeof(target_pte1),
    315      1.1  christos 				       1/*ro?*/) != 4)
    316      1.1  christos 	  device_error(me, "failed to write a pte a 0x%lx", (unsigned long)pte);
    317      1.1  christos 	DTRACE(htab, ("map - va=0x%08lx ra=0x%lx vsid=0x%lx h=%d vpage=0x%lx hash=0x%lx pteg=0x%lx+%2d pte0=0x%lx pte1=0x%lx\n",
    318      1.1  christos 		      (unsigned long)va,
    319      1.1  christos 		      (unsigned long)ra,
    320      1.1  christos 		      (unsigned long)vsid,
    321      1.1  christos 		      h,
    322      1.1  christos 		      (unsigned long)vpage,
    323      1.1  christos 		      (unsigned long)hash,
    324      1.1  christos 		      (unsigned long)pteg,
    325      1.1  christos 		      pti * 8,
    326      1.1  christos 		      (unsigned long)pte0,
    327      1.1  christos 		      (unsigned long)pte1));
    328      1.1  christos 	return;
    329      1.1  christos       }
    330      1.1  christos     }
    331      1.1  christos     /* re-hash */
    332      1.1  christos     hash = MASKED32(~hash, 0, 18);
    333      1.1  christos   }
    334      1.1  christos }
    335      1.1  christos 
    336      1.1  christos static unsigned_word
    337      1.1  christos claim_memory(device *me,
    338      1.1  christos 	     device_instance *memory,
    339      1.1  christos 	     unsigned_word ra,
    340      1.1  christos 	     unsigned_word size)
    341      1.1  christos {
    342  1.1.1.6  christos   uint32_t args[3];
    343  1.1.1.6  christos   uint32_t results[1];
    344      1.1  christos   int status;
    345      1.1  christos   args[0] = 0; /* alignment */
    346      1.1  christos   args[1] = size;
    347      1.1  christos   args[2] = ra;
    348      1.1  christos   status = device_instance_call_method(memory, "claim", 3, args, 1, results);
    349      1.1  christos   if (status != 0)
    350      1.1  christos     device_error(me, "failed to claim memory");
    351      1.1  christos   return results[0];
    352      1.1  christos }
    353      1.1  christos 
    354      1.1  christos static void
    355      1.1  christos htab_map_region(device *me,
    356      1.1  christos 		device_instance *memory,
    357      1.1  christos 		unsigned_word pte_ra,
    358  1.1.1.6  christos 		uint64_t pte_va,
    359      1.1  christos 		unsigned nr_bytes,
    360      1.1  christos 		unsigned wimg,
    361      1.1  christos 		unsigned pp,
    362  1.1.1.6  christos 		uint32_t htaborg,
    363  1.1.1.6  christos 		uint32_t htabmask)
    364      1.1  christos {
    365      1.1  christos   unsigned_word ra;
    366  1.1.1.6  christos   uint64_t va;
    367      1.1  christos   /* claim the memory */
    368      1.1  christos   if (memory != NULL)
    369      1.1  christos     claim_memory(me, memory, pte_ra, nr_bytes);
    370      1.1  christos   /* go through all pages and create a pte for each */
    371      1.1  christos   for (ra = pte_ra, va = pte_va;
    372      1.1  christos        ra < pte_ra + nr_bytes;
    373      1.1  christos        ra += 0x1000, va += 0x1000) {
    374      1.1  christos     htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
    375      1.1  christos   }
    376      1.1  christos }
    377      1.1  christos 
    378      1.1  christos typedef struct _htab_binary_sizes {
    379      1.1  christos   unsigned_word text_ra;
    380      1.1  christos   unsigned_word text_base;
    381      1.1  christos   unsigned_word text_bound;
    382      1.1  christos   unsigned_word data_ra;
    383      1.1  christos   unsigned_word data_base;
    384      1.1  christos   unsigned data_bound;
    385      1.1  christos   device *me;
    386      1.1  christos } htab_binary_sizes;
    387      1.1  christos 
    388      1.1  christos static void
    389      1.1  christos htab_sum_binary(bfd *abfd,
    390      1.1  christos 		sec_ptr sec,
    391  1.1.1.6  christos 		void *data)
    392      1.1  christos {
    393      1.1  christos   htab_binary_sizes *sizes = (htab_binary_sizes*)data;
    394  1.1.1.5  christos   unsigned_word size = bfd_section_size (sec);
    395  1.1.1.5  christos   unsigned_word vma = bfd_section_vma (sec);
    396  1.1.1.5  christos   unsigned_word ra = bfd_section_lma (sec);
    397      1.1  christos 
    398      1.1  christos   /* skip the section if no memory to allocate */
    399  1.1.1.5  christos   if (! (bfd_section_flags (sec) & SEC_ALLOC))
    400      1.1  christos     return;
    401      1.1  christos 
    402  1.1.1.5  christos   if ((bfd_section_flags (sec) & SEC_CODE)
    403  1.1.1.5  christos       || (bfd_section_flags (sec) & SEC_READONLY)) {
    404      1.1  christos     if (sizes->text_bound < vma + size)
    405      1.1  christos       sizes->text_bound = ALIGN_PAGE(vma + size);
    406      1.1  christos     if (sizes->text_base > vma)
    407      1.1  christos       sizes->text_base = FLOOR_PAGE(vma);
    408      1.1  christos     if (sizes->text_ra > ra)
    409      1.1  christos       sizes->text_ra = FLOOR_PAGE(ra);
    410      1.1  christos   }
    411  1.1.1.5  christos   else if ((bfd_section_flags (sec) & SEC_DATA)
    412  1.1.1.5  christos 	   || (bfd_section_flags (sec) & SEC_ALLOC)) {
    413      1.1  christos     if (sizes->data_bound < vma + size)
    414      1.1  christos       sizes->data_bound = ALIGN_PAGE(vma + size);
    415      1.1  christos     if (sizes->data_base > vma)
    416      1.1  christos       sizes->data_base = FLOOR_PAGE(vma);
    417      1.1  christos     if (sizes->data_ra > ra)
    418      1.1  christos       sizes->data_ra = FLOOR_PAGE(ra);
    419      1.1  christos   }
    420      1.1  christos }
    421      1.1  christos 
    422      1.1  christos static void
    423      1.1  christos htab_dma_binary(bfd *abfd,
    424      1.1  christos 		sec_ptr sec,
    425  1.1.1.6  christos 		void *data)
    426      1.1  christos {
    427      1.1  christos   htab_binary_sizes *sizes = (htab_binary_sizes*)data;
    428      1.1  christos   void *section_init;
    429      1.1  christos   unsigned_word section_vma;
    430      1.1  christos   unsigned_word section_size;
    431      1.1  christos   unsigned_word section_ra;
    432      1.1  christos   device *me = sizes->me;
    433      1.1  christos 
    434      1.1  christos   /* skip the section if no memory to allocate */
    435  1.1.1.5  christos   if (! (bfd_section_flags (sec) & SEC_ALLOC))
    436      1.1  christos     return;
    437      1.1  christos 
    438      1.1  christos   /* check/ignore any sections of size zero */
    439  1.1.1.5  christos   section_size = bfd_section_size (sec);
    440      1.1  christos   if (section_size == 0)
    441      1.1  christos     return;
    442      1.1  christos 
    443      1.1  christos   /* if nothing to load, ignore this one */
    444  1.1.1.5  christos   if (! (bfd_section_flags (sec) & SEC_LOAD))
    445      1.1  christos     return;
    446      1.1  christos 
    447      1.1  christos   /* find where it is to go */
    448  1.1.1.5  christos   section_vma = bfd_section_vma (sec);
    449      1.1  christos   section_ra = 0;
    450  1.1.1.5  christos   if ((bfd_section_flags (sec) & SEC_CODE)
    451  1.1.1.5  christos       || (bfd_section_flags (sec) & SEC_READONLY))
    452      1.1  christos     section_ra = (section_vma - sizes->text_base + sizes->text_ra);
    453  1.1.1.5  christos   else if ((bfd_section_flags (sec) & SEC_DATA))
    454      1.1  christos     section_ra = (section_vma - sizes->data_base + sizes->data_ra);
    455      1.1  christos   else
    456      1.1  christos     return; /* just ignore it */
    457      1.1  christos 
    458      1.1  christos   DTRACE(htab,
    459      1.1  christos 	 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
    460  1.1.1.5  christos 	  bfd_section_name (sec),
    461      1.1  christos 	  (long)section_vma,
    462      1.1  christos 	  (long)section_size,
    463      1.1  christos 	  (long)section_ra,
    464  1.1.1.5  christos 	  (long)bfd_section_flags (sec),
    465  1.1.1.5  christos 	  bfd_section_flags (sec) & SEC_LOAD ? " LOAD" : "",
    466  1.1.1.5  christos 	  bfd_section_flags (sec) & SEC_CODE ? " CODE" : "",
    467  1.1.1.5  christos 	  bfd_section_flags (sec) & SEC_DATA ? " DATA" : "",
    468  1.1.1.5  christos 	  bfd_section_flags (sec) & SEC_ALLOC ? " ALLOC" : "",
    469  1.1.1.5  christos 	  bfd_section_flags (sec) & SEC_READONLY ? " READONLY" : ""
    470      1.1  christos 	  ));
    471      1.1  christos 
    472      1.1  christos   /* dma in the sections data */
    473      1.1  christos   section_init = zalloc(section_size);
    474      1.1  christos   if (!bfd_get_section_contents(abfd,
    475      1.1  christos 				sec,
    476      1.1  christos 				section_init, 0,
    477      1.1  christos 				section_size)) {
    478      1.1  christos     bfd_perror("devices/pte");
    479      1.1  christos     device_error(me, "no data loaded");
    480      1.1  christos   }
    481      1.1  christos   if (device_dma_write_buffer(device_parent(me),
    482      1.1  christos 			      section_init,
    483      1.1  christos 			      0 /*space*/,
    484      1.1  christos 			      section_ra,
    485      1.1  christos 			      section_size,
    486      1.1  christos 			      1 /*violate_read_only*/)
    487      1.1  christos       != section_size)
    488      1.1  christos     device_error(me, "broken dma transfer");
    489      1.1  christos   free(section_init); /* only free if load */
    490      1.1  christos }
    491      1.1  christos 
    492      1.1  christos /* create a memory map from a binaries virtual addresses to a copy of
    493      1.1  christos    the binary laid out linearly in memory */
    494      1.1  christos 
    495      1.1  christos static void
    496      1.1  christos htab_map_binary(device *me,
    497      1.1  christos 		device_instance *memory,
    498      1.1  christos 		unsigned_word ra,
    499      1.1  christos 		unsigned wimg,
    500      1.1  christos 		unsigned pp,
    501      1.1  christos 		const char *file_name,
    502  1.1.1.6  christos 		uint32_t htaborg,
    503  1.1.1.6  christos 		uint32_t htabmask)
    504      1.1  christos {
    505      1.1  christos   htab_binary_sizes sizes;
    506      1.1  christos   bfd *image;
    507      1.1  christos   sizes.text_ra = -1;
    508      1.1  christos   sizes.data_ra = -1;
    509      1.1  christos   sizes.text_base = -1;
    510      1.1  christos   sizes.data_base = -1;
    511      1.1  christos   sizes.text_bound = 0;
    512      1.1  christos   sizes.data_bound = 0;
    513      1.1  christos   sizes.me = me;
    514      1.1  christos 
    515      1.1  christos   /* open the file */
    516      1.1  christos   image = bfd_openr(file_name, NULL);
    517      1.1  christos   if (image == NULL) {
    518      1.1  christos     bfd_perror("devices/pte");
    519      1.1  christos     device_error(me, "the file %s not loaded", file_name);
    520      1.1  christos   }
    521      1.1  christos 
    522      1.1  christos   /* check it is valid */
    523      1.1  christos   if (!bfd_check_format(image, bfd_object)) {
    524      1.1  christos     bfd_close(image);
    525      1.1  christos     device_error(me, "the file %s has an invalid binary format", file_name);
    526      1.1  christos   }
    527      1.1  christos 
    528      1.1  christos   /* determine the size of each of the files regions */
    529  1.1.1.6  christos   bfd_map_over_sections (image, htab_sum_binary, &sizes);
    530      1.1  christos 
    531      1.1  christos   /* if needed, determine the real addresses of the sections */
    532      1.1  christos   if (ra != -1) {
    533      1.1  christos     sizes.text_ra = ra;
    534      1.1  christos     sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
    535      1.1  christos 			       (sizes.text_bound - sizes.text_base));
    536      1.1  christos   }
    537      1.1  christos 
    538      1.1  christos   DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
    539      1.1  christos 		(unsigned long)sizes.text_base,
    540      1.1  christos 		(unsigned long)sizes.text_bound,
    541      1.1  christos 		(unsigned long)sizes.text_ra));
    542      1.1  christos   DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
    543      1.1  christos 		(unsigned long)sizes.data_base,
    544      1.1  christos 		(unsigned long)sizes.data_bound,
    545      1.1  christos 		(unsigned long)sizes.data_ra));
    546      1.1  christos 
    547      1.1  christos   /* check for and fix a botched image (text and data segments
    548      1.1  christos      overlap) */
    549      1.1  christos   if ((sizes.text_base <= sizes.data_base
    550      1.1  christos        && sizes.text_bound >= sizes.data_bound)
    551      1.1  christos       || (sizes.data_base <= sizes.text_base
    552  1.1.1.4  christos 	  && sizes.data_bound >= sizes.text_bound)
    553      1.1  christos       || (sizes.text_bound > sizes.data_base
    554      1.1  christos 	  && sizes.text_bound <= sizes.data_bound)
    555      1.1  christos       || (sizes.text_base >= sizes.data_base
    556      1.1  christos 	  && sizes.text_base < sizes.data_bound)) {
    557      1.1  christos     DTRACE(htab, ("text and data segment overlaped - using just data segment\n"));
    558      1.1  christos     /* check va->ra linear */
    559      1.1  christos     if ((sizes.text_base - sizes.text_ra)
    560      1.1  christos 	!= (sizes.data_base - sizes.data_ra))
    561      1.1  christos       device_error(me, "overlapping but missaligned text and data segments");
    562      1.1  christos     /* enlarge the data segment */
    563      1.1  christos     if (sizes.text_base < sizes.data_base)
    564      1.1  christos       sizes.data_base = sizes.text_base;
    565      1.1  christos     if (sizes.text_bound > sizes.data_bound)
    566      1.1  christos       sizes.data_bound = sizes.text_bound;
    567      1.1  christos     if (sizes.text_ra < sizes.data_ra)
    568      1.1  christos       sizes.data_ra = sizes.text_ra;
    569      1.1  christos     /* zap the text segment */
    570      1.1  christos     sizes.text_base = 0;
    571      1.1  christos     sizes.text_bound = 0;
    572      1.1  christos     sizes.text_ra = 0;
    573      1.1  christos     DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
    574      1.1  christos 		  (unsigned long)sizes.data_base,
    575      1.1  christos 		  (unsigned long)sizes.data_bound,
    576      1.1  christos 		  (unsigned long)sizes.data_ra));
    577      1.1  christos   }
    578      1.1  christos 
    579      1.1  christos   /* set up virtual memory maps for each of the regions */
    580      1.1  christos   if (sizes.text_bound - sizes.text_base > 0) {
    581      1.1  christos     htab_map_region(me, memory, sizes.text_ra, sizes.text_base,
    582      1.1  christos 		    sizes.text_bound - sizes.text_base,
    583      1.1  christos 		    wimg, pp,
    584      1.1  christos 		    htaborg, htabmask);
    585      1.1  christos   }
    586      1.1  christos 
    587      1.1  christos   htab_map_region(me, memory, sizes.data_ra, sizes.data_base,
    588      1.1  christos 		  sizes.data_bound - sizes.data_base,
    589      1.1  christos 		  wimg, pp,
    590      1.1  christos 		  htaborg, htabmask);
    591      1.1  christos 
    592      1.1  christos   /* dma the sections into physical memory */
    593  1.1.1.6  christos   bfd_map_over_sections (image, htab_dma_binary, &sizes);
    594      1.1  christos }
    595      1.1  christos 
    596      1.1  christos static void
    597      1.1  christos htab_init_data_callback(device *me)
    598      1.1  christos {
    599      1.1  christos   device_instance *memory = NULL;
    600      1.1  christos   if (WITH_TARGET_WORD_BITSIZE != 32)
    601      1.1  christos     device_error(me, "only 32bit targets currently suported");
    602      1.1  christos 
    603      1.1  christos   /* find memory device */
    604      1.1  christos   if (device_find_property(me, "claim") != NULL)
    605      1.1  christos     memory = tree_find_ihandle_property(me, "/chosen/memory");
    606      1.1  christos 
    607      1.1  christos   /* for the htab, just allocate space for it */
    608      1.1  christos   if (strcmp(device_name(me), "htab") == 0) {
    609      1.1  christos     unsigned_word address = device_find_integer_property(me, "real-address");
    610      1.1  christos     unsigned_word length = device_find_integer_property(me, "nr-bytes");
    611      1.1  christos     unsigned_word base = claim_memory(me, memory, address, length);
    612      1.1  christos     if (base == -1 || base != address)
    613      1.1  christos       device_error(me, "cannot allocate hash table");
    614      1.1  christos   }
    615      1.1  christos 
    616      1.1  christos   /* for the pte, do all the real work */
    617      1.1  christos   if (strcmp(device_name(me), "pte") == 0) {
    618  1.1.1.6  christos     uint32_t htaborg;
    619  1.1.1.6  christos     uint32_t htabmask;
    620      1.1  christos 
    621      1.1  christos     htab_decode_hash_table(me, &htaborg, &htabmask);
    622      1.1  christos 
    623      1.1  christos     if (device_find_property(me, "file-name") != NULL) {
    624      1.1  christos       /* map in a binary */
    625      1.1  christos       unsigned pte_wimg = device_find_integer_property(me, "wimg");
    626      1.1  christos       unsigned pte_pp = device_find_integer_property(me, "pp");
    627      1.1  christos       const char *file_name = device_find_string_property(me, "file-name");
    628      1.1  christos       if (device_find_property(me, "real-address") != NULL) {
    629  1.1.1.6  christos 	uint32_t pte_ra = device_find_integer_property(me, "real-address");
    630      1.1  christos 	DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
    631      1.1  christos 		      (unsigned long)pte_ra,
    632      1.1  christos 		      (unsigned long)pte_wimg,
    633      1.1  christos 		      (long)pte_pp,
    634      1.1  christos 		      file_name));
    635      1.1  christos 	htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name,
    636      1.1  christos 			htaborg, htabmask);
    637      1.1  christos       }
    638      1.1  christos       else {
    639      1.1  christos 	DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n",
    640      1.1  christos 		      (unsigned long)pte_wimg,
    641      1.1  christos 		      (long)pte_pp,
    642      1.1  christos 		      file_name));
    643      1.1  christos 	htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name,
    644      1.1  christos 			htaborg, htabmask);
    645      1.1  christos       }
    646      1.1  christos     }
    647      1.1  christos     else {
    648      1.1  christos       /* handle a normal mapping definition */
    649  1.1.1.6  christos       uint64_t pte_va = 0;
    650  1.1.1.6  christos       uint32_t pte_ra = device_find_integer_property(me, "real-address");
    651      1.1  christos       unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
    652      1.1  christos       unsigned pte_wimg = device_find_integer_property(me, "wimg");
    653      1.1  christos       unsigned pte_pp = device_find_integer_property(me, "pp");
    654      1.1  christos       signed_cell partial_va;
    655      1.1  christos       int i;
    656      1.1  christos       for (i = 0;
    657      1.1  christos 	   device_find_integer_array_property(me, "virtual-address", i, &partial_va);
    658      1.1  christos 	   i++) {
    659      1.1  christos 	pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va;
    660      1.1  christos       }
    661      1.1  christos       DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
    662      1.1  christos 		    (unsigned long)pte_ra,
    663      1.1  christos 		    (long)pte_wimg,
    664      1.1  christos 		    (long)pte_pp,
    665      1.1  christos 		    (unsigned long)pte_va,
    666      1.1  christos 		    (long)pte_nr_bytes));
    667      1.1  christos       htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
    668      1.1  christos 		      htaborg, htabmask);
    669      1.1  christos     }
    670      1.1  christos   }
    671      1.1  christos }
    672      1.1  christos 
    673      1.1  christos 
    674      1.1  christos static device_callbacks const htab_callbacks = {
    675      1.1  christos   { NULL, htab_init_data_callback, },
    676      1.1  christos   { NULL, }, /* address */
    677      1.1  christos   { NULL, }, /* IO */
    678      1.1  christos   { passthrough_device_dma_read_buffer,
    679      1.1  christos     passthrough_device_dma_write_buffer, },
    680      1.1  christos   { NULL, }, /* interrupt */
    681      1.1  christos   { generic_device_unit_decode,
    682      1.1  christos     generic_device_unit_encode, },
    683      1.1  christos };
    684      1.1  christos 
    685      1.1  christos const device_descriptor hw_htab_device_descriptor[] = {
    686      1.1  christos   { "htab", NULL, &htab_callbacks },
    687      1.1  christos   { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
    688      1.1  christos   { NULL },
    689      1.1  christos };
    690      1.1  christos 
    691      1.1  christos #endif /* _HW_HTAB_C_ */
    692