1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _DEVICE_TABLE_C_
23 #define _DEVICE_TABLE_C_
25 #ifndef STATIC_INLINE_DEVICE_TABLE
26 #define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
35 #include "device_table.h"
51 /* Helper functions */
53 /* Generic device init: Attaches the device of size <nr_bytes> (taken
54 from <name>@<int>,<nr_bytes>) to its parent at address zero and
55 with read/write access. */
57 typedef struct _generic_reg_spec
{
64 generic_device_init_address(device
*me
)
66 const device_property
*reg
= device_find_array_property(me
, "reg");
67 const generic_reg_spec
*spec
= reg
->array
;
68 int nr_entries
= reg
->sizeof_array
/ sizeof(generic_reg_spec
);
70 if ((reg
->sizeof_array
% sizeof(generic_reg_spec
)) != 0)
71 error("devices/%s reg property is of wrong size\n", device_name(me
));
73 while (nr_entries
> 0) {
74 device_attach_address(device_parent(me
),
80 access_read_write_exec
,
88 generic_device_unit_decode(device
*me
,
92 memset(phys
, 0, sizeof(device_unit
));
96 char *pos
= (char*)unit
; /* force for strtoul() */
99 long int val
= strtoul(pos
, &pos
, 0);
100 if (old_pos
== pos
&& *pos
== '\0')
101 return phys
->nr_cells
;
102 if (old_pos
== pos
&& *pos
!= '\0')
104 if (phys
->nr_cells
== 4)
106 phys
->cells
[phys
->nr_cells
] = val
;
113 generic_device_unit_encode(device
*me
,
114 const device_unit
*phys
,
120 char *pos
= buf
; /* force for strtoul() */
121 for (i
= 0; i
< phys
->nr_cells
; i
++) {
124 pos
= strchr(pos
, '\0');
126 sprintf(pos
, "0x%lx", (unsigned long)phys
->cells
[i
]);
127 pos
= strchr(pos
, '\0');
130 if (len
>= sizeof_buf
)
131 error("generic_unit_encode - buffer overflow\n");
135 /* DMA a file into memory */
136 STATIC_INLINE_DEVICE_TABLE
int
138 const char *file_name
,
147 image
= fopen(file_name
, "r");
151 /* read it in slowly */
154 inc
= fread(buf
, 1, sizeof(buf
), image
);
155 if (feof(image
) || ferror(image
))
157 if (device_dma_write_buffer(device_parent(me
),
162 1 /*violate ro*/) != inc
) {
169 /* close down again */
177 /* ignore/passthrough versions of each function */
180 passthrough_device_address_attach(device
*me
,
187 device
*who
) /*callback/default*/
189 device_attach_address(device_parent(me
), name
, attach
,
190 space
, addr
, nr_bytes
,
196 passthrough_device_address_detach(device
*me
,
203 device
*who
) /*callback/default*/
205 device_detach_address(device_parent(me
), name
, attach
,
206 space
, addr
, nr_bytes
, access
,
211 passthrough_device_dma_read_buffer(device
*me
,
217 return device_dma_read_buffer(device_parent(me
), dest
,
218 space
, addr
, nr_bytes
);
222 passthrough_device_dma_write_buffer(device
*me
,
227 int violate_read_only_section
)
229 return device_dma_write_buffer(device_parent(me
), source
,
232 violate_read_only_section
);
236 ignore_device_unit_decode(device
*me
,
240 memset(phys
, 0, sizeof(device_unit
));
245 static const device_callbacks passthrough_callbacks
= {
246 { NULL
, }, /* init */
247 { passthrough_device_address_attach
,
248 passthrough_device_address_detach
, },
250 { passthrough_device_dma_read_buffer
, passthrough_device_dma_write_buffer
, },
251 { NULL
, }, /* interrupt */
252 { generic_device_unit_decode
,
253 generic_device_unit_encode
, },
258 /* Register init device: register@<nothing>
260 Properties attached to the register device specify the name/value
261 initialization pair for cpu registers.
263 A specific processor can be initialized by creating a property with
266 Properties are normally processed old-to-new and this function
267 needs to allow older (first in) properties to override new (last
268 in) ones. The suport function do_register_init() manages this. */
271 do_register_init(device
*me
,
272 const device_property
*prop
)
274 psim
*system
= device_system(me
);
276 const char *name
= prop
->name
;
277 unsigned32 value
= device_find_integer_property(me
, name
);
280 do_register_init(me
, device_next_property(prop
));
282 if (strchr(name
, '.') == NULL
) {
284 DTRACE(register, ("%s=0x%lx\n", name
, (unsigned long)value
));
288 processor
= strtoul(name
, &end
, 0);
289 ASSERT(end
[0] == '.');
291 DTRACE(register, ("%d.%s=0x%lx\n", processor
, name
,
292 (unsigned long)value
));
294 psim_write_register(system
, processor
, /* all processors */
303 register_init_data_callback(device
*me
)
305 const device_property
*prop
= device_find_property(me
, NULL
);
306 do_register_init(me
, prop
);
310 static device_callbacks
const register_callbacks
= {
311 { NULL
, register_init_data_callback
, },
312 { NULL
, }, /* address */
315 { NULL
, }, /* interrupt */
316 { NULL
, }, /* unit */
323 Properties attached to the trace device are names and values for
324 the various trace variables. When initialized trace goes through
325 the propertie and sets the global trace variables so that they
326 match what was specified in the device tree. */
329 trace_init_data_callback(device
*me
)
331 const device_property
*prop
= device_find_property(me
, NULL
);
332 while (prop
!= NULL
) {
333 const char *name
= prop
->name
;
334 unsigned32 value
= device_find_integer_property(me
, name
);
335 trace_option(name
, value
);
336 prop
= device_next_property(prop
);
341 static device_callbacks
const trace_callbacks
= {
342 { NULL
, trace_init_data_callback
, },
343 { NULL
, }, /* address */
346 { NULL
, }, /* interrupt */
347 { NULL
, }, /* unit */
358 A VEA mode device. This sets its self up as the default memory
359 device capturing all accesses (reads/writes) to currently unmapped
360 addresses. If the unmaped access falls within unallocated stack or
361 heap address ranges then memory is allocated and the access is
364 During init phase, this device expects to receive `attach' requests
365 from its children for the text/data/bss memory areas. Typically,
366 this would be done by the binary device.
368 STACK: The location of the stack in memory is specified as part of
369 the devices name. Unmaped accesses that fall within the stack
370 space result in the allocated stack being grown downwards so that
371 it includes the page of the culprit access.
373 HEAP: During initialization, the vm device monitors all `attach'
374 operations from its children using this to determine the initial
375 location of the heap. The heap is then extended by system calls
376 that frob the heap upper bound variable (see system.c). */
379 typedef struct _vm_device
{
380 /* area of memory valid for stack addresses */
381 unsigned_word stack_base
; /* min possible stack value */
382 unsigned_word stack_bound
;
383 unsigned_word stack_lower_limit
;
384 /* area of memory valid for heap addresses */
385 unsigned_word heap_base
;
386 unsigned_word heap_bound
;
387 unsigned_word heap_upper_limit
;
392 vm_init_address_callback(device
*me
)
394 vm_device
*vm
= (vm_device
*)device_data(me
);
396 /* revert the stack/heap variables to their defaults */
397 vm
->stack_base
= device_find_integer_property(me
, "stack-base");
398 vm
->stack_bound
= (vm
->stack_base
399 + device_find_integer_property(me
, "nr-bytes"));
400 vm
->stack_lower_limit
= vm
->stack_bound
;
403 vm
->heap_upper_limit
= 0;
405 /* establish this device as the default memory handler */
406 device_attach_address(device_parent(me
),
409 0 /*address space - ignore*/,
411 (((unsigned)0)-1) /*nr_bytes - ignore*/,
412 access_read_write
/*access*/,
418 vm_attach_address(device
*me
,
425 device
*who
) /*callback/default*/
427 vm_device
*vm
= (vm_device
*)device_data(me
);
428 /* update end of bss if necessary */
429 if (vm
->heap_base
< addr
+ nr_bytes
) {
430 vm
->heap_base
= addr
+ nr_bytes
;
431 vm
->heap_bound
= addr
+ nr_bytes
;
432 vm
->heap_upper_limit
= addr
+ nr_bytes
;
434 device_attach_address(device_parent(me
),
435 "vm@0x0,0", /* stop remap */
445 STATIC_INLINE_DEVICE_TABLE
unsigned
446 add_vm_space(device
*me
,
452 vm_device
*vm
= (vm_device
*)device_data(me
);
453 unsigned_word block_addr
;
454 unsigned block_nr_bytes
;
456 /* an address in the stack area, allocate just down to the addressed
458 if (addr
>= vm
->stack_base
&& addr
< vm
->stack_lower_limit
) {
459 block_addr
= FLOOR_PAGE(addr
);
460 block_nr_bytes
= vm
->stack_lower_limit
- block_addr
;
461 vm
->stack_lower_limit
= block_addr
;
463 /* an address in the heap area, allocate all of the required heap */
464 else if (addr
>= vm
->heap_upper_limit
&& addr
< vm
->heap_bound
) {
465 block_addr
= vm
->heap_upper_limit
;
466 block_nr_bytes
= vm
->heap_bound
- vm
->heap_upper_limit
;
467 vm
->heap_upper_limit
= vm
->heap_bound
;
469 /* oops - an invalid address - abort the cpu */
470 else if (processor
!= NULL
) {
471 cpu_halt(processor
, cia
, was_signalled
, SIGSEGV
);
474 /* 2*oops - an invalid address and no processor */
479 /* got the parameters, allocate the space */
480 device_attach_address(device_parent(me
),
481 "vm@0x0,0", /* stop remap */
488 return block_nr_bytes
;
493 vm_io_read_buffer_callback(device
*me
,
501 if (add_vm_space(me
, addr
, nr_bytes
, processor
, cia
) >= nr_bytes
) {
502 memset(dest
, 0, nr_bytes
); /* always initialized to zero */
511 vm_io_write_buffer_callback(device
*me
,
519 if (add_vm_space(me
, addr
, nr_bytes
, processor
, cia
) >= nr_bytes
) {
520 return device_dma_write_buffer(device_parent(me
), source
,
523 0/*violate_read_only*/);
531 vm_ioctl_callback(device
*me
,
537 /* While the caller is notified that the heap has grown by the
538 requested amount, the heap is actually extended out to a page
540 vm_device
*vm
= (vm_device
*)device_data(me
);
541 unsigned_word requested_break
= va_arg(ap
, unsigned_word
);
542 unsigned_word new_break
= ALIGN_8(requested_break
);
543 unsigned_word old_break
= vm
->heap_bound
;
544 signed_word delta
= new_break
- old_break
;
546 vm
->heap_bound
= ALIGN_PAGE(new_break
);
551 static device_callbacks
const vm_callbacks
= {
552 { vm_init_address_callback
, },
554 passthrough_device_address_detach
, },
555 { vm_io_read_buffer_callback
,
556 vm_io_write_buffer_callback
, },
557 { NULL
, passthrough_device_dma_write_buffer
, },
558 { NULL
, }, /* interrupt */
559 { generic_device_unit_decode
,
560 generic_device_unit_encode
, },
561 { NULL
, }, /* instance */
567 vea_vm_create(const char *name
,
568 const device_unit
*address
,
572 vm_device
*vm
= ZALLOC(vm_device
);
578 /* FILE device: file@0x<address>,<file-name>
579 (later - file@0x<address>,<size>,<file-offset>,<file-name>)
581 Specifies a file to read directly into memory starting at <address> */
585 file_init_data_callback(device
*me
)
588 const char *file_name
= device_find_string_property(me
, "file-name");
589 unsigned_word addr
= device_find_integer_property(me
, "real-address");
591 count
= dma_file(me
, file_name
, addr
);
593 error("device_table/%s - Problem loading file %s\n",
594 device_name(me
), file_name
);
598 static device_callbacks
const file_callbacks
= {
599 { NULL
, file_init_data_callback
, },
600 { NULL
, }, /* address */
603 { NULL
, }, /* interrupt */
604 { NULL
, }, /* unit */
609 /* DATA device: data@<address>
611 <data> - property containing the value to store
612 <real-address> - address to store data at
614 Store <data> at <address> using approperiate byte order */
617 data_init_data_callback(device
*me
)
619 unsigned_word addr
= device_find_integer_property(me
, "real-address");
620 const device_property
*data
= device_find_property(me
, "data");
622 error("devices/data - missing data property\n");
623 switch (data
->type
) {
624 case integer_property
:
626 unsigned32 buf
= device_find_integer_property(me
, "data");
628 if (device_dma_write_buffer(device_parent(me
),
632 sizeof(buf
), /*nr-bytes*/
633 1 /*violate ro*/) != sizeof(buf
))
634 error("devices/%s - Problem storing integer 0x%x at 0x%lx\n",
635 device_name(me
), (long)buf
, (unsigned long)addr
);
639 error("devices/%s - write of this data is not yet implemented\n", device_name(me
));
645 static device_callbacks
const data_callbacks
= {
646 { NULL
, data_init_data_callback
, },
647 { NULL
, }, /* address */
650 { NULL
, }, /* interrupt */
651 { NULL
, }, /* unit */
675 HTAB defines the location (in physical memory) of a HASH table.
676 PTE (as a child of HTAB) defines a mapping that is to be entered
679 NB: All the work in this device is done during init by the PTE.
680 The pte, looks up its parent to determine the address of the HTAB
681 and then uses DMA calls to establish the required mapping. */
683 STATIC_INLINE_DEVICE_TABLE
void
684 htab_decode_hash_table(device
*parent
,
686 unsigned32
*htabmask
)
688 unsigned_word htab_ra
;
689 unsigned htab_nr_bytes
;
691 /* determine the location/size of the hash table */
693 || strcmp(device_name(parent
), "htab") != 0)
694 error("devices/htab - missing htab parent device\n");
695 htab_ra
= device_find_integer_property(parent
, "real-address");
696 htab_nr_bytes
= device_find_integer_property(parent
, "nr-bytes");
697 for (n
= htab_nr_bytes
; n
> 1; n
= n
/ 2) {
699 error("devices/%s - htab size 0x%x not a power of two\n",
700 device_name(parent
), htab_nr_bytes
);
703 *htabmask
= MASKED32(htab_nr_bytes
- 1, 7, 31-6);
704 if ((htab_ra
& INSERTED32(*htabmask
, 7, 15)) != 0) {
705 error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
706 device_name(parent
), *htaborg
, *htabmask
);
708 DTRACE(htab
, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
709 (unsigned long)*htaborg
, (unsigned long)*htabmask
));
713 htab_map_page(device
*me
,
721 unsigned64 vpn
= va
<< 12;
722 unsigned32 vsid
= INSERTED32(EXTRACTED64(vpn
, 0, 23), 0, 23);
723 unsigned32 page
= INSERTED32(EXTRACTED64(vpn
, 24, 39), 0, 15);
724 unsigned32 hash
= INSERTED32(EXTRACTED32(vsid
, 5, 23)
725 ^ EXTRACTED32(page
, 0, 15),
728 for (h
= 0; h
< 2; h
++) {
729 unsigned32 pteg
= (htaborg
| (hash
& htabmask
));
731 for (pti
= 0; pti
< 8; pti
++, pteg
+= 8) {
732 unsigned32 current_target_pte0
;
733 unsigned32 current_pte0
;
734 if (device_dma_read_buffer(device_parent(me
),
735 ¤t_target_pte0
,
738 sizeof(current_target_pte0
)) != 4)
739 error("htab_init_callback() failed to read a pte at 0x%x\n",
741 current_pte0
= T2H_4(current_target_pte0
);
742 if (!MASKED32(current_pte0
, 0, 0)) {
743 /* empty pte fill it */
744 unsigned32 pte0
= (MASK32(0, 0)
745 | INSERTED32(EXTRACTED32(vsid
, 0, 23), 1, 24)
746 | INSERTED32(h
, 25, 25)
747 | INSERTED32(EXTRACTED32(page
, 0, 5), 26, 31));
748 unsigned32 target_pte0
= H2T_4(pte0
);
749 unsigned32 pte1
= (INSERTED32(EXTRACTED32(ra
, 0, 19), 0, 19)
750 | INSERTED32(wimg
, 25, 28)
751 | INSERTED32(pp
, 30, 31));
752 unsigned32 target_pte1
= H2T_4(pte1
);
753 if (device_dma_write_buffer(device_parent(me
),
759 || device_dma_write_buffer(device_parent(me
),
765 error("htab_init_callback() failed to write a pte a 0x%x\n",
767 DTRACE(htab
, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
768 (unsigned long)va
, (unsigned long)ra
,
770 (unsigned long)pte0
, (unsigned long)pte1
));
775 hash
= MASKED32(~hash
, 0, 18);
779 STATIC_INLINE_DEVICE_TABLE
void
780 htab_map_region(device
*me
,
781 unsigned_word pte_ra
,
782 unsigned_word pte_va
,
791 /* go through all pages and create a pte for each */
792 for (ra
= pte_ra
, va
= (signed_word
)pte_va
;
793 ra
< pte_ra
+ nr_bytes
;
794 ra
+= 0x1000, va
+= 0x1000) {
795 htab_map_page(me
, ra
, va
, wimg
, pp
, htaborg
, htabmask
);
799 typedef struct _htab_binary_sizes
{
800 unsigned_word text_ra
;
801 unsigned_word text_base
;
802 unsigned_word text_bound
;
803 unsigned_word data_ra
;
804 unsigned_word data_base
;
809 STATIC_INLINE_DEVICE_TABLE
void
810 htab_sum_binary(bfd
*abfd
,
814 htab_binary_sizes
*sizes
= (htab_binary_sizes
*)data
;
815 unsigned_word size
= bfd_get_section_size_before_reloc (sec
);
816 unsigned_word vma
= bfd_get_section_vma (abfd
, sec
);
818 /* skip the section if no memory to allocate */
819 if (! (bfd_get_section_flags(abfd
, sec
) & SEC_ALLOC
))
822 if ((bfd_get_section_flags (abfd
, sec
) & SEC_CODE
)
823 || (bfd_get_section_flags (abfd
, sec
) & SEC_READONLY
)) {
824 if (sizes
->text_bound
< vma
+ size
)
825 sizes
->text_bound
= ALIGN_PAGE(vma
+ size
);
826 if (sizes
->text_base
> vma
)
827 sizes
->text_base
= FLOOR_PAGE(vma
);
829 else if ((bfd_get_section_flags (abfd
, sec
) & SEC_DATA
)
830 || (bfd_get_section_flags (abfd
, sec
) & SEC_ALLOC
)) {
831 if (sizes
->data_bound
< vma
+ size
)
832 sizes
->data_bound
= ALIGN_PAGE(vma
+ size
);
833 if (sizes
->data_base
> vma
)
834 sizes
->data_base
= FLOOR_PAGE(vma
);
838 STATIC_INLINE_DEVICE_TABLE
void
839 htab_dma_binary(bfd
*abfd
,
843 htab_binary_sizes
*sizes
= (htab_binary_sizes
*)data
;
845 unsigned_word section_vma
;
846 unsigned_word section_size
;
847 unsigned_word section_ra
;
848 device
*me
= sizes
->me
;
850 /* skip the section if no memory to allocate */
851 if (! (bfd_get_section_flags(abfd
, sec
) & SEC_ALLOC
))
854 /* check/ignore any sections of size zero */
855 section_size
= bfd_get_section_size_before_reloc(sec
);
856 if (section_size
== 0)
859 /* if nothing to load, ignore this one */
860 if (! (bfd_get_section_flags(abfd
, sec
) & SEC_LOAD
))
863 /* find where it is to go */
864 section_vma
= bfd_get_section_vma(abfd
, sec
);
866 if ((bfd_get_section_flags (abfd
, sec
) & SEC_CODE
)
867 || (bfd_get_section_flags (abfd
, sec
) & SEC_READONLY
))
868 section_ra
= (section_vma
- sizes
->text_base
+ sizes
->text_ra
);
869 else if ((bfd_get_section_flags (abfd
, sec
) & SEC_DATA
))
870 section_ra
= (section_vma
- sizes
->data_base
+ sizes
->data_ra
);
872 return; /* just ignore it */
875 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
876 bfd_get_section_name(abfd
, sec
),
880 (long)bfd_get_section_flags(abfd
, sec
),
881 bfd_get_section_flags(abfd
, sec
) & SEC_LOAD
? " LOAD" : "",
882 bfd_get_section_flags(abfd
, sec
) & SEC_CODE
? " CODE" : "",
883 bfd_get_section_flags(abfd
, sec
) & SEC_DATA
? " DATA" : "",
884 bfd_get_section_flags(abfd
, sec
) & SEC_ALLOC
? " ALLOC" : "",
885 bfd_get_section_flags(abfd
, sec
) & SEC_READONLY
? " READONLY" : ""
888 /* dma in the sections data */
889 section_init
= zalloc(section_size
);
890 if (!bfd_get_section_contents(abfd
,
894 bfd_perror("devices/pte");
895 error("devices/%s - no data loaded\n", device_name(me
));
897 if (device_dma_write_buffer(device_parent(me
),
902 1 /*violate_read_only*/)
904 error("devices/%s - broken dma transfer\n", device_name(me
));
905 zfree(section_init
); /* only free if load */
908 STATIC_INLINE_DEVICE_TABLE
void
909 htab_map_binary(device
*me
,
913 const char *file_name
,
917 htab_binary_sizes sizes
;
919 sizes
.text_base
= -1;
920 sizes
.data_base
= -1;
921 sizes
.text_bound
= 0;
922 sizes
.data_bound
= 0;
926 image
= bfd_openr(file_name
, NULL
);
928 bfd_perror("devices/pte");
929 error("devices/%s - the file %s not loaded\n", device_name(me
), file_name
);
932 /* check it is valid */
933 if (!bfd_check_format(image
, bfd_object
)) {
935 error("devices/%s - the file %s has an invalid binary format\n",
936 device_name(me
), file_name
);
939 /* determine the size of each of the files regions */
940 bfd_map_over_sections (image
, htab_sum_binary
, (PTR
) &sizes
);
942 /* determine the real addresses of the sections */
944 sizes
.data_ra
= ALIGN_PAGE(sizes
.text_ra
+
945 (sizes
.text_bound
- sizes
.text_base
));
947 DTRACE(htab
, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
948 (unsigned long)sizes
.text_base
,
949 (unsigned long)sizes
.text_bound
,
950 (unsigned long)sizes
.text_ra
));
951 DTRACE(htab
, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
952 (unsigned long)sizes
.data_base
,
953 (unsigned long)sizes
.data_bound
,
954 (unsigned long)sizes
.data_ra
));
956 /* set up virtual memory maps for each of the regions */
957 htab_map_region(me
, sizes
.text_ra
, sizes
.text_base
,
958 sizes
.text_bound
- sizes
.text_base
,
961 htab_map_region(me
, sizes
.data_ra
, sizes
.data_base
,
962 sizes
.data_bound
- sizes
.data_base
,
966 /* dma the sections into physical memory */
967 bfd_map_over_sections (image
, htab_dma_binary
, (PTR
) &sizes
);
971 htab_init_data_callback(device
*me
)
973 if (WITH_TARGET_WORD_BITSIZE
!= 32)
974 error("devices/htab: only 32bit targets currently suported\n");
976 /* only the pte does work */
977 if (strcmp(device_name(me
), "pte") == 0) {
981 htab_decode_hash_table(device_parent(me
), &htaborg
, &htabmask
);
983 if (device_find_property(me
, "file-name") != NULL
) {
984 /* map in a binary */
985 unsigned32 pte_ra
= device_find_integer_property(me
, "real-address");
986 unsigned pte_wimg
= device_find_integer_property(me
, "wimg");
987 unsigned pte_pp
= device_find_integer_property(me
, "pp");
988 const char *file_name
= device_find_string_property(me
, "file-name");
989 DTRACE(htab
, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
990 (unsigned long)pte_ra
,
991 (unsigned long)pte_wimg
,
994 htab_map_binary(me
, pte_ra
, pte_wimg
, pte_pp
, file_name
,
998 /* handle a normal mapping definition */
999 /* so that 0xff...0 is make 0xffffff00 */
1000 signed32 pte_va
= device_find_integer_property(me
, "virtual-address");
1001 unsigned32 pte_ra
= device_find_integer_property(me
, "real-address");
1002 unsigned pte_nr_bytes
= device_find_integer_property(me
, "nr-bytes");
1003 unsigned pte_wimg
= device_find_integer_property(me
, "wimg");
1004 unsigned pte_pp
= device_find_integer_property(me
, "pp");
1005 DTRACE(htab
, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
1006 (unsigned long)pte_ra
,
1009 (unsigned long)pte_va
,
1010 (long)pte_nr_bytes
));
1011 htab_map_region(me
, pte_ra
, pte_va
, pte_nr_bytes
, pte_wimg
, pte_pp
,
1018 static device_callbacks
const htab_callbacks
= {
1019 { NULL
, htab_init_data_callback
, },
1020 { NULL
, }, /* address */
1022 { passthrough_device_dma_read_buffer
,
1023 passthrough_device_dma_write_buffer
, },
1024 { NULL
, }, /* interrupt */
1025 { generic_device_unit_decode
,
1026 generic_device_unit_encode
, },
1031 /* Load device: binary
1033 Single property the name of which specifies the file (understood by
1034 BFD) that is to be DMAed into memory as part of init */
1036 STATIC_INLINE_DEVICE_TABLE
void
1037 update_for_binary_section(bfd
*abfd
,
1038 asection
*the_section
,
1041 unsigned_word section_vma
;
1042 unsigned_word section_size
;
1044 device
*me
= (device
*)obj
;
1046 /* skip the section if no memory to allocate */
1047 if (! (bfd_get_section_flags(abfd
, the_section
) & SEC_ALLOC
))
1050 /* check/ignore any sections of size zero */
1051 section_size
= bfd_get_section_size_before_reloc(the_section
);
1052 if (section_size
== 0)
1055 /* find where it is to go */
1056 section_vma
= bfd_get_section_vma(abfd
, the_section
);
1059 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
1060 bfd_get_section_name(abfd
, the_section
),
1063 (long)bfd_get_section_flags(abfd
, the_section
),
1064 bfd_get_section_flags(abfd
, the_section
) & SEC_LOAD
? " LOAD" : "",
1065 bfd_get_section_flags(abfd
, the_section
) & SEC_CODE
? " CODE" : "",
1066 bfd_get_section_flags(abfd
, the_section
) & SEC_DATA
? " DATA" : "",
1067 bfd_get_section_flags(abfd
, the_section
) & SEC_ALLOC
? " ALLOC" : "",
1068 bfd_get_section_flags(abfd
, the_section
) & SEC_READONLY
? " READONLY" : ""
1071 /* If there is an .interp section, it means it needs a shared library interpreter. */
1072 if (strcmp(".interp", bfd_get_section_name(abfd
, the_section
)) == 0)
1073 error("Shared libraries are not yet supported.\n");
1075 /* determine the devices access */
1076 access
= access_read
;
1077 if (bfd_get_section_flags(abfd
, the_section
) & SEC_CODE
)
1078 access
|= access_exec
;
1079 if (!(bfd_get_section_flags(abfd
, the_section
) & SEC_READONLY
))
1080 access
|= access_write
;
1082 /* if a map, pass up a request to create the memory in core */
1083 if (strncmp(device_name(me
), "map-binary", strlen("map-binary")) == 0)
1084 device_attach_address(device_parent(me
),
1087 0 /*address space*/,
1093 /* if a load dma in the required data */
1094 if (bfd_get_section_flags(abfd
, the_section
) & SEC_LOAD
) {
1095 void *section_init
= zalloc(section_size
);
1096 if (!bfd_get_section_contents(abfd
,
1100 bfd_perror("core:load_section()");
1101 error("load of data failed");
1104 if (device_dma_write_buffer(device_parent(me
),
1109 1 /*violate_read_only*/)
1111 error("data_init_callback() broken transfer for %s\n", device_name(me
));
1112 zfree(section_init
); /* only free if load */
1118 binary_init_data_callback(device
*me
)
1120 /* get the file name */
1121 const char *file_name
= device_find_string_property(me
, "file-name");
1125 image
= bfd_openr(file_name
, NULL
);
1126 if (image
== NULL
) {
1127 bfd_perror("devices/binary");
1128 error("devices/%s - the file %s not loaded\n", device_name(me
), file_name
);
1131 /* check it is valid */
1132 if (!bfd_check_format(image
, bfd_object
)) {
1134 error("devices/%s - the file %s has an invalid binary format\n",
1135 device_name(me
), file_name
);
1138 /* and the data sections */
1139 bfd_map_over_sections(image
,
1140 update_for_binary_section
,
1147 static device_callbacks
const binary_callbacks
= {
1148 { NULL
, binary_init_data_callback
, },
1149 { NULL
, }, /* address */
1151 { NULL
, }, /* DMA */
1152 { NULL
, }, /* interrupt */
1153 { NULL
, }, /* unit */
1158 /* Stack device: stack@<type>
1160 Has a single IOCTL to create a stack frame of the specified type.
1161 If <type> is elf or xcoff then a corresponding stack is created.
1162 Any other value of type is ignored.
1164 The IOCTL takes the additional arguments:
1166 unsigned_word stack_end -- where the stack should come down from
1172 STATIC_INLINE_DEVICE_TABLE
int
1173 sizeof_argument_strings(char **arg
)
1175 int sizeof_strings
= 0;
1181 /* add up all the string sizes (padding as we go) */
1182 for (; *arg
!= NULL
; arg
++) {
1183 int len
= strlen(*arg
) + 1;
1184 sizeof_strings
+= ALIGN_8(len
);
1187 return sizeof_strings
;
1190 STATIC_INLINE_DEVICE_TABLE
int
1191 number_of_arguments(char **arg
)
1196 for (nr
= 0; *arg
!= NULL
; arg
++, nr
++);
1200 STATIC_INLINE_DEVICE_TABLE
int
1201 sizeof_arguments(char **arg
)
1203 return ALIGN_8((number_of_arguments(arg
) + 1) * sizeof(unsigned_word
));
1206 STATIC_INLINE_DEVICE_TABLE
void
1207 write_stack_arguments(psim
*system
,
1209 unsigned_word start_block
,
1210 unsigned_word end_block
,
1211 unsigned_word start_arg
,
1212 unsigned_word end_arg
)
1215 ("write_stack_arguments(system=0x%lx, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
1216 (long)system
, (long)arg
, (long)start_block
, (long)end_block
, (long)start_arg
, (long)end_arg
));
1218 error("write_arguments: character array NULL\n");
1219 /* only copy in arguments, memory is already zero */
1220 for (; *arg
!= NULL
; arg
++) {
1221 int len
= strlen(*arg
)+1;
1222 unsigned_word target_start_block
;
1224 ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
1225 "**arg", *arg
, "start_block", (long)start_block
,
1226 "len", (long)len
, "start_arg", (long)start_arg
));
1227 if (psim_write_memory(system
, 0, *arg
,
1229 0/*violate_readonly*/) != len
)
1230 error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
1232 target_start_block
= H2T_word(start_block
);
1233 if (psim_write_memory(system
, 0, &target_start_block
,
1234 start_arg
, sizeof(target_start_block
),
1235 0) != sizeof(target_start_block
))
1236 error("write_stack_arguments() - write of *arg failed\n");
1237 start_block
+= ALIGN_8(len
);
1238 start_arg
+= sizeof(start_block
);
1240 start_arg
+= sizeof(start_block
); /*the null at the end*/
1241 if (start_block
!= end_block
1242 || ALIGN_8(start_arg
) != end_arg
)
1243 error("write_stack_arguments - possible corruption\n");
1245 ("write_stack_arguments() = void\n"));
1248 STATIC_INLINE_DEVICE_TABLE
void
1249 create_elf_stack_frame(psim
*system
,
1250 unsigned_word bottom_of_stack
,
1254 /* fixme - this is over aligned */
1256 /* information block */
1257 const unsigned sizeof_envp_block
= sizeof_argument_strings(envp
);
1258 const unsigned_word start_envp_block
= bottom_of_stack
- sizeof_envp_block
;
1259 const unsigned sizeof_argv_block
= sizeof_argument_strings(argv
);
1260 const unsigned_word start_argv_block
= start_envp_block
- sizeof_argv_block
;
1262 /* auxiliary vector - contains only one entry */
1263 const unsigned sizeof_aux_entry
= 2*sizeof(unsigned_word
); /* magic */
1264 const unsigned_word start_aux
= start_argv_block
- ALIGN_8(sizeof_aux_entry
);
1266 /* environment points (including null sentinal) */
1267 const unsigned sizeof_envp
= sizeof_arguments(envp
);
1268 const unsigned_word start_envp
= start_aux
- sizeof_envp
;
1270 /* argument pointers (including null sentinal) */
1271 const int argc
= number_of_arguments(argv
);
1272 const unsigned sizeof_argv
= sizeof_arguments(argv
);
1273 const unsigned_word start_argv
= start_envp
- sizeof_argv
;
1275 /* link register save address - alligned to a 16byte boundary */
1276 const unsigned_word top_of_stack
= ((start_argv
1277 - 2 * sizeof(unsigned_word
))
1280 /* install arguments on stack */
1281 write_stack_arguments(system
, envp
,
1282 start_envp_block
, bottom_of_stack
,
1283 start_envp
, start_aux
);
1284 write_stack_arguments(system
, argv
,
1285 start_argv_block
, start_envp_block
,
1286 start_argv
, start_envp
);
1288 /* set up the registers */
1289 psim_write_register(system
, -1,
1290 &top_of_stack
, "sp", cooked_transfer
);
1291 psim_write_register(system
, -1,
1292 &argc
, "r3", cooked_transfer
);
1293 psim_write_register(system
, -1,
1294 &start_argv
, "r4", cooked_transfer
);
1295 psim_write_register(system
, -1,
1296 &start_envp
, "r5", cooked_transfer
);
1297 psim_write_register(system
, -1,
1298 &start_aux
, "r6", cooked_transfer
);
1301 STATIC_INLINE_DEVICE_TABLE
void
1302 create_aix_stack_frame(psim
*system
,
1303 unsigned_word bottom_of_stack
,
1307 unsigned_word core_envp
;
1308 unsigned_word core_argv
;
1309 unsigned_word core_argc
;
1310 unsigned_word core_aux
;
1311 unsigned_word top_of_stack
;
1313 /* cheat - create an elf stack frame */
1314 create_elf_stack_frame(system
, bottom_of_stack
, argv
, envp
);
1316 /* extract argument addresses from registers */
1317 psim_read_register(system
, 0, &top_of_stack
, "r1", cooked_transfer
);
1318 psim_read_register(system
, 0, &core_argc
, "r3", cooked_transfer
);
1319 psim_read_register(system
, 0, &core_argv
, "r4", cooked_transfer
);
1320 psim_read_register(system
, 0, &core_envp
, "r5", cooked_transfer
);
1321 psim_read_register(system
, 0, &core_aux
, "r6", cooked_transfer
);
1323 /* extract arguments from registers */
1324 error("create_aix_stack_frame() - what happens next?\n");
1330 stack_ioctl_callback(device
*me
,
1336 unsigned_word stack_pointer
;
1337 const char *stack_type
;
1340 stack_pointer
= va_arg(ap
, unsigned_word
);
1341 argv
= va_arg(ap
, char **);
1342 envp
= va_arg(ap
, char **);
1344 ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
1345 (long)me
, device_name(me
), (long)system
, (long)processor
, (long)cia
, (long)argv
, (long)envp
));
1346 stack_type
= device_find_string_property(me
, "stack-type");
1347 if (strcmp(stack_type
, "elf") == 0)
1348 create_elf_stack_frame(system
, stack_pointer
, argv
, envp
);
1349 else if (strcmp(stack_type
, "xcoff") == 0)
1350 create_aix_stack_frame(system
, stack_pointer
, argv
, envp
);
1352 ("stack_ioctl_callback() = void\n"));
1356 static device_callbacks
const stack_callbacks
= {
1358 { NULL
, }, /* address */
1360 { NULL
, }, /* DMA */
1361 { NULL
, }, /* interrupt */
1362 { NULL
, }, /* unit */
1363 { NULL
, }, /* instance */
1364 stack_ioctl_callback
,
1369 static const device_descriptor old_device_table
[] = {
1370 { "vm", vea_vm_create
, &vm_callbacks
},
1371 { "register", NULL
, ®ister_callbacks
},
1372 { "file", NULL
, &file_callbacks
},
1373 { "data", NULL
, &data_callbacks
},
1374 { "htab", NULL
, &htab_callbacks
},
1375 { "pte", NULL
, &htab_callbacks
}, /* yep - uses htab's table */
1376 { "stack", NULL
, &stack_callbacks
},
1377 { "load-binary", NULL
, &binary_callbacks
},
1378 { "map-binary", NULL
, &binary_callbacks
},
1379 /* standard OpenBoot devices */
1380 { "aliases", NULL
, &passthrough_callbacks
},
1381 { "options", NULL
, &passthrough_callbacks
},
1382 { "chosen", NULL
, &passthrough_callbacks
},
1383 { "packages", NULL
, &passthrough_callbacks
},
1384 { "cpus", NULL
, &passthrough_callbacks
},
1385 { "openprom", NULL
, &passthrough_callbacks
},
1386 { "init", NULL
, &passthrough_callbacks
},
1387 { "trace", NULL
, &trace_callbacks
},
1391 const device_descriptor
*const device_table
[] = {
1398 #endif /* _DEVICE_TABLE_C_ */