This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / ppc / device_table.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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.
18
19 */
20
21
22 #ifndef _DEVICE_TABLE_C_
23 #define _DEVICE_TABLE_C_
24
25 #ifndef STATIC_INLINE_DEVICE_TABLE
26 #define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
27 #endif
28
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <signal.h>
32 #include <stdarg.h>
33 #include <ctype.h>
34
35 #include "device_table.h"
36
37 #include "events.h"
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #ifdef HAVE_STDLIB_H
44 #include <stdlib.h>
45 #endif
46
47 #include "cpu.h"
48
49 #include "bfd.h"
50
51 /* Helper functions */
52
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. */
56
57 typedef struct _generic_reg_spec {
58 unsigned32 base;
59 unsigned32 size;
60 } generic_reg_spec;
61
62
63 void
64 generic_device_init_address(device *me)
65 {
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);
69
70 if ((reg->sizeof_array % sizeof(generic_reg_spec)) != 0)
71 error("devices/%s reg property is of wrong size\n", device_name(me));
72
73 while (nr_entries > 0) {
74 device_attach_address(device_parent(me),
75 device_name(me),
76 attach_callback,
77 0 /*space*/,
78 BE2H_4(spec->base),
79 BE2H_4(spec->size),
80 access_read_write_exec,
81 me);
82 spec++;
83 nr_entries--;
84 }
85 }
86
87 int
88 generic_device_unit_decode(device *me,
89 const char *unit,
90 device_unit *phys)
91 {
92 memset(phys, 0, sizeof(device_unit));
93 if (unit == NULL)
94 return 0;
95 else {
96 char *pos = (char*)unit; /* force for strtoul() */
97 while (1) {
98 char *old_pos = pos;
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')
103 return -1;
104 if (phys->nr_cells == 4)
105 return -1;
106 phys->cells[phys->nr_cells] = val;
107 phys->nr_cells++;
108 }
109 }
110 }
111
112 int
113 generic_device_unit_encode(device *me,
114 const device_unit *phys,
115 char *buf,
116 int sizeof_buf)
117 {
118 int i;
119 int len;
120 char *pos = buf; /* force for strtoul() */
121 for (i = 0; i < phys->nr_cells; i++) {
122 if (pos != buf) {
123 strcat(pos, ",");
124 pos = strchr(pos, '\0');
125 }
126 sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
127 pos = strchr(pos, '\0');
128 }
129 len = pos - buf;
130 if (len >= sizeof_buf)
131 error("generic_unit_encode - buffer overflow\n");
132 return len;
133 }
134
135 /* DMA a file into memory */
136 STATIC_INLINE_DEVICE_TABLE int
137 dma_file(device *me,
138 const char *file_name,
139 unsigned_word addr)
140 {
141 int count;
142 int inc;
143 FILE *image;
144 char buf[1024];
145
146 /* get it open */
147 image = fopen(file_name, "r");
148 if (image == NULL)
149 return -1;
150
151 /* read it in slowly */
152 count = 0;
153 while (1) {
154 inc = fread(buf, 1, sizeof(buf), image);
155 if (feof(image) || ferror(image))
156 break;
157 if (device_dma_write_buffer(device_parent(me),
158 buf,
159 0 /*address-space*/,
160 addr+count,
161 inc /*nr-bytes*/,
162 1 /*violate ro*/) != inc) {
163 fclose(image);
164 return -1;
165 }
166 count += inc;
167 }
168
169 /* close down again */
170 fclose(image);
171
172 return count;
173 }
174
175
176 \f
177 /* ignore/passthrough versions of each function */
178
179 void
180 passthrough_device_address_attach(device *me,
181 const char *name,
182 attach_type attach,
183 int space,
184 unsigned_word addr,
185 unsigned nr_bytes,
186 access_type access,
187 device *who) /*callback/default*/
188 {
189 device_attach_address(device_parent(me), name, attach,
190 space, addr, nr_bytes,
191 access,
192 who);
193 }
194
195 void
196 passthrough_device_address_detach(device *me,
197 const char *name,
198 attach_type attach,
199 int space,
200 unsigned_word addr,
201 unsigned nr_bytes,
202 access_type access,
203 device *who) /*callback/default*/
204 {
205 device_detach_address(device_parent(me), name, attach,
206 space, addr, nr_bytes, access,
207 who);
208 }
209
210 unsigned
211 passthrough_device_dma_read_buffer(device *me,
212 void *dest,
213 int space,
214 unsigned_word addr,
215 unsigned nr_bytes)
216 {
217 return device_dma_read_buffer(device_parent(me), dest,
218 space, addr, nr_bytes);
219 }
220
221 unsigned
222 passthrough_device_dma_write_buffer(device *me,
223 const void *source,
224 int space,
225 unsigned_word addr,
226 unsigned nr_bytes,
227 int violate_read_only_section)
228 {
229 return device_dma_write_buffer(device_parent(me), source,
230 space, addr,
231 nr_bytes,
232 violate_read_only_section);
233 }
234
235 int
236 ignore_device_unit_decode(device *me,
237 const char *unit,
238 device_unit *phys)
239 {
240 memset(phys, 0, sizeof(device_unit));
241 return 0;
242 }
243
244
245 static const device_callbacks passthrough_callbacks = {
246 { NULL, }, /* init */
247 { passthrough_device_address_attach,
248 passthrough_device_address_detach, },
249 { NULL, }, /* IO */
250 { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
251 { NULL, }, /* interrupt */
252 { generic_device_unit_decode,
253 generic_device_unit_encode, },
254 };
255
256
257 \f
258 /* Register init device: register@<nothing>
259
260 Properties attached to the register device specify the name/value
261 initialization pair for cpu registers.
262
263 A specific processor can be initialized by creating a property with
264 a name like `0.pc'.
265
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. */
269
270 static void
271 do_register_init(device *me,
272 const device_property *prop)
273 {
274 psim *system = device_system(me);
275 if (prop != NULL) {
276 const char *name = prop->name;
277 unsigned32 value = device_find_integer_property(me, name);
278 int processor;
279
280 do_register_init(me, device_next_property(prop));
281
282 if (strchr(name, '.') == NULL) {
283 processor = -1;
284 DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
285 }
286 else {
287 char *end;
288 processor = strtoul(name, &end, 0);
289 ASSERT(end[0] == '.');
290 name = end+1;
291 DTRACE(register, ("%d.%s=0x%lx\n", processor, name,
292 (unsigned long)value));
293 }
294 psim_write_register(system, processor, /* all processors */
295 &value,
296 name,
297 cooked_transfer);
298 }
299 }
300
301
302 static void
303 register_init_data_callback(device *me)
304 {
305 const device_property *prop = device_find_property(me, NULL);
306 do_register_init(me, prop);
307 }
308
309
310 static device_callbacks const register_callbacks = {
311 { NULL, register_init_data_callback, },
312 { NULL, }, /* address */
313 { NULL, }, /* IO */
314 { NULL, }, /* DMA */
315 { NULL, }, /* interrupt */
316 { NULL, }, /* unit */
317 };
318
319
320 \f
321 /* Trace device:
322
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. */
327
328 static void
329 trace_init_data_callback(device *me)
330 {
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);
337 }
338 }
339
340
341 static device_callbacks const trace_callbacks = {
342 { NULL, trace_init_data_callback, },
343 { NULL, }, /* address */
344 { NULL, }, /* IO */
345 { NULL, }, /* DMA */
346 { NULL, }, /* interrupt */
347 { NULL, }, /* unit */
348 };
349
350
351 \f
352 /* VEA VM:
353
354 vm@<stack-base>
355 stack-base =
356 nr-bytes =
357
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
362 allowed to continue.
363
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.
367
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.
372
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). */
377
378
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;
388 } vm_device;
389
390
391 static void
392 vm_init_address_callback(device *me)
393 {
394 vm_device *vm = (vm_device*)device_data(me);
395
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;
401 vm->heap_base = 0;
402 vm->heap_bound = 0;
403 vm->heap_upper_limit = 0;
404
405 /* establish this device as the default memory handler */
406 device_attach_address(device_parent(me),
407 device_name(me),
408 attach_callback + 1,
409 0 /*address space - ignore*/,
410 0 /*addr - ignore*/,
411 (((unsigned)0)-1) /*nr_bytes - ignore*/,
412 access_read_write /*access*/,
413 me);
414 }
415
416
417 static void
418 vm_attach_address(device *me,
419 const char *name,
420 attach_type attach,
421 int space,
422 unsigned_word addr,
423 unsigned nr_bytes,
424 access_type access,
425 device *who) /*callback/default*/
426 {
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;
433 }
434 device_attach_address(device_parent(me),
435 "vm@0x0,0", /* stop remap */
436 attach_raw_memory,
437 0 /*address space*/,
438 addr,
439 nr_bytes,
440 access,
441 me);
442 }
443
444
445 STATIC_INLINE_DEVICE_TABLE unsigned
446 add_vm_space(device *me,
447 unsigned_word addr,
448 unsigned nr_bytes,
449 cpu *processor,
450 unsigned_word cia)
451 {
452 vm_device *vm = (vm_device*)device_data(me);
453 unsigned_word block_addr;
454 unsigned block_nr_bytes;
455
456 /* an address in the stack area, allocate just down to the addressed
457 page */
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;
462 }
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;
468 }
469 /* oops - an invalid address - abort the cpu */
470 else if (processor != NULL) {
471 cpu_halt(processor, cia, was_signalled, SIGSEGV);
472 return 0;
473 }
474 /* 2*oops - an invalid address and no processor */
475 else {
476 return 0;
477 }
478
479 /* got the parameters, allocate the space */
480 device_attach_address(device_parent(me),
481 "vm@0x0,0", /* stop remap */
482 attach_raw_memory,
483 0 /*address space*/,
484 block_addr,
485 block_nr_bytes,
486 access_read_write,
487 me);
488 return block_nr_bytes;
489 }
490
491
492 static unsigned
493 vm_io_read_buffer_callback(device *me,
494 void *dest,
495 int space,
496 unsigned_word addr,
497 unsigned nr_bytes,
498 cpu *processor,
499 unsigned_word cia)
500 {
501 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
502 memset(dest, 0, nr_bytes); /* always initialized to zero */
503 return nr_bytes;
504 }
505 else
506 return 0;
507 }
508
509
510 static unsigned
511 vm_io_write_buffer_callback(device *me,
512 const void *source,
513 int space,
514 unsigned_word addr,
515 unsigned nr_bytes,
516 cpu *processor,
517 unsigned_word cia)
518 {
519 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
520 return device_dma_write_buffer(device_parent(me), source,
521 space, addr,
522 nr_bytes,
523 0/*violate_read_only*/);
524 }
525 else
526 return 0;
527 }
528
529
530 static int
531 vm_ioctl_callback(device *me,
532 psim *system,
533 cpu *processor,
534 unsigned_word cia,
535 va_list ap)
536 {
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
539 boundary. */
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;
545 if (delta > 0)
546 vm->heap_bound = ALIGN_PAGE(new_break);
547 return 0;
548 }
549
550
551 static device_callbacks const vm_callbacks = {
552 { vm_init_address_callback, },
553 { vm_attach_address,
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 */
562 vm_ioctl_callback,
563 };
564
565
566 static void *
567 vea_vm_create(const char *name,
568 const device_unit *address,
569 const char *args,
570 device *parent)
571 {
572 vm_device *vm = ZALLOC(vm_device);
573 return vm;
574 }
575
576
577 \f
578 /* FILE device: file@0x<address>,<file-name>
579 (later - file@0x<address>,<size>,<file-offset>,<file-name>)
580
581 Specifies a file to read directly into memory starting at <address> */
582
583
584 static void
585 file_init_data_callback(device *me)
586 {
587 int count;
588 const char *file_name = device_find_string_property(me, "file-name");
589 unsigned_word addr = device_find_integer_property(me, "real-address");
590 /* load the file */
591 count = dma_file(me, file_name, addr);
592 if (count < 0)
593 error("device_table/%s - Problem loading file %s\n",
594 device_name(me), file_name);
595 }
596
597
598 static device_callbacks const file_callbacks = {
599 { NULL, file_init_data_callback, },
600 { NULL, }, /* address */
601 { NULL, }, /* IO */
602 { NULL, }, /* DMA */
603 { NULL, }, /* interrupt */
604 { NULL, }, /* unit */
605 };
606
607
608 \f
609 /* DATA device: data@<address>
610
611 <data> - property containing the value to store
612 <real-address> - address to store data at
613
614 Store <data> at <address> using approperiate byte order */
615
616 static void
617 data_init_data_callback(device *me)
618 {
619 unsigned_word addr = device_find_integer_property(me, "real-address");
620 const device_property *data = device_find_property(me, "data");
621 if (data == NULL)
622 error("devices/data - missing data property\n");
623 switch (data->type) {
624 case integer_property:
625 {
626 unsigned32 buf = device_find_integer_property(me, "data");
627 H2T(buf);
628 if (device_dma_write_buffer(device_parent(me),
629 &buf,
630 0 /*address-space*/,
631 addr,
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);
636 }
637 break;
638 default:
639 error("devices/%s - write of this data is not yet implemented\n", device_name(me));
640 break;
641 }
642 }
643
644
645 static device_callbacks const data_callbacks = {
646 { NULL, data_init_data_callback, },
647 { NULL, }, /* address */
648 { NULL, }, /* IO */
649 { NULL, }, /* DMA */
650 { NULL, }, /* interrupt */
651 { NULL, }, /* unit */
652 };
653
654
655 \f
656 /* HTAB:
657
658 htab@<real-address>
659 real-address =
660 nr-bytes =
661
662 pte@<real-address>
663 real-address =
664 virtual-address =
665 nr-bytes =
666 wimg =
667 pp =
668
669 pte@<real-address>
670 real-address =
671 file-name =
672 wimg =
673 pp =
674
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
677 into that table.
678
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. */
682
683 STATIC_INLINE_DEVICE_TABLE void
684 htab_decode_hash_table(device *parent,
685 unsigned32 *htaborg,
686 unsigned32 *htabmask)
687 {
688 unsigned_word htab_ra;
689 unsigned htab_nr_bytes;
690 unsigned n;
691 /* determine the location/size of the hash table */
692 if (parent == NULL
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) {
698 if (n % 2 != 0)
699 error("devices/%s - htab size 0x%x not a power of two\n",
700 device_name(parent), htab_nr_bytes);
701 }
702 *htaborg = htab_ra;
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);
707 }
708 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
709 (unsigned long)*htaborg, (unsigned long)*htabmask));
710 }
711
712 STATIC_INLINE void
713 htab_map_page(device *me,
714 unsigned_word ra,
715 unsigned64 va,
716 unsigned wimg,
717 unsigned pp,
718 unsigned32 htaborg,
719 unsigned32 htabmask)
720 {
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),
726 7, 31-6);
727 int h;
728 for (h = 0; h < 2; h++) {
729 unsigned32 pteg = (htaborg | (hash & htabmask));
730 int pti;
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 &current_target_pte0,
736 0, /*space*/
737 pteg,
738 sizeof(current_target_pte0)) != 4)
739 error("htab_init_callback() failed to read a pte at 0x%x\n",
740 pteg);
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),
754 &target_pte0,
755 0, /*space*/
756 pteg,
757 sizeof(target_pte0),
758 1/*ro?*/) != 4
759 || device_dma_write_buffer(device_parent(me),
760 &target_pte1,
761 0, /*space*/
762 pteg + 4,
763 sizeof(target_pte1),
764 1/*ro?*/) != 4)
765 error("htab_init_callback() failed to write a pte a 0x%x\n",
766 pteg);
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,
769 (unsigned long)pteg,
770 (unsigned long)pte0, (unsigned long)pte1));
771 return;
772 }
773 }
774 /* re-hash */
775 hash = MASKED32(~hash, 0, 18);
776 }
777 }
778
779 STATIC_INLINE_DEVICE_TABLE void
780 htab_map_region(device *me,
781 unsigned_word pte_ra,
782 unsigned_word pte_va,
783 unsigned nr_bytes,
784 unsigned wimg,
785 unsigned pp,
786 unsigned32 htaborg,
787 unsigned32 htabmask)
788 {
789 unsigned_word ra;
790 unsigned64 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);
796 }
797 }
798
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;
805 unsigned data_bound;
806 device *me;
807 } htab_binary_sizes;
808
809 STATIC_INLINE_DEVICE_TABLE void
810 htab_sum_binary(bfd *abfd,
811 sec_ptr sec,
812 PTR data)
813 {
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);
817
818 /* skip the section if no memory to allocate */
819 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
820 return;
821
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);
828 }
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);
835 }
836 }
837
838 STATIC_INLINE_DEVICE_TABLE void
839 htab_dma_binary(bfd *abfd,
840 sec_ptr sec,
841 PTR data)
842 {
843 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
844 void *section_init;
845 unsigned_word section_vma;
846 unsigned_word section_size;
847 unsigned_word section_ra;
848 device *me = sizes->me;
849
850 /* skip the section if no memory to allocate */
851 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
852 return;
853
854 /* check/ignore any sections of size zero */
855 section_size = bfd_get_section_size_before_reloc(sec);
856 if (section_size == 0)
857 return;
858
859 /* if nothing to load, ignore this one */
860 if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
861 return;
862
863 /* find where it is to go */
864 section_vma = bfd_get_section_vma(abfd, sec);
865 section_ra = 0;
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);
871 else
872 return; /* just ignore it */
873
874 DTRACE(htab,
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),
877 (long)section_vma,
878 (long)section_size,
879 (long)section_ra,
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" : ""
886 ));
887
888 /* dma in the sections data */
889 section_init = zalloc(section_size);
890 if (!bfd_get_section_contents(abfd,
891 sec,
892 section_init, 0,
893 section_size)) {
894 bfd_perror("devices/pte");
895 error("devices/%s - no data loaded\n", device_name(me));
896 }
897 if (device_dma_write_buffer(device_parent(me),
898 section_init,
899 0 /*space*/,
900 section_ra,
901 section_size,
902 1 /*violate_read_only*/)
903 != section_size)
904 error("devices/%s - broken dma transfer\n", device_name(me));
905 zfree(section_init); /* only free if load */
906 }
907
908 STATIC_INLINE_DEVICE_TABLE void
909 htab_map_binary(device *me,
910 unsigned_word ra,
911 unsigned wimg,
912 unsigned pp,
913 const char *file_name,
914 unsigned32 htaborg,
915 unsigned32 htabmask)
916 {
917 htab_binary_sizes sizes;
918 bfd *image;
919 sizes.text_base = -1;
920 sizes.data_base = -1;
921 sizes.text_bound = 0;
922 sizes.data_bound = 0;
923 sizes.me = me;
924
925 /* open the file */
926 image = bfd_openr(file_name, NULL);
927 if (image == NULL) {
928 bfd_perror("devices/pte");
929 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
930 }
931
932 /* check it is valid */
933 if (!bfd_check_format(image, bfd_object)) {
934 bfd_close(image);
935 error("devices/%s - the file %s has an invalid binary format\n",
936 device_name(me), file_name);
937 }
938
939 /* determine the size of each of the files regions */
940 bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
941
942 /* determine the real addresses of the sections */
943 sizes.text_ra = ra;
944 sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
945 (sizes.text_bound - sizes.text_base));
946
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));
955
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,
959 wimg, pp,
960 htaborg, htabmask);
961 htab_map_region(me, sizes.data_ra, sizes.data_base,
962 sizes.data_bound - sizes.data_base,
963 wimg, pp,
964 htaborg, htabmask);
965
966 /* dma the sections into physical memory */
967 bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
968 }
969
970 static void
971 htab_init_data_callback(device *me)
972 {
973 if (WITH_TARGET_WORD_BITSIZE != 32)
974 error("devices/htab: only 32bit targets currently suported\n");
975
976 /* only the pte does work */
977 if (strcmp(device_name(me), "pte") == 0) {
978 unsigned32 htaborg;
979 unsigned32 htabmask;
980
981 htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
982
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,
992 (long)pte_pp,
993 file_name));
994 htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
995 htaborg, htabmask);
996 }
997 else {
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,
1007 (long)pte_wimg,
1008 (long)pte_pp,
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,
1012 htaborg, htabmask);
1013 }
1014 }
1015 }
1016
1017
1018 static device_callbacks const htab_callbacks = {
1019 { NULL, htab_init_data_callback, },
1020 { NULL, }, /* address */
1021 { NULL, }, /* IO */
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, },
1027 };
1028
1029
1030 \f
1031 /* Load device: binary
1032
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 */
1035
1036 STATIC_INLINE_DEVICE_TABLE void
1037 update_for_binary_section(bfd *abfd,
1038 asection *the_section,
1039 PTR obj)
1040 {
1041 unsigned_word section_vma;
1042 unsigned_word section_size;
1043 access_type access;
1044 device *me = (device*)obj;
1045
1046 /* skip the section if no memory to allocate */
1047 if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
1048 return;
1049
1050 /* check/ignore any sections of size zero */
1051 section_size = bfd_get_section_size_before_reloc(the_section);
1052 if (section_size == 0)
1053 return;
1054
1055 /* find where it is to go */
1056 section_vma = bfd_get_section_vma(abfd, the_section);
1057
1058 DTRACE(binary,
1059 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
1060 bfd_get_section_name(abfd, the_section),
1061 (long)section_vma,
1062 (long)section_size,
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" : ""
1069 ));
1070
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");
1074
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;
1081
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),
1085 device_name(me),
1086 attach_raw_memory,
1087 0 /*address space*/,
1088 section_vma,
1089 section_size,
1090 access,
1091 me);
1092
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,
1097 the_section,
1098 section_init, 0,
1099 section_size)) {
1100 bfd_perror("core:load_section()");
1101 error("load of data failed");
1102 return;
1103 }
1104 if (device_dma_write_buffer(device_parent(me),
1105 section_init,
1106 0 /*space*/,
1107 section_vma,
1108 section_size,
1109 1 /*violate_read_only*/)
1110 != section_size)
1111 error("data_init_callback() broken transfer for %s\n", device_name(me));
1112 zfree(section_init); /* only free if load */
1113 }
1114 }
1115
1116
1117 static void
1118 binary_init_data_callback(device *me)
1119 {
1120 /* get the file name */
1121 const char *file_name = device_find_string_property(me, "file-name");
1122 bfd *image;
1123
1124 /* open the file */
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);
1129 }
1130
1131 /* check it is valid */
1132 if (!bfd_check_format(image, bfd_object)) {
1133 bfd_close(image);
1134 error("devices/%s - the file %s has an invalid binary format\n",
1135 device_name(me), file_name);
1136 }
1137
1138 /* and the data sections */
1139 bfd_map_over_sections(image,
1140 update_for_binary_section,
1141 (PTR)me);
1142
1143 bfd_close(image);
1144 }
1145
1146
1147 static device_callbacks const binary_callbacks = {
1148 { NULL, binary_init_data_callback, },
1149 { NULL, }, /* address */
1150 { NULL, }, /* IO */
1151 { NULL, }, /* DMA */
1152 { NULL, }, /* interrupt */
1153 { NULL, }, /* unit */
1154 };
1155
1156
1157 \f
1158 /* Stack device: stack@<type>
1159
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.
1163
1164 The IOCTL takes the additional arguments:
1165
1166 unsigned_word stack_end -- where the stack should come down from
1167 char **argv -- ...
1168 char **envp -- ...
1169
1170 */
1171
1172 STATIC_INLINE_DEVICE_TABLE int
1173 sizeof_argument_strings(char **arg)
1174 {
1175 int sizeof_strings = 0;
1176
1177 /* robust */
1178 if (arg == NULL)
1179 return 0;
1180
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);
1185 }
1186
1187 return sizeof_strings;
1188 }
1189
1190 STATIC_INLINE_DEVICE_TABLE int
1191 number_of_arguments(char **arg)
1192 {
1193 int nr;
1194 if (arg == NULL)
1195 return 0;
1196 for (nr = 0; *arg != NULL; arg++, nr++);
1197 return nr;
1198 }
1199
1200 STATIC_INLINE_DEVICE_TABLE int
1201 sizeof_arguments(char **arg)
1202 {
1203 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
1204 }
1205
1206 STATIC_INLINE_DEVICE_TABLE void
1207 write_stack_arguments(psim *system,
1208 char **arg,
1209 unsigned_word start_block,
1210 unsigned_word end_block,
1211 unsigned_word start_arg,
1212 unsigned_word end_arg)
1213 {
1214 DTRACE(stack,
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));
1217 if (arg == NULL)
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;
1223 DTRACE(stack,
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,
1228 start_block, len,
1229 0/*violate_readonly*/) != len)
1230 error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
1231 *arg, start_block);
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);
1239 }
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");
1244 DTRACE(stack,
1245 ("write_stack_arguments() = void\n"));
1246 }
1247
1248 STATIC_INLINE_DEVICE_TABLE void
1249 create_elf_stack_frame(psim *system,
1250 unsigned_word bottom_of_stack,
1251 char **argv,
1252 char **envp)
1253 {
1254 /* fixme - this is over aligned */
1255
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;
1261
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);
1265
1266 /* environment points (including null sentinal) */
1267 const unsigned sizeof_envp = sizeof_arguments(envp);
1268 const unsigned_word start_envp = start_aux - sizeof_envp;
1269
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;
1274
1275 /* link register save address - alligned to a 16byte boundary */
1276 const unsigned_word top_of_stack = ((start_argv
1277 - 2 * sizeof(unsigned_word))
1278 & ~0xf);
1279
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);
1287
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);
1299 }
1300
1301 STATIC_INLINE_DEVICE_TABLE void
1302 create_aix_stack_frame(psim *system,
1303 unsigned_word bottom_of_stack,
1304 char **argv,
1305 char **envp)
1306 {
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;
1312
1313 /* cheat - create an elf stack frame */
1314 create_elf_stack_frame(system, bottom_of_stack, argv, envp);
1315
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);
1322
1323 /* extract arguments from registers */
1324 error("create_aix_stack_frame() - what happens next?\n");
1325 }
1326
1327
1328
1329 static int
1330 stack_ioctl_callback(device *me,
1331 psim *system,
1332 cpu *processor,
1333 unsigned_word cia,
1334 va_list ap)
1335 {
1336 unsigned_word stack_pointer;
1337 const char *stack_type;
1338 char **argv;
1339 char **envp;
1340 stack_pointer = va_arg(ap, unsigned_word);
1341 argv = va_arg(ap, char **);
1342 envp = va_arg(ap, char **);
1343 DTRACE(stack,
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);
1351 DTRACE(stack,
1352 ("stack_ioctl_callback() = void\n"));
1353 return 0;
1354 }
1355
1356 static device_callbacks const stack_callbacks = {
1357 { NULL, },
1358 { NULL, }, /* address */
1359 { NULL, }, /* IO */
1360 { NULL, }, /* DMA */
1361 { NULL, }, /* interrupt */
1362 { NULL, }, /* unit */
1363 { NULL, }, /* instance */
1364 stack_ioctl_callback,
1365 };
1366
1367
1368 \f
1369 static const device_descriptor old_device_table[] = {
1370 { "vm", vea_vm_create, &vm_callbacks },
1371 { "register", NULL, &register_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 },
1388 { NULL },
1389 };
1390
1391 const device_descriptor *const device_table[] = {
1392 old_device_table,
1393 #include "hw.c"
1394 NULL,
1395 };
1396
1397
1398 #endif /* _DEVICE_TABLE_C_ */
This page took 0.080189 seconds and 5 git commands to generate.