fd3619828e
This large patch removes the unnecessary bfd parameter from various bfd section macros and functions. The bfd is hardly ever used and if needed for the bfd_set_section_* or bfd_rename_section functions can be found via section->owner except for the com, und, abs, and ind std_section special sections. Those sections shouldn't be modified anyway. The patch also removes various bfd_get_section_<field> macros, replacing their use with bfd_section_<field>, and adds bfd_set_section_lma. I've also fixed a minor bug in gas where compressed section renaming was done directly rather than calling bfd_rename_section. This would have broken bfd_get_section_by_name and similar functions, but that hardly mattered at such a late stage in gas processing. bfd/ * bfd-in.h (bfd_get_section_name, bfd_get_section_vma), (bfd_get_section_lma, bfd_get_section_alignment), (bfd_get_section_size, bfd_get_section_flags), (bfd_get_section_userdata): Delete. (bfd_section_name, bfd_section_size, bfd_section_vma), (bfd_section_lma, bfd_section_alignment): Lose bfd parameter. (bfd_section_flags, bfd_section_userdata): New. (bfd_is_com_section): Rename parameter. * section.c (bfd_set_section_userdata, bfd_set_section_vma), (bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section), (bfd_set_section_size): Delete bfd parameter, rename section parameter. (bfd_set_section_lma): New. * bfd-in2.h: Regenerate. * mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param, update callers. * aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c, * coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c, * compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h, * elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c, * elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c, * elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c, * elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c, * elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c, * elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c, * elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c, * elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c, * elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c, * elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c, * elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c, * elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c, * elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c, * elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c, * elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c, * elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c, * elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c, * elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c, * elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c, * elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c, * mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c, * peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c, * xcofflink.c: Update throughout for bfd section macro and function changes. binutils/ * addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c, * objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c, * od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c, * resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update throughout for bfd section macro and function changes. gas/ * as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c, * read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c, * config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c, * config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c, * config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c, * config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c, * config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c, * config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c, * config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c, * config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c, * config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c, * config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c, * config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c, * config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c, * config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c, * config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c, * config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c, * config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c, * config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c, * config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for bfd section macro and function changes. * write.c (compress_debug): Use bfd_rename_section. gdb/ * aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c, * coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c, * dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c, * exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h, * hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c, * i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c, * maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c, * mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c, * objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c, * ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c, * rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c, * s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c, * solib-spu.c, * solib-svr4.c, * solib-target.c, * spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c, * symmisc.c, * symtab.c, * target.c, * windows-nat.c, * xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c, * mi/mi-interp.c: Update throughout for bfd section macro and function changes. * gcore (gcore_create_callback): Use bfd_set_section_lma. * spu-tdep.c (spu_overlay_new_objfile): Likewise. gprof/ * corefile.c, * symtab.c: Update throughout for bfd section macro and function changes. ld/ * ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c, * emultempl/aarch64elf.em, * emultempl/aix.em, * emultempl/armcoff.em, * emultempl/armelf.em, * emultempl/cr16elf.em, * emultempl/cskyelf.em, * emultempl/m68hc1xelf.em, * emultempl/m68kelf.em, * emultempl/mipself.em, * emultempl/mmix-elfnmmo.em, * emultempl/mmo.em, * emultempl/msp430.em, * emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em, * emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update throughout for bfd section macro and function changes. libctf/ * ctf-open-bfd.c: Update throughout for bfd section macro changes. opcodes/ * arc-ext.c: Update throughout for bfd section macro changes. sim/ * common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c, * erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c, * m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c, * rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c, * rx/trace.c: Update throughout for bfd section macro changes.
692 lines
20 KiB
C
692 lines
20 KiB
C
/* This file is part of the program psim.
|
|
|
|
Copyright 1994, 1995, 1996, 2003, 2004 Andrew Cagney
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
#ifndef _HW_HTAB_C_
|
|
#define _HW_HTAB_C_
|
|
|
|
#include "device_table.h"
|
|
#include "device.h"
|
|
|
|
#include "bfd.h"
|
|
|
|
|
|
/* DEVICE
|
|
|
|
|
|
htab - pseudo-device describing a PowerPC hash table
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
|
|
During the initialization of the device tree, the pseudo-device
|
|
<<htab>>, in conjunction with any child <<pte>> pseudo-devices,
|
|
will create a PowerPC hash table in memory. The hash table values
|
|
are written using dma transfers.
|
|
|
|
The size and address of the hash table are determined by properties
|
|
of the htab node.
|
|
|
|
By convention, the htab device is made a child of the
|
|
<</openprom/init>> node.
|
|
|
|
By convention, the real address of the htab is used as the htab
|
|
nodes unit address.
|
|
|
|
|
|
PROPERTIES
|
|
|
|
|
|
real-address = <address> (required)
|
|
|
|
The physical address of the hash table. The PowerPC architecture
|
|
places limitations on what is a valid hash table real-address.
|
|
|
|
|
|
nr-bytes = <size> (required)
|
|
|
|
The size of the hash table (in bytes) that is to be created at
|
|
<<real-address>>. The PowerPC architecture places limitations on
|
|
what is a valid hash table size.
|
|
|
|
|
|
claim = <anything> (optional)
|
|
|
|
If this property is present, the memory used to construct the hash
|
|
table will be claimed from the memory device. The memory device
|
|
being specified by the <</chosen/memory>> ihandle property.
|
|
|
|
|
|
EXAMPLES
|
|
|
|
Enable tracing.
|
|
|
|
| $ psim -t htab-device \
|
|
|
|
|
|
Create a htab specifying the base address and minimum size.
|
|
|
|
| -o '/openprom/init/htab@0x10000/real-address 0x10000' \
|
|
| -o '/openprom/init/htab@0x10000/claim 0' \
|
|
| -o '/openprom/init/htab@0x10000/nr-bytes 65536' \
|
|
|
|
|
|
BUGS
|
|
|
|
|
|
See the <<pte>> device.
|
|
|
|
|
|
*/
|
|
|
|
|
|
/* DEVICE
|
|
|
|
|
|
pte - pseudo-device describing a htab entry
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
|
|
The <<pte>> pseudo-device, which must be a child of a <<htabl>>
|
|
node, describes a virtual to physical mapping that is to be entered
|
|
into the parents hash table.
|
|
|
|
Two alternative specifications of the mapping are allowed. Either
|
|
a section of physical memory can be mapped to a virtual address, or
|
|
the header of an executible image can be used to define the
|
|
mapping.
|
|
|
|
By convention, the real address of the map is specified as the pte
|
|
devices unit address.
|
|
|
|
|
|
PROPERTIES
|
|
|
|
|
|
real-address = <address> (required)
|
|
|
|
The starting physical address that is to be mapped by the hash
|
|
table.
|
|
|
|
|
|
wimg = <int> (required)
|
|
pp = <int> (required)
|
|
|
|
The value of hash table protection bits that are to be used when
|
|
creating the virtual to physical address map.
|
|
|
|
|
|
claim = <anything> (optional)
|
|
|
|
If this property is present, the real memory that is being mapped by the
|
|
hash table will be claimed from the memory node (specified by the
|
|
ihandle <</chosen/memory>>).
|
|
|
|
|
|
virtual-address = <integer> [ <integer> ] (option A)
|
|
nr-bytes = <size> (option A)
|
|
|
|
Option A - Virtual virtual address (and size) at which the physical
|
|
address is to be mapped. If multiple values are specified for the
|
|
virtual address then they are concatenated to gether to form a
|
|
longer virtual address.
|
|
|
|
|
|
file-name = <string> (option B)
|
|
|
|
Option B - An executable image that is to be loaded (starting at
|
|
the physical address specified above) and then mapped in using
|
|
informatioin taken from the executables header. information found
|
|
in the files header.
|
|
|
|
|
|
EXAMPLES
|
|
|
|
|
|
Enable tracing (note that both the <<htab>> and <<pte>> device use the
|
|
same trace option).
|
|
|
|
| -t htab-device \
|
|
|
|
|
|
Map a block of physical memory into a specified virtual address:
|
|
|
|
| -o '/openprom/init/htab/pte@0x0/real-address 0' \
|
|
| -o '/openprom/init/htab/pte@0x0/nr-bytes 4096' \
|
|
| -o '/openprom/init/htab/pte@0x0/virtual-address 0x1000000' \
|
|
| -o '/openprom/init/htab/pte@0x0/claim 0' \
|
|
| -o '/openprom/init/htab/pte@0x0/wimg 0x7' \
|
|
| -o '/openprom/init/htab/pte@0x0/pp 0x2' \
|
|
|
|
|
|
Map a file into memory.
|
|
|
|
| -o '/openprom/init/htab/pte@0x10000/real-address 0x10000' \
|
|
| -o '/openprom/init/htab/pte@0x10000/file-name "netbsd.elf' \
|
|
| -o '/openprom/init/htab/pte@0x10000/wimg 0x7' \
|
|
| -o '/openprom/init/htab/pte@0x10000/pp 0x2' \
|
|
|
|
|
|
BUGS
|
|
|
|
|
|
For an ELF executable, the header defines both the virtual and real
|
|
address at which each file section should be loaded. At present, the
|
|
real addresses that are specified in the header are ignored, the file
|
|
instead being loaded in to physical memory in a linear fashion.
|
|
|
|
When claiming memory, this device assumes that the #address-cells
|
|
and #size-cells is one. For future implementations, this may not
|
|
be the case.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
htab_decode_hash_table(device *me,
|
|
unsigned32 *htaborg,
|
|
unsigned32 *htabmask)
|
|
{
|
|
unsigned_word htab_ra;
|
|
unsigned htab_nr_bytes;
|
|
unsigned n;
|
|
device *parent = device_parent(me);
|
|
/* determine the location/size of the hash table */
|
|
if (parent == NULL
|
|
|| strcmp(device_name(parent), "htab") != 0)
|
|
device_error(parent, "must be a htab device");
|
|
htab_ra = device_find_integer_property(parent, "real-address");
|
|
htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
|
|
if (htab_nr_bytes < 0x10000) {
|
|
device_error(parent, "htab size 0x%x less than 0x1000",
|
|
htab_nr_bytes);
|
|
}
|
|
for (n = htab_nr_bytes; n > 1; n = n / 2) {
|
|
if (n % 2 != 0)
|
|
device_error(parent, "htab size 0x%x not a power of two",
|
|
htab_nr_bytes);
|
|
}
|
|
*htaborg = htab_ra;
|
|
/* Position the HTABMASK ready for use against a hashed address and
|
|
not ready for insertion into SDR1.HTABMASK. */
|
|
*htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
|
|
/* Check that the MASK and ADDRESS do not overlap. */
|
|
if ((htab_ra & (*htabmask)) != 0) {
|
|
device_error(parent, "htaborg 0x%lx not aligned to htabmask 0x%lx",
|
|
(unsigned long)*htaborg, (unsigned long)*htabmask);
|
|
}
|
|
DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
|
|
(unsigned long)*htaborg, (unsigned long)*htabmask));
|
|
}
|
|
|
|
static void
|
|
htab_map_page(device *me,
|
|
unsigned_word ra,
|
|
unsigned64 va,
|
|
unsigned wimg,
|
|
unsigned pp,
|
|
unsigned32 htaborg,
|
|
unsigned32 htabmask)
|
|
{
|
|
/* keep everything left shifted so that the numbering is easier */
|
|
unsigned64 vpn = va << 12;
|
|
unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
|
|
unsigned32 vpage = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
|
|
unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
|
|
^ EXTRACTED32(vpage, 0, 15),
|
|
7, 31-6);
|
|
int h;
|
|
for (h = 0; h < 2; h++) {
|
|
unsigned32 pteg = (htaborg | (hash & htabmask));
|
|
int pti;
|
|
for (pti = 0; pti < 8; pti++) {
|
|
unsigned32 pte = pteg + 8 * pti;
|
|
unsigned32 current_target_pte0;
|
|
unsigned32 current_pte0;
|
|
if (device_dma_read_buffer(device_parent(me),
|
|
¤t_target_pte0,
|
|
0, /*space*/
|
|
pte,
|
|
sizeof(current_target_pte0)) != 4)
|
|
device_error(me, "failed to read a pte at 0x%lx", (unsigned long)pte);
|
|
current_pte0 = T2H_4(current_target_pte0);
|
|
if (MASKED32(current_pte0, 0, 0)) {
|
|
/* full pte, check it isn't already mapping the same virtual
|
|
address */
|
|
unsigned32 curr_vsid = INSERTED32(EXTRACTED32(current_pte0, 1, 24), 0, 23);
|
|
unsigned32 curr_api = INSERTED32(EXTRACTED32(current_pte0, 26, 31), 0, 5);
|
|
unsigned32 curr_h = EXTRACTED32(current_pte0, 25, 25);
|
|
if (curr_h == h
|
|
&& curr_vsid == vsid
|
|
&& curr_api == MASKED32(vpage, 0, 5))
|
|
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",
|
|
(unsigned long)va,
|
|
(unsigned long)ra,
|
|
(unsigned long)vsid,
|
|
h,
|
|
(unsigned long)vpage,
|
|
(unsigned long)hash,
|
|
(unsigned long)pteg,
|
|
pti * 8,
|
|
(unsigned long)current_pte0);
|
|
}
|
|
else {
|
|
/* empty pte fill it */
|
|
unsigned32 pte0 = (MASK32(0, 0)
|
|
| INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
|
|
| INSERTED32(h, 25, 25)
|
|
| INSERTED32(EXTRACTED32(vpage, 0, 5), 26, 31));
|
|
unsigned32 target_pte0 = H2T_4(pte0);
|
|
unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
|
|
| INSERTED32(wimg, 25, 28)
|
|
| INSERTED32(pp, 30, 31));
|
|
unsigned32 target_pte1 = H2T_4(pte1);
|
|
if (device_dma_write_buffer(device_parent(me),
|
|
&target_pte0,
|
|
0, /*space*/
|
|
pte,
|
|
sizeof(target_pte0),
|
|
1/*ro?*/) != 4
|
|
|| device_dma_write_buffer(device_parent(me),
|
|
&target_pte1,
|
|
0, /*space*/
|
|
pte + 4,
|
|
sizeof(target_pte1),
|
|
1/*ro?*/) != 4)
|
|
device_error(me, "failed to write a pte a 0x%lx", (unsigned long)pte);
|
|
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",
|
|
(unsigned long)va,
|
|
(unsigned long)ra,
|
|
(unsigned long)vsid,
|
|
h,
|
|
(unsigned long)vpage,
|
|
(unsigned long)hash,
|
|
(unsigned long)pteg,
|
|
pti * 8,
|
|
(unsigned long)pte0,
|
|
(unsigned long)pte1));
|
|
return;
|
|
}
|
|
}
|
|
/* re-hash */
|
|
hash = MASKED32(~hash, 0, 18);
|
|
}
|
|
}
|
|
|
|
static unsigned_word
|
|
claim_memory(device *me,
|
|
device_instance *memory,
|
|
unsigned_word ra,
|
|
unsigned_word size)
|
|
{
|
|
unsigned32 args[3];
|
|
unsigned32 results[1];
|
|
int status;
|
|
args[0] = 0; /* alignment */
|
|
args[1] = size;
|
|
args[2] = ra;
|
|
status = device_instance_call_method(memory, "claim", 3, args, 1, results);
|
|
if (status != 0)
|
|
device_error(me, "failed to claim memory");
|
|
return results[0];
|
|
}
|
|
|
|
static void
|
|
htab_map_region(device *me,
|
|
device_instance *memory,
|
|
unsigned_word pte_ra,
|
|
unsigned64 pte_va,
|
|
unsigned nr_bytes,
|
|
unsigned wimg,
|
|
unsigned pp,
|
|
unsigned32 htaborg,
|
|
unsigned32 htabmask)
|
|
{
|
|
unsigned_word ra;
|
|
unsigned64 va;
|
|
/* claim the memory */
|
|
if (memory != NULL)
|
|
claim_memory(me, memory, pte_ra, nr_bytes);
|
|
/* go through all pages and create a pte for each */
|
|
for (ra = pte_ra, va = pte_va;
|
|
ra < pte_ra + nr_bytes;
|
|
ra += 0x1000, va += 0x1000) {
|
|
htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
|
|
}
|
|
}
|
|
|
|
typedef struct _htab_binary_sizes {
|
|
unsigned_word text_ra;
|
|
unsigned_word text_base;
|
|
unsigned_word text_bound;
|
|
unsigned_word data_ra;
|
|
unsigned_word data_base;
|
|
unsigned data_bound;
|
|
device *me;
|
|
} htab_binary_sizes;
|
|
|
|
static void
|
|
htab_sum_binary(bfd *abfd,
|
|
sec_ptr sec,
|
|
PTR data)
|
|
{
|
|
htab_binary_sizes *sizes = (htab_binary_sizes*)data;
|
|
unsigned_word size = bfd_section_size (sec);
|
|
unsigned_word vma = bfd_section_vma (sec);
|
|
unsigned_word ra = bfd_section_lma (sec);
|
|
|
|
/* skip the section if no memory to allocate */
|
|
if (! (bfd_section_flags (sec) & SEC_ALLOC))
|
|
return;
|
|
|
|
if ((bfd_section_flags (sec) & SEC_CODE)
|
|
|| (bfd_section_flags (sec) & SEC_READONLY)) {
|
|
if (sizes->text_bound < vma + size)
|
|
sizes->text_bound = ALIGN_PAGE(vma + size);
|
|
if (sizes->text_base > vma)
|
|
sizes->text_base = FLOOR_PAGE(vma);
|
|
if (sizes->text_ra > ra)
|
|
sizes->text_ra = FLOOR_PAGE(ra);
|
|
}
|
|
else if ((bfd_section_flags (sec) & SEC_DATA)
|
|
|| (bfd_section_flags (sec) & SEC_ALLOC)) {
|
|
if (sizes->data_bound < vma + size)
|
|
sizes->data_bound = ALIGN_PAGE(vma + size);
|
|
if (sizes->data_base > vma)
|
|
sizes->data_base = FLOOR_PAGE(vma);
|
|
if (sizes->data_ra > ra)
|
|
sizes->data_ra = FLOOR_PAGE(ra);
|
|
}
|
|
}
|
|
|
|
static void
|
|
htab_dma_binary(bfd *abfd,
|
|
sec_ptr sec,
|
|
PTR data)
|
|
{
|
|
htab_binary_sizes *sizes = (htab_binary_sizes*)data;
|
|
void *section_init;
|
|
unsigned_word section_vma;
|
|
unsigned_word section_size;
|
|
unsigned_word section_ra;
|
|
device *me = sizes->me;
|
|
|
|
/* skip the section if no memory to allocate */
|
|
if (! (bfd_section_flags (sec) & SEC_ALLOC))
|
|
return;
|
|
|
|
/* check/ignore any sections of size zero */
|
|
section_size = bfd_section_size (sec);
|
|
if (section_size == 0)
|
|
return;
|
|
|
|
/* if nothing to load, ignore this one */
|
|
if (! (bfd_section_flags (sec) & SEC_LOAD))
|
|
return;
|
|
|
|
/* find where it is to go */
|
|
section_vma = bfd_section_vma (sec);
|
|
section_ra = 0;
|
|
if ((bfd_section_flags (sec) & SEC_CODE)
|
|
|| (bfd_section_flags (sec) & SEC_READONLY))
|
|
section_ra = (section_vma - sizes->text_base + sizes->text_ra);
|
|
else if ((bfd_section_flags (sec) & SEC_DATA))
|
|
section_ra = (section_vma - sizes->data_base + sizes->data_ra);
|
|
else
|
|
return; /* just ignore it */
|
|
|
|
DTRACE(htab,
|
|
("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
|
|
bfd_section_name (sec),
|
|
(long)section_vma,
|
|
(long)section_size,
|
|
(long)section_ra,
|
|
(long)bfd_section_flags (sec),
|
|
bfd_section_flags (sec) & SEC_LOAD ? " LOAD" : "",
|
|
bfd_section_flags (sec) & SEC_CODE ? " CODE" : "",
|
|
bfd_section_flags (sec) & SEC_DATA ? " DATA" : "",
|
|
bfd_section_flags (sec) & SEC_ALLOC ? " ALLOC" : "",
|
|
bfd_section_flags (sec) & SEC_READONLY ? " READONLY" : ""
|
|
));
|
|
|
|
/* dma in the sections data */
|
|
section_init = zalloc(section_size);
|
|
if (!bfd_get_section_contents(abfd,
|
|
sec,
|
|
section_init, 0,
|
|
section_size)) {
|
|
bfd_perror("devices/pte");
|
|
device_error(me, "no data loaded");
|
|
}
|
|
if (device_dma_write_buffer(device_parent(me),
|
|
section_init,
|
|
0 /*space*/,
|
|
section_ra,
|
|
section_size,
|
|
1 /*violate_read_only*/)
|
|
!= section_size)
|
|
device_error(me, "broken dma transfer");
|
|
free(section_init); /* only free if load */
|
|
}
|
|
|
|
/* create a memory map from a binaries virtual addresses to a copy of
|
|
the binary laid out linearly in memory */
|
|
|
|
static void
|
|
htab_map_binary(device *me,
|
|
device_instance *memory,
|
|
unsigned_word ra,
|
|
unsigned wimg,
|
|
unsigned pp,
|
|
const char *file_name,
|
|
unsigned32 htaborg,
|
|
unsigned32 htabmask)
|
|
{
|
|
htab_binary_sizes sizes;
|
|
bfd *image;
|
|
sizes.text_ra = -1;
|
|
sizes.data_ra = -1;
|
|
sizes.text_base = -1;
|
|
sizes.data_base = -1;
|
|
sizes.text_bound = 0;
|
|
sizes.data_bound = 0;
|
|
sizes.me = me;
|
|
|
|
/* open the file */
|
|
image = bfd_openr(file_name, NULL);
|
|
if (image == NULL) {
|
|
bfd_perror("devices/pte");
|
|
device_error(me, "the file %s not loaded", file_name);
|
|
}
|
|
|
|
/* check it is valid */
|
|
if (!bfd_check_format(image, bfd_object)) {
|
|
bfd_close(image);
|
|
device_error(me, "the file %s has an invalid binary format", file_name);
|
|
}
|
|
|
|
/* determine the size of each of the files regions */
|
|
bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
|
|
|
|
/* if needed, determine the real addresses of the sections */
|
|
if (ra != -1) {
|
|
sizes.text_ra = ra;
|
|
sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
|
|
(sizes.text_bound - sizes.text_base));
|
|
}
|
|
|
|
DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
|
|
(unsigned long)sizes.text_base,
|
|
(unsigned long)sizes.text_bound,
|
|
(unsigned long)sizes.text_ra));
|
|
DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
|
|
(unsigned long)sizes.data_base,
|
|
(unsigned long)sizes.data_bound,
|
|
(unsigned long)sizes.data_ra));
|
|
|
|
/* check for and fix a botched image (text and data segments
|
|
overlap) */
|
|
if ((sizes.text_base <= sizes.data_base
|
|
&& sizes.text_bound >= sizes.data_bound)
|
|
|| (sizes.data_base <= sizes.text_base
|
|
&& sizes.data_bound >= sizes.text_bound)
|
|
|| (sizes.text_bound > sizes.data_base
|
|
&& sizes.text_bound <= sizes.data_bound)
|
|
|| (sizes.text_base >= sizes.data_base
|
|
&& sizes.text_base < sizes.data_bound)) {
|
|
DTRACE(htab, ("text and data segment overlaped - using just data segment\n"));
|
|
/* check va->ra linear */
|
|
if ((sizes.text_base - sizes.text_ra)
|
|
!= (sizes.data_base - sizes.data_ra))
|
|
device_error(me, "overlapping but missaligned text and data segments");
|
|
/* enlarge the data segment */
|
|
if (sizes.text_base < sizes.data_base)
|
|
sizes.data_base = sizes.text_base;
|
|
if (sizes.text_bound > sizes.data_bound)
|
|
sizes.data_bound = sizes.text_bound;
|
|
if (sizes.text_ra < sizes.data_ra)
|
|
sizes.data_ra = sizes.text_ra;
|
|
/* zap the text segment */
|
|
sizes.text_base = 0;
|
|
sizes.text_bound = 0;
|
|
sizes.text_ra = 0;
|
|
DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
|
|
(unsigned long)sizes.data_base,
|
|
(unsigned long)sizes.data_bound,
|
|
(unsigned long)sizes.data_ra));
|
|
}
|
|
|
|
/* set up virtual memory maps for each of the regions */
|
|
if (sizes.text_bound - sizes.text_base > 0) {
|
|
htab_map_region(me, memory, sizes.text_ra, sizes.text_base,
|
|
sizes.text_bound - sizes.text_base,
|
|
wimg, pp,
|
|
htaborg, htabmask);
|
|
}
|
|
|
|
htab_map_region(me, memory, sizes.data_ra, sizes.data_base,
|
|
sizes.data_bound - sizes.data_base,
|
|
wimg, pp,
|
|
htaborg, htabmask);
|
|
|
|
/* dma the sections into physical memory */
|
|
bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
|
|
}
|
|
|
|
static void
|
|
htab_init_data_callback(device *me)
|
|
{
|
|
device_instance *memory = NULL;
|
|
if (WITH_TARGET_WORD_BITSIZE != 32)
|
|
device_error(me, "only 32bit targets currently suported");
|
|
|
|
/* find memory device */
|
|
if (device_find_property(me, "claim") != NULL)
|
|
memory = tree_find_ihandle_property(me, "/chosen/memory");
|
|
|
|
/* for the htab, just allocate space for it */
|
|
if (strcmp(device_name(me), "htab") == 0) {
|
|
unsigned_word address = device_find_integer_property(me, "real-address");
|
|
unsigned_word length = device_find_integer_property(me, "nr-bytes");
|
|
unsigned_word base = claim_memory(me, memory, address, length);
|
|
if (base == -1 || base != address)
|
|
device_error(me, "cannot allocate hash table");
|
|
}
|
|
|
|
/* for the pte, do all the real work */
|
|
if (strcmp(device_name(me), "pte") == 0) {
|
|
unsigned32 htaborg;
|
|
unsigned32 htabmask;
|
|
|
|
htab_decode_hash_table(me, &htaborg, &htabmask);
|
|
|
|
if (device_find_property(me, "file-name") != NULL) {
|
|
/* map in a binary */
|
|
unsigned pte_wimg = device_find_integer_property(me, "wimg");
|
|
unsigned pte_pp = device_find_integer_property(me, "pp");
|
|
const char *file_name = device_find_string_property(me, "file-name");
|
|
if (device_find_property(me, "real-address") != NULL) {
|
|
unsigned32 pte_ra = device_find_integer_property(me, "real-address");
|
|
DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
|
|
(unsigned long)pte_ra,
|
|
(unsigned long)pte_wimg,
|
|
(long)pte_pp,
|
|
file_name));
|
|
htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name,
|
|
htaborg, htabmask);
|
|
}
|
|
else {
|
|
DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n",
|
|
(unsigned long)pte_wimg,
|
|
(long)pte_pp,
|
|
file_name));
|
|
htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name,
|
|
htaborg, htabmask);
|
|
}
|
|
}
|
|
else {
|
|
/* handle a normal mapping definition */
|
|
unsigned64 pte_va = 0;
|
|
unsigned32 pte_ra = device_find_integer_property(me, "real-address");
|
|
unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
|
|
unsigned pte_wimg = device_find_integer_property(me, "wimg");
|
|
unsigned pte_pp = device_find_integer_property(me, "pp");
|
|
signed_cell partial_va;
|
|
int i;
|
|
for (i = 0;
|
|
device_find_integer_array_property(me, "virtual-address", i, &partial_va);
|
|
i++) {
|
|
pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va;
|
|
}
|
|
DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
|
|
(unsigned long)pte_ra,
|
|
(long)pte_wimg,
|
|
(long)pte_pp,
|
|
(unsigned long)pte_va,
|
|
(long)pte_nr_bytes));
|
|
htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
|
|
htaborg, htabmask);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static device_callbacks const htab_callbacks = {
|
|
{ NULL, htab_init_data_callback, },
|
|
{ NULL, }, /* address */
|
|
{ NULL, }, /* IO */
|
|
{ passthrough_device_dma_read_buffer,
|
|
passthrough_device_dma_write_buffer, },
|
|
{ NULL, }, /* interrupt */
|
|
{ generic_device_unit_decode,
|
|
generic_device_unit_encode, },
|
|
};
|
|
|
|
const device_descriptor hw_htab_device_descriptor[] = {
|
|
{ "htab", NULL, &htab_callbacks },
|
|
{ "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
|
|
{ NULL },
|
|
};
|
|
|
|
#endif /* _HW_HTAB_C_ */
|