Fix -m switch
[deliverable/binutils-gdb.git] / sim / ppc / device_table.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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 #ifdef HAVE_STRING_H
48 #include <string.h>
49 #else
50 #ifdef HAVE_STRINGS_H
51 #include <strings.h>
52 #endif
53 #endif
54
55 #include "cpu.h"
56
57 #include "bfd.h"
58
59 /* Helper functions */
60
61 /* Generic device init: Attaches the device of size <nr_bytes> (taken
62 from <name>@<int>,<nr_bytes>) to its parent at address zero and
63 with read/write access. */
64
65 STATIC_INLINE_DEVICE_TABLE void
66 generic_init_callback(device *me,
67 psim *system)
68 {
69 unsigned_word addr;
70 unsigned nr_bytes;
71 if (scand_uw_u(device_name(me), &addr, &nr_bytes) != 2)
72 error("generic_init_callback() invalid nr_bytes in %s\n", device_name(me));
73 device_attach_address(device_parent(me),
74 device_name(me),
75 attach_callback,
76 0 /*space*/,
77 addr,
78 nr_bytes,
79 access_read_write,
80 me);
81 }
82
83
84 /* DMA a file into memory */
85 STATIC_INLINE_DEVICE_TABLE int
86 dma_file(device *me,
87 const char *file_name,
88 unsigned_word addr)
89 {
90 int count;
91 int inc;
92 FILE *image;
93 char buf[1024];
94
95 /* get it open */
96 image = fopen(file_name, "r");
97 if (image == NULL)
98 return -1;
99
100 /* read it in slowly */
101 count = 0;
102 while (1) {
103 inc = fread(buf, 1, sizeof(buf), image);
104 if (feof(image) || ferror(image))
105 break;
106 if (device_dma_write_buffer(device_parent(me),
107 buf,
108 0 /*address-space*/,
109 addr+count,
110 inc /*nr-bytes*/,
111 1 /*violate ro*/) != inc) {
112 fclose(image);
113 return -1;
114 }
115 count += inc;
116 }
117
118 /* close down again */
119 fclose(image);
120
121 return count;
122 }
123
124
125 \f
126 /* inimplemented versions of each function */
127
128 void
129 unimp_device_init(device *me,
130 psim *system)
131 {
132 error("device_init_callback for %s not implemented\n", device_name(me));
133 }
134
135 void
136 unimp_device_attach_address(device *me,
137 const char *name,
138 attach_type type,
139 int space,
140 unsigned_word addr,
141 unsigned nr_bytes,
142 access_type access,
143 device *who) /*callback/default*/
144 {
145 error("device_attach_address_callback for %s not implemented\n", device_name(me));
146 }
147
148 void
149 unimp_device_detach_address(device *me,
150 const char *name,
151 attach_type type,
152 int space,
153 unsigned_word addr,
154 unsigned nr_bytes,
155 access_type access,
156 device *who) /*callback/default*/
157 {
158 error("device_detach_address_callback for %s not implemented\n", device_name(me));
159 }
160
161 unsigned
162 unimp_device_io_read_buffer(device *me,
163 void *dest,
164 int space,
165 unsigned_word addr,
166 unsigned nr_bytes,
167 cpu *processor,
168 unsigned_word cia)
169 {
170 error("device_io_read_buffer_callback for %s not implemented\n", device_name(me));
171 return 0;
172 }
173
174 unsigned
175 unimp_device_io_write_buffer(device *me,
176 const void *source,
177 int space,
178 unsigned_word addr,
179 unsigned nr_bytes,
180 cpu *processor,
181 unsigned_word cia)
182 {
183 error("device_io_write_buffer_callback for %s not implemented\n", device_name(me));
184 return 0;
185 }
186
187 unsigned
188 unimp_device_dma_read_buffer(device *me,
189 void *target,
190 int space,
191 unsigned_word addr,
192 unsigned nr_bytes)
193 {
194 error("device_dma_read_buffer_callback for %s not implemented\n", device_name(me));
195 return 0;
196 }
197
198 unsigned
199 unimp_device_dma_write_buffer(device *me,
200 const void *source,
201 int space,
202 unsigned_word addr,
203 unsigned nr_bytes,
204 int violate_read_only_section)
205 {
206 error("device_dma_write_buffer_callback for %s not implemented\n", device_name(me));
207 return 0;
208 }
209
210 void
211 unimp_device_attach_interrupt(device *me,
212 device *who,
213 int interrupt_line,
214 const char *name)
215 {
216 error("device_attach_interrupt_callback for %s not implemented\n", device_name(me));
217 }
218
219 void
220 unimp_device_detach_interrupt(device *me,
221 device *who,
222 int interrupt_line,
223 const char *name)
224 {
225 error("device_detach_interrupt_callback for %s not implemented\n", device_name(me));
226 }
227
228 void
229 unimp_device_interrupt(device *me,
230 device *who,
231 int interrupt_line,
232 int interrupt_status,
233 cpu *processor,
234 unsigned_word cia)
235 {
236 error("device_interrupt_callback for %s not implemented\n", device_name(me));
237 }
238
239 void
240 unimp_device_interrupt_ack(device *me,
241 int interrupt_line,
242 int interrupt_status)
243 {
244 error("device_interrupt_ack_callback for %s not implemented\n", device_name(me));
245 }
246
247 void
248 unimp_device_ioctl(device *me,
249 psim *system,
250 cpu *processor,
251 unsigned_word cia,
252 va_list ap)
253 {
254 error("device_ioctl_callback for %s not implemented\n", device_name(me));
255 }
256
257
258 \f
259 /* ignore/passthrough versions of each function */
260
261 void
262 ignore_device_init(device *me,
263 psim *system)
264 {
265 /*null*/
266 }
267
268 void
269 passthrough_device_attach_address(device *me,
270 const char *name,
271 attach_type attach,
272 int space,
273 unsigned_word addr,
274 unsigned nr_bytes,
275 access_type access,
276 device *who) /*callback/default*/
277 {
278 device_attach_address(device_parent(me), name, attach,
279 space, addr, nr_bytes,
280 access,
281 who);
282 }
283
284 void
285 passthrough_device_detach_address(device *me,
286 const char *name,
287 attach_type attach,
288 int space,
289 unsigned_word addr,
290 unsigned nr_bytes,
291 access_type access,
292 device *who) /*callback/default*/
293 {
294 device_detach_address(device_parent(me), name, attach,
295 space, addr, nr_bytes, access,
296 who);
297 }
298
299 unsigned
300 passthrough_device_dma_read_buffer(device *me,
301 void *dest,
302 int space,
303 unsigned_word addr,
304 unsigned nr_bytes)
305 {
306 return device_dma_read_buffer(device_parent(me), dest,
307 space, addr, nr_bytes);
308 }
309
310 unsigned
311 passthrough_device_dma_write_buffer(device *me,
312 const void *source,
313 int space,
314 unsigned_word addr,
315 unsigned nr_bytes,
316 int violate_read_only_section)
317 {
318 return device_dma_write_buffer(device_parent(me), source,
319 space, addr,
320 nr_bytes,
321 violate_read_only_section);
322 }
323
324 void
325 passthrough_device_attach_interrupt(device *me,
326 device *who,
327 int interrupt_line,
328 const char *name)
329 {
330 device_attach_interrupt(device_parent(me), who,
331 interrupt_line, name);
332 }
333
334 void
335 passthrough_device_detach_interrupt(device *me,
336 device *who,
337 int interrupt_line,
338 const char *name)
339 {
340 device_detach_interrupt(device_parent(me), who,
341 interrupt_line, name);
342 }
343
344
345 void
346 passthrough_device_interrupt(device *me,
347 device *who,
348 int interrupt_line,
349 int interrupt_status,
350 cpu *processor,
351 unsigned_word cia)
352 {
353 device_interrupt(device_parent(me), who,
354 interrupt_line, interrupt_status,
355 processor, cia);
356 }
357
358
359 static const device_callbacks passthrough_callbacks = {
360 ignore_device_init,
361 passthrough_device_attach_address,
362 passthrough_device_detach_address,
363 unimp_device_io_read_buffer,
364 unimp_device_io_write_buffer,
365 passthrough_device_dma_read_buffer,
366 passthrough_device_dma_write_buffer,
367 passthrough_device_attach_interrupt,
368 passthrough_device_detach_interrupt,
369 passthrough_device_interrupt,
370 unimp_device_interrupt_ack,
371 unimp_device_ioctl,
372 };
373
374
375 \f
376 /* Simple console device: console@<address>,16
377
378 Input characters are taken from the keyboard, output characters
379 sent to the terminal. Echoing of characters is not disabled.
380
381 The device has four registers:
382
383 0x0: read
384 0x4: read-status
385 0x8: write
386 0xC: write-status
387
388 Where a nonzero status register indicates that the device is ready
389 (input fifo contains a character or output fifo has space). */
390
391 typedef struct _console_buffer {
392 char buffer;
393 int status;
394 event_entry_tag event_tag;
395 } console_buffer;
396
397 typedef struct _console_device {
398 console_buffer input;
399 console_buffer output;
400 } console_device;
401
402 typedef enum {
403 console_read_buffer = 0,
404 console_read_status = 4,
405 console_write_buffer = 8,
406 console_write_status = 12,
407 console_offset_mask = 0xc,
408 console_size = 16,
409 } console_offsets;
410
411
412 static unsigned
413 console_io_read_buffer_callback(device *me,
414 void *dest,
415 int space,
416 unsigned_word addr,
417 unsigned nr_bytes,
418 cpu *processor,
419 unsigned_word cia)
420 {
421 console_device *console = (console_device*)device_data(me);
422 unsigned_1 val;
423
424 /* determine what was read */
425
426 switch ((int)addr) {
427
428 case console_read_buffer:
429 val = console->input.buffer;
430 break;
431
432 case console_read_status:
433 { /* check for input */
434 int flags;
435 int status;
436 /* get the old status */
437 flags = fcntl(0, F_GETFL, 0);
438 if (flags == -1) {
439 perror("console");
440 val = 0;
441 break;
442 }
443 /* temp, disable blocking IO */
444 status = fcntl(0, F_SETFL, flags | O_NDELAY);
445 if (status == -1) {
446 perror("console");
447 val = 0;
448 break;
449 }
450 /* try for input */
451 status = read(0, &console->input.buffer, 1);
452 if (status == 1) {
453 console->input.status = 1;
454 }
455 else {
456 console->input.status = 0;
457 }
458 /* return to regular vewing */
459 fcntl(0, F_SETFL, flags);
460 }
461 val = console->input.status;
462 break;
463
464 case console_write_buffer:
465 val = console->output.buffer;
466 break;
467
468 case console_write_status:
469 val = console->output.status;
470 break;
471
472 default:
473 error("console_read_callback() internal error\n");
474 val = 0;
475 break;
476
477 }
478
479 memset(dest, 0, nr_bytes);
480 *(unsigned_1*)dest = val;
481 return nr_bytes;
482 }
483
484 static unsigned
485 console_io_write_buffer_callback(device *me,
486 const void *source,
487 int space,
488 unsigned_word addr,
489 unsigned nr_bytes,
490 cpu *processor,
491 unsigned_word cia)
492 {
493 console_device *console = (console_device*)device_data(me);
494 unsigned_1 val = *(unsigned_1*)source;
495
496 switch ((int)addr) {
497 case console_read_buffer:
498 console->input.buffer = val;
499 break;
500 case console_read_status:
501 console->input.status = val;
502 break;
503 case console_write_buffer:
504 DTRACE(console, ("<%c:%d>", val, val));
505 printf_filtered("%c",val) ;
506 console->output.buffer = val;
507 console->output.status = 1;
508 break;
509 case console_write_status:
510 console->output.status = val;
511 break;
512 default:
513 error("console_write_callback() internal error\n");
514 }
515
516 return nr_bytes;
517 }
518
519
520 static device_callbacks const console_callbacks = {
521 generic_init_callback,
522 unimp_device_attach_address,
523 unimp_device_detach_address,
524 console_io_read_buffer_callback,
525 console_io_write_buffer_callback,
526 unimp_device_dma_read_buffer,
527 unimp_device_dma_write_buffer,
528 unimp_device_attach_interrupt,
529 unimp_device_detach_interrupt,
530 unimp_device_interrupt,
531 unimp_device_interrupt_ack,
532 unimp_device_ioctl,
533 };
534
535
536 static void *
537 console_create(const char *name,
538 device *parent)
539 {
540 /* create the descriptor */
541 console_device *console = ZALLOC(console_device);
542 console->output.status = 1;
543 console->output.buffer = '\0';
544 console->input.status = 0;
545 console->input.buffer = '\0';
546 return console;
547 }
548
549
550 \f
551 /* ICU device: icu@0x<address>,4
552
553 Single 4 byte register. Read returns processor number. Write
554 interrupts specified processor.
555
556 Illustrates passing of events to parent device. Passing of
557 interrupts to parent bus.
558
559 NB: For the sake of illustrating the passing of interrupts. This
560 device doesn't pass interrupt events to its parent. Instead it
561 passes them back to its self. */
562
563 static unsigned
564 icu_io_read_buffer_callback(device *me,
565 void *dest,
566 int space,
567 unsigned_word addr,
568 unsigned nr_bytes,
569 cpu *processor,
570 unsigned_word cia)
571 {
572 unsigned_1 val;
573 val = cpu_nr(processor);
574 memset(dest, 0, nr_bytes);
575 *(unsigned_1*)dest = val;
576 return nr_bytes;
577 }
578
579
580 static unsigned
581 icu_io_write_buffer_callback(device *me,
582 const void *source,
583 int space,
584 unsigned_word addr,
585 unsigned nr_bytes,
586 cpu *processor,
587 unsigned_word cia)
588 {
589 unsigned_1 val = H2T_1(*(unsigned_1*)source);
590 /* tell the parent device that the interrupt lines have changed.
591 For this fake ICU. The interrupt lines just indicate the cpu to
592 interrupt next */
593 device_interrupt(device_parent(me), me,
594 val, val,
595 processor, cia);
596 return nr_bytes;
597 }
598
599
600 static device_callbacks const icu_callbacks = {
601 generic_init_callback,
602 unimp_device_attach_address,
603 unimp_device_detach_address,
604 icu_io_read_buffer_callback,
605 icu_io_write_buffer_callback,
606 unimp_device_dma_read_buffer,
607 unimp_device_dma_write_buffer,
608 unimp_device_attach_interrupt,
609 unimp_device_detach_interrupt,
610 unimp_device_interrupt,
611 unimp_device_interrupt_ack,
612 unimp_device_ioctl,
613 };
614
615
616 \f
617 /* HALT device: halt@0x<address>,4
618
619 With real hardware, the processor operation is normally terminated
620 through a reset. This device illustrates how a reset device could
621 be attached to an address */
622
623
624 static unsigned
625 halt_io_read_buffer_callback(device *me,
626 void *dest,
627 int space,
628 unsigned_word addr,
629 unsigned nr_bytes,
630 cpu *processor,
631 unsigned_word cia)
632 {
633 cpu_halt(processor, cia, was_exited, 0);
634 return 0;
635 }
636
637
638 static unsigned
639 halt_io_write_buffer_callback(device *me,
640 const void *source,
641 int space,
642 unsigned_word addr,
643 unsigned nr_bytes,
644 cpu *processor,
645 unsigned_word cia)
646 {
647 cpu_halt(processor, cia, was_exited, *(unsigned_1*)source);
648 return 0;
649 }
650
651
652 static device_callbacks const halt_callbacks = {
653 generic_init_callback,
654 unimp_device_attach_address,
655 unimp_device_detach_address,
656 halt_io_read_buffer_callback,
657 halt_io_write_buffer_callback,
658 unimp_device_dma_read_buffer,
659 unimp_device_dma_write_buffer,
660 unimp_device_attach_interrupt,
661 unimp_device_detach_interrupt,
662 unimp_device_interrupt,
663 unimp_device_interrupt_ack,
664 unimp_device_ioctl,
665 };
666
667
668 \f
669 /* Register init device: register
670
671 Properties attached to the register device specify the name/value
672 initialization pair for cpu registers.
673
674 FIXME: A specific processor can be initialized by creating a
675 property with a name like `0.pc'. */
676
677 static void
678 register_init(device *me,
679 const char *name,
680 void *data)
681 {
682 psim *system = (psim*)data;
683 unsigned32 value = device_find_integer_property(me, name);
684 int processor;
685 if (isdigit(name[0]) && name[1] == '.') {
686 processor = atol(name);
687 name += 2;
688 DTRACE(register, ("%d.%s=0x%lx\n", processor, name, (unsigned long)value));
689 }
690 else {
691 processor = -1;
692 DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
693 }
694 psim_write_register(system, processor, /* all processors */
695 &value,
696 name,
697 cooked_transfer);
698 }
699
700
701 static void
702 register_init_callback(device *me,
703 psim *system)
704 {
705 device_traverse_properties(me, register_init, system);
706 }
707
708
709 static device_callbacks const register_callbacks = {
710 register_init_callback,
711 unimp_device_attach_address,
712 unimp_device_detach_address,
713 unimp_device_io_read_buffer,
714 unimp_device_io_write_buffer,
715 unimp_device_dma_read_buffer,
716 unimp_device_dma_write_buffer,
717 unimp_device_attach_interrupt,
718 unimp_device_detach_interrupt,
719 unimp_device_interrupt,
720 unimp_device_interrupt_ack,
721 unimp_device_ioctl,
722 };
723
724
725 \f
726 /* VEA VM device: vm@0x<stack-base>,<nr_bytes>
727
728 A VEA mode device. This sets its self up as the default memory
729 device capturing all accesses (reads/writes) to currently unmapped
730 addresses. If the unmaped access falls within unallocated stack or
731 heap address ranges then memory is allocated and the access is
732 allowed to continue.
733
734 During init phase, this device expects to receive `attach' requests
735 from its children for the text/data/bss memory areas. Typically,
736 this would be done by the binary device.
737
738 STACK: The location of the stack in memory is specified as part of
739 the devices name. Unmaped accesses that fall within the stack
740 space result in the allocated stack being grown downwards so that
741 it includes the page of the culprit access.
742
743 HEAP: During initialization, the vm device monitors all `attach'
744 operations from its children using this to determine the initial
745 location of the heap. The heap is then extended by system calls
746 that frob the heap upper bound variable (see system.c). */
747
748
749 typedef struct _vm_device {
750 /* area of memory valid for stack addresses */
751 unsigned_word stack_base; /* min possible stack value */
752 unsigned_word stack_bound;
753 unsigned_word stack_lower_limit;
754 /* area of memory valid for heap addresses */
755 unsigned_word heap_base;
756 unsigned_word heap_bound;
757 unsigned_word heap_upper_limit;
758 } vm_device;
759
760
761 static void
762 vm_init_callback(device *me,
763 psim *system)
764 {
765 vm_device *vm = (vm_device*)device_data(me);
766
767 /* revert the stack/heap variables to their defaults */
768 vm->stack_lower_limit = vm->stack_bound;
769 vm->heap_base = 0;
770 vm->heap_bound = 0;
771 vm->heap_upper_limit = 0;
772
773 /* establish this device as the default memory handler */
774 device_attach_address(device_parent(me),
775 device_name(me),
776 attach_default,
777 0 /*address space - ignore*/,
778 0 /*addr - ignore*/,
779 0 /*nr_bytes - ignore*/,
780 access_read_write /*access*/,
781 me);
782 }
783
784
785 static void
786 vm_attach_address(device *me,
787 const char *name,
788 attach_type attach,
789 int space,
790 unsigned_word addr,
791 unsigned nr_bytes,
792 access_type access,
793 device *who) /*callback/default*/
794 {
795 vm_device *vm = (vm_device*)device_data(me);
796 /* update end of bss if necessary */
797 if (vm->heap_base < addr + nr_bytes) {
798 vm->heap_base = addr + nr_bytes;
799 vm->heap_bound = addr + nr_bytes;
800 vm->heap_upper_limit = addr + nr_bytes;
801 }
802 device_attach_address(device_parent(me),
803 "vm@0x0,0", /* stop remap */
804 attach_raw_memory,
805 0 /*address space*/,
806 addr,
807 nr_bytes,
808 access,
809 me);
810 }
811
812
813 STATIC_INLINE_DEVICE_TABLE unsigned
814 add_vm_space(device *me,
815 unsigned_word addr,
816 unsigned nr_bytes,
817 cpu *processor,
818 unsigned_word cia)
819 {
820 vm_device *vm = (vm_device*)device_data(me);
821 unsigned_word block_addr;
822 unsigned block_nr_bytes;
823
824 /* an address in the stack area, allocate just down to the addressed
825 page */
826 if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
827 block_addr = FLOOR_PAGE(addr);
828 block_nr_bytes = vm->stack_lower_limit - block_addr;
829 vm->stack_lower_limit = block_addr;
830 }
831 /* an address in the heap area, allocate all of the required heap */
832 else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
833 block_addr = vm->heap_upper_limit;
834 block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
835 vm->heap_upper_limit = vm->heap_bound;
836 }
837 /* oops - an invalid address - abort the cpu */
838 else if (processor != NULL) {
839 cpu_halt(processor, cia, was_signalled, SIGSEGV);
840 return 0;
841 }
842 /* 2*oops - an invalid address and no processor */
843 else {
844 return 0;
845 }
846
847 /* got the parameters, allocate the space */
848 device_attach_address(device_parent(me),
849 "vm@0x0,0", /* stop remap */
850 attach_raw_memory,
851 0 /*address space*/,
852 block_addr,
853 block_nr_bytes,
854 access_read_write,
855 me);
856 return block_nr_bytes;
857 }
858
859
860 static unsigned
861 vm_io_read_buffer_callback(device *me,
862 void *dest,
863 int space,
864 unsigned_word addr,
865 unsigned nr_bytes,
866 cpu *processor,
867 unsigned_word cia)
868 {
869 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
870 memset(dest, 0, nr_bytes); /* always initialized to zero */
871 return nr_bytes;
872 }
873 else
874 return 0;
875 }
876
877
878 static unsigned
879 vm_io_write_buffer_callback(device *me,
880 const void *source,
881 int space,
882 unsigned_word addr,
883 unsigned nr_bytes,
884 cpu *processor,
885 unsigned_word cia)
886 {
887 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
888 return device_dma_write_buffer(device_parent(me), source,
889 space, addr,
890 nr_bytes,
891 0/*violate_read_only*/);
892 }
893 else
894 return 0;
895 }
896
897
898 static void
899 vm_ioctl_callback(device *me,
900 psim *system,
901 cpu *processor,
902 unsigned_word cia,
903 va_list ap)
904 {
905 /* While the caller is notified that the heap has grown by the
906 requested amount, the heap is infact extended out to a page
907 boundary. */
908 vm_device *vm = (vm_device*)device_data(me);
909 unsigned_word new_break = ALIGN_8(cpu_registers(processor)->gpr[3]);
910 unsigned_word old_break = vm->heap_bound;
911 signed_word delta = new_break - old_break;
912 if (delta > 0)
913 vm->heap_bound = ALIGN_PAGE(new_break);
914 cpu_registers(processor)->gpr[0] = 0;
915 cpu_registers(processor)->gpr[3] = new_break;
916 }
917
918
919 static device_callbacks const vm_callbacks = {
920 vm_init_callback,
921 vm_attach_address,
922 passthrough_device_detach_address,
923 vm_io_read_buffer_callback,
924 vm_io_write_buffer_callback,
925 unimp_device_dma_read_buffer,
926 passthrough_device_dma_write_buffer,
927 unimp_device_attach_interrupt,
928 unimp_device_detach_interrupt,
929 unimp_device_interrupt,
930 unimp_device_interrupt_ack,
931 vm_ioctl_callback,
932 };
933
934
935 static void *
936 vea_vm_create(const char *name,
937 device *parent)
938 {
939 vm_device *vm = ZALLOC(vm_device);
940 unsigned_word addr;
941 unsigned nr_bytes;
942
943 /* extract out the stack parameters */
944 if (scand_uw_u(name, &addr, &nr_bytes) != 2)
945 error("vm_device_create() invalid vm device %s\n", name);
946 vm->stack_base = addr;
947 vm->stack_bound = addr + nr_bytes;
948 return vm;
949 }
950
951
952 \f
953 /* Memory init device: memory@0x<addr>,<size>,<access>
954
955 This strange device is used create sections of memory */
956
957 static void
958 memory_init_callback(device *me,
959 psim *system)
960 {
961 unsigned_word addr;
962 unsigned nr_bytes;
963 unsigned access;
964 int nr_args;
965
966 nr_args = scand_uw_u_u(device_name(me), &addr, &nr_bytes, &access);
967 switch (nr_args) {
968 case 2:
969 access = access_read_write_exec;
970 break;
971 case 3:
972 break;
973 default:
974 error("memory_init_callback() invalid memory device %s\n", device_name(me));
975 break;
976 }
977
978 device_attach_address(device_parent(me),
979 device_name(me),
980 attach_raw_memory,
981 0 /*address space*/,
982 addr,
983 nr_bytes,
984 (access_type)access,
985 me);
986 }
987
988
989 static device_callbacks const memory_callbacks = {
990 memory_init_callback,
991 unimp_device_attach_address,
992 unimp_device_detach_address,
993 unimp_device_io_read_buffer,
994 unimp_device_io_write_buffer,
995 unimp_device_dma_read_buffer,
996 unimp_device_dma_write_buffer,
997 unimp_device_attach_interrupt,
998 unimp_device_detach_interrupt,
999 unimp_device_interrupt,
1000 unimp_device_interrupt_ack,
1001 unimp_device_ioctl,
1002 };
1003
1004
1005 \f
1006 /* IOBUS device: iobus@<address>
1007
1008 Simple bus on which some IO devices live */
1009
1010 static void
1011 iobus_attach_address_callback(device *me,
1012 const char *name,
1013 attach_type type,
1014 int space,
1015 unsigned_word addr,
1016 unsigned nr_bytes,
1017 access_type access,
1018 device *who) /*callback/default*/
1019 {
1020 unsigned_word iobus_addr;
1021 /* sanity check */
1022 if (type == attach_default)
1023 error("iobus_attach_address_callback() no default for %s/%s\n",
1024 device_name(me), name);
1025 if (space != 0)
1026 error("iobus_attach_address_callback() no space for %s/%s\n",
1027 device_name(me), name);
1028 /* get the bus address */
1029 if (scand_uw(device_name(me), &iobus_addr) != 1)
1030 error("iobus_attach_address_callback() invalid address for %s\n",
1031 device_name(me));
1032 device_attach_address(device_parent(me),
1033 device_name(me),
1034 type,
1035 0 /*space*/,
1036 iobus_addr + addr,
1037 nr_bytes,
1038 access,
1039 who);
1040 }
1041
1042
1043 STATIC_INLINE_DEVICE_TABLE void
1044 iobus_do_interrupt(event_queue *queue,
1045 void *data)
1046 {
1047 cpu *target = (cpu*)data;
1048 /* try to interrupt the processor. If the attempt fails, try again
1049 on the next tick */
1050 if (!external_interrupt(target))
1051 event_queue_schedule(queue, 1, iobus_do_interrupt, target);
1052 }
1053
1054
1055 static void
1056 iobus_interrupt_callback(device *me,
1057 device *who,
1058 int interrupt_line,
1059 int interrupt_status,
1060 cpu *processor,
1061 unsigned_word cia)
1062 {
1063 /* the interrupt controler can't interrupt a cpu at any time.
1064 Rather it must synchronize with the system clock before
1065 performing an interrupt on the given processor */
1066 psim *system = cpu_system(processor);
1067 cpu *target = psim_cpu(system, interrupt_status);
1068 if (target != NULL) {
1069 event_queue *events = cpu_event_queue(target);
1070 event_queue_schedule(events, 1, iobus_do_interrupt, target);
1071 }
1072 }
1073
1074
1075 static device_callbacks const iobus_callbacks = {
1076 ignore_device_init,
1077 iobus_attach_address_callback,
1078 unimp_device_detach_address,
1079 unimp_device_io_read_buffer,
1080 unimp_device_io_write_buffer,
1081 unimp_device_dma_read_buffer,
1082 unimp_device_dma_write_buffer,
1083 unimp_device_attach_interrupt,
1084 unimp_device_detach_interrupt,
1085 iobus_interrupt_callback,
1086 unimp_device_interrupt_ack,
1087 unimp_device_ioctl,
1088 };
1089
1090
1091 \f
1092 /* FILE device: file@0x<address>,<file-name>
1093 (later - file@0x<address>,<size>,<file-offset>,<file-name>)
1094
1095 Specifies a file to read directly into memory starting at <address> */
1096
1097
1098 static void
1099 file_init_callback(device *me,
1100 psim *system)
1101 {
1102 unsigned_word addr;
1103 int count;
1104 char file_name[1024];
1105
1106 if (scand_uw_c(device_name(me), &addr, file_name, sizeof(file_name)) != 2)
1107 error("devices/file - Usage: file@<address>,<file-name>\n");
1108
1109 /* load the file */
1110 count = dma_file(me, file_name, addr);
1111 if (count < 0)
1112 error("device_table/%s - Problem loading file %s\n", device_name(me), file_name);
1113 }
1114
1115
1116 static device_callbacks const file_callbacks = {
1117 file_init_callback,
1118 unimp_device_attach_address,
1119 unimp_device_detach_address,
1120 unimp_device_io_read_buffer,
1121 unimp_device_io_write_buffer,
1122 unimp_device_dma_read_buffer,
1123 unimp_device_dma_write_buffer,
1124 unimp_device_attach_interrupt,
1125 unimp_device_detach_interrupt,
1126 unimp_device_interrupt,
1127 unimp_device_interrupt_ack,
1128 unimp_device_ioctl,
1129 };
1130
1131
1132 \f
1133 /* DATA device: data@<address>,<count>,<value>
1134
1135 Store <value> at <address> using <count> size transfer */
1136
1137 static void
1138 data_init_callback(device *me,
1139 psim *system)
1140 {
1141 unsigned_word addr;
1142 unsigned count;
1143 unsigned value;
1144 union {
1145 unsigned_1 v1;
1146 unsigned_2 v2;
1147 unsigned_4 v4;
1148 unsigned_8 v8;
1149 } buf;
1150
1151 if (scand_uw_u_u(device_name(me), &addr, &count, &value) != 3)
1152 error("devices/data - Usage: data@<address>,<count>,<value>\n");
1153
1154 /* store the data value */
1155 switch (count) {
1156 case 1:
1157 buf.v1 = H2T_1(value);
1158 break;
1159 case 2:
1160 buf.v2 = H2T_2(value);
1161 break;
1162 case 4:
1163 buf.v4 = H2T_4(value);
1164 break;
1165 case 8:
1166 buf.v8 = H2T_8(value);
1167 break;
1168 }
1169 if (device_dma_write_buffer(device_parent(me),
1170 &buf,
1171 0 /*address-space*/,
1172 addr,
1173 count, /*nr-bytes*/
1174 1 /*violate ro*/) != count) {
1175 error("devices/%s - Problem storing 0x%x at 0x%lx\n",
1176 device_name(me), value, (long)addr);
1177 }
1178 }
1179
1180
1181 static device_callbacks const data_callbacks = {
1182 data_init_callback,
1183 unimp_device_attach_address,
1184 unimp_device_detach_address,
1185 unimp_device_io_read_buffer,
1186 unimp_device_io_write_buffer,
1187 unimp_device_dma_read_buffer,
1188 unimp_device_dma_write_buffer,
1189 unimp_device_attach_interrupt,
1190 unimp_device_detach_interrupt,
1191 unimp_device_interrupt,
1192 unimp_device_interrupt_ack,
1193 unimp_device_ioctl,
1194 };
1195
1196
1197 \f
1198 /* HTAB: htab@<address>,<nr_bytes>
1199 PTE: pte@<real-address>,<virtual-address>,<nr_bytes>,<wimg>,<pp>
1200 PTE: pte@<real-address>,<wimg>,<pp>,<binary>
1201
1202 HTAB defines the location (in physical memory) of a HASH table.
1203 PTE (as a child of HTAB) defines a mapping that is to be entered
1204 into that table.
1205
1206 NB: All the work in this device is done during init by the PTE.
1207 The pte, looks up its parent to determine the address of the HTAB
1208 and then uses DMA calls to establish the required mapping. */
1209
1210
1211 STATIC_INLINE_DEVICE_TABLE void
1212 htab_decode_hash_table(device *parent,
1213 unsigned32 *htaborg,
1214 unsigned32 *htabmask)
1215 {
1216 unsigned_word htab_ra;
1217 unsigned htab_nr_bytes;
1218 unsigned n;
1219 /* determine the location/size of the hash table */
1220 if (parent == NULL
1221 || strncmp(device_name(parent), "htab@", strlen("htab@")) != 0)
1222 error("devices/htab - missing htab device\n");
1223 if (scand_uw_u(device_name(parent), &htab_ra, &htab_nr_bytes) != 2)
1224 error("devices/%s - Usage: htab@<real-addr>,<nr_bytes>\n",
1225 device_name(parent));
1226 for (n = htab_nr_bytes; n > 1; n = n / 2) {
1227 if (n % 2 != 0)
1228 error("devices/%s - htab size 0x%x not a power of two\n",
1229 device_name(parent), htab_nr_bytes);
1230 }
1231 *htaborg = htab_ra;
1232 *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
1233 if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
1234 error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
1235 device_name(parent), *htaborg, *htabmask);
1236 }
1237 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
1238 (unsigned long)*htaborg, (unsigned long)*htabmask));
1239 }
1240
1241
1242 STATIC_INLINE void
1243 htab_map_page(device *me,
1244 unsigned_word ra,
1245 unsigned64 va,
1246 unsigned wimg,
1247 unsigned pp,
1248 unsigned32 htaborg,
1249 unsigned32 htabmask)
1250 {
1251 unsigned64 vpn = va << 12;
1252 unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
1253 unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
1254 unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
1255 ^ EXTRACTED32(page, 0, 15),
1256 7, 31-6);
1257 int h;
1258 for (h = 0; h < 2; h++) {
1259 unsigned32 pteg = (htaborg | (hash & htabmask));
1260 int pti;
1261 for (pti = 0; pti < 8; pti++, pteg += 8) {
1262 unsigned32 current_target_pte0;
1263 unsigned32 current_pte0;
1264 if (device_dma_read_buffer(device_parent(me),
1265 &current_target_pte0,
1266 0, /*space*/
1267 pteg,
1268 sizeof(current_target_pte0)) != 4)
1269 error("htab_init_callback() failed to read a pte at 0x%x\n",
1270 pteg);
1271 current_pte0 = T2H_4(current_target_pte0);
1272 if (!MASKED32(current_pte0, 0, 0)) {
1273 /* empty pte fill it */
1274 unsigned32 pte0 = (MASK32(0, 0)
1275 | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
1276 | INSERTED32(h, 25, 25)
1277 | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
1278 unsigned32 target_pte0 = H2T_4(pte0);
1279 unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
1280 | INSERTED32(wimg, 25, 28)
1281 | INSERTED32(pp, 30, 31));
1282 unsigned32 target_pte1 = H2T_4(pte1);
1283 if (device_dma_write_buffer(device_parent(me),
1284 &target_pte0,
1285 0, /*space*/
1286 pteg,
1287 sizeof(target_pte0),
1288 1/*ro?*/) != 4
1289 || device_dma_write_buffer(device_parent(me),
1290 &target_pte1,
1291 0, /*space*/
1292 pteg + 4,
1293 sizeof(target_pte1),
1294 1/*ro?*/) != 4)
1295 error("htab_init_callback() failed to write a pte a 0x%x\n",
1296 pteg);
1297 DTRACE(htab, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
1298 (unsigned long)va, (unsigned long)ra,
1299 (unsigned long)pteg,
1300 (unsigned long)pte0, (unsigned long)pte1));
1301 return;
1302 }
1303 }
1304 /* re-hash */
1305 hash = MASKED32(~hash, 0, 18);
1306 }
1307 }
1308
1309 STATIC_INLINE_DEVICE_TABLE void
1310 htab_map_region(device *me,
1311 unsigned_word pte_ra,
1312 unsigned_word pte_va,
1313 unsigned nr_bytes,
1314 unsigned wimg,
1315 unsigned pp,
1316 unsigned32 htaborg,
1317 unsigned32 htabmask)
1318 {
1319 unsigned_word ra;
1320 unsigned64 va;
1321 /* go through all pages and create a pte for each */
1322 for (ra = pte_ra, va = (signed_word)pte_va;
1323 ra < pte_ra + nr_bytes;
1324 ra += 0x1000, va += 0x1000) {
1325 htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
1326 }
1327 }
1328
1329 typedef struct _htab_binary_sizes {
1330 unsigned_word text_ra;
1331 unsigned_word text_base;
1332 unsigned_word text_bound;
1333 unsigned_word data_ra;
1334 unsigned_word data_base;
1335 unsigned data_bound;
1336 device *me;
1337 } htab_binary_sizes;
1338
1339 STATIC_INLINE_DEVICE_TABLE void
1340 htab_sum_binary(bfd *abfd,
1341 sec_ptr sec,
1342 PTR data)
1343 {
1344 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
1345 unsigned_word size = bfd_get_section_size_before_reloc (sec);
1346 unsigned_word vma = bfd_get_section_vma (abfd, sec);
1347
1348 /* skip the section if no memory to allocate */
1349 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
1350 return;
1351
1352 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
1353 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
1354 if (sizes->text_bound < vma + size)
1355 sizes->text_bound = ALIGN_PAGE(vma + size);
1356 if (sizes->text_base > vma)
1357 sizes->text_base = FLOOR_PAGE(vma);
1358 }
1359 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
1360 || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
1361 if (sizes->data_bound < vma + size)
1362 sizes->data_bound = ALIGN_PAGE(vma + size);
1363 if (sizes->data_base > vma)
1364 sizes->data_base = FLOOR_PAGE(vma);
1365 }
1366 }
1367
1368 STATIC_INLINE_DEVICE_TABLE void
1369 htab_dma_binary(bfd *abfd,
1370 sec_ptr sec,
1371 PTR data)
1372 {
1373 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
1374 void *section_init;
1375 unsigned_word section_vma;
1376 unsigned_word section_size;
1377 unsigned_word section_ra;
1378 device *me = sizes->me;
1379
1380 /* skip the section if no memory to allocate */
1381 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
1382 return;
1383
1384 /* check/ignore any sections of size zero */
1385 section_size = bfd_get_section_size_before_reloc(sec);
1386 if (section_size == 0)
1387 return;
1388
1389 /* if nothing to load, ignore this one */
1390 if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
1391 return;
1392
1393 /* find where it is to go */
1394 section_vma = bfd_get_section_vma(abfd, sec);
1395 section_ra = 0;
1396 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
1397 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
1398 section_ra = (section_vma - sizes->text_base + sizes->text_ra);
1399 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
1400 section_ra = (section_vma - sizes->data_base + sizes->data_ra);
1401 else
1402 return; /* just ignore it */
1403
1404 DTRACE(htab,
1405 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
1406 bfd_get_section_name(abfd, sec),
1407 (long)section_vma,
1408 (long)section_size,
1409 (long)section_ra,
1410 (long)bfd_get_section_flags(abfd, sec),
1411 bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
1412 bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
1413 bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
1414 bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
1415 bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
1416 ));
1417
1418 /* dma in the sections data */
1419 section_init = zalloc(section_size);
1420 if (!bfd_get_section_contents(abfd,
1421 sec,
1422 section_init, 0,
1423 section_size)) {
1424 bfd_perror("devices/pte");
1425 error("devices/%s - no data loaded\n", device_name(me));
1426 }
1427 if (device_dma_write_buffer(device_parent(me),
1428 section_init,
1429 0 /*space*/,
1430 section_ra,
1431 section_size,
1432 1 /*violate_read_only*/)
1433 != section_size)
1434 error("devices/%s - broken dma transfer\n", device_name(me));
1435 zfree(section_init); /* only free if load */
1436 }
1437
1438
1439 STATIC_INLINE_DEVICE_TABLE void
1440 htab_map_binary(device *me,
1441 unsigned_word ra,
1442 unsigned wimg,
1443 unsigned pp,
1444 char *file_name,
1445 unsigned32 htaborg,
1446 unsigned32 htabmask)
1447 {
1448 htab_binary_sizes sizes;
1449 bfd *image;
1450 sizes.text_base = -1;
1451 sizes.data_base = -1;
1452 sizes.text_bound = 0;
1453 sizes.data_bound = 0;
1454 sizes.me = me;
1455
1456 /* open the file */
1457 image = bfd_openr(file_name, NULL);
1458 if (image == NULL) {
1459 bfd_perror("devices/pte");
1460 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
1461 }
1462
1463 /* check it is valid */
1464 if (!bfd_check_format(image, bfd_object)) {
1465 bfd_close(image);
1466 error("devices/%s - the file %s has an invalid binary format\n",
1467 device_name(me), file_name);
1468 }
1469
1470 /* determine the size of each of the files regions */
1471 bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
1472
1473 /* determine the real addresses of the sections */
1474 sizes.text_ra = ra;
1475 sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
1476 (sizes.text_bound - sizes.text_base));
1477
1478 DTRACE(htab, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
1479 (unsigned long)sizes.text_base,
1480 (unsigned long)sizes.text_bound,
1481 (unsigned long)sizes.text_ra));
1482 DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
1483 (unsigned long)sizes.data_base,
1484 (unsigned long)sizes.data_bound,
1485 (unsigned long)sizes.data_ra));
1486
1487 /* set up virtual memory maps for each of the regions */
1488 htab_map_region(me, sizes.text_ra, sizes.text_base,
1489 sizes.text_bound - sizes.text_base,
1490 wimg, pp,
1491 htaborg, htabmask);
1492 htab_map_region(me, sizes.data_ra, sizes.data_base,
1493 sizes.data_bound - sizes.data_base,
1494 wimg, pp,
1495 htaborg, htabmask);
1496
1497 /* dma the sections into physical memory */
1498 bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
1499 }
1500
1501 static void
1502 htab_init_callback(device *me,
1503 psim *system)
1504 {
1505 if (WITH_TARGET_WORD_BITSIZE != 32)
1506 error("devices/htab: only 32bit targets currently suported\n");
1507
1508 /* only the pte does work */
1509 if (strncmp(device_name(me), "pte@", strlen("pte@")) == 0) {
1510 unsigned32 htaborg;
1511 unsigned32 htabmask;
1512 signed32 pte_va; /* so that 0xff...0 is make 0xffffff00 */
1513 unsigned32 pte_ra;
1514 unsigned pte_nr_bytes;
1515 unsigned pte_wimg;
1516 unsigned pte_pp;
1517 char file_name[1024];
1518
1519 htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
1520
1521 /* handle a normal mapping definition */
1522 if (scand_uw_uw_u_u_u(device_name(me), &pte_ra, &pte_va, &pte_nr_bytes,
1523 &pte_wimg, &pte_pp) == 5) {
1524 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
1525 (unsigned long)pte_ra,
1526 (long)pte_wimg,
1527 (long)pte_pp,
1528 (unsigned long)pte_va,
1529 (long)pte_nr_bytes));
1530 htab_map_region(me, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
1531 htaborg, htabmask);
1532 }
1533 else if (scand_uw_u_u_c(device_name(me), &pte_ra, &pte_wimg, &pte_pp,
1534 file_name, sizeof(file_name)) == 4) {
1535 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, binary=%s\n",
1536 (unsigned long)pte_ra,
1537 (unsigned long)pte_wimg,
1538 (long)pte_pp,
1539 file_name));
1540 htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
1541 htaborg, htabmask);
1542 }
1543 else {
1544 error("devices/%s - Usage: %s\nor\t%s\n",
1545 device_name(me),
1546 "pte@,<real-addr>,<virtual-addr>,<nr-bytes>,<wimg>,<pp>",
1547 "pte@<real-addr>,<wimg>,<pp>,<binary>");
1548 }
1549 }
1550 }
1551
1552
1553 static device_callbacks const htab_callbacks = {
1554 htab_init_callback,
1555 unimp_device_attach_address,
1556 unimp_device_detach_address,
1557 unimp_device_io_read_buffer,
1558 unimp_device_io_write_buffer,
1559 passthrough_device_dma_read_buffer,
1560 passthrough_device_dma_write_buffer,
1561 unimp_device_attach_interrupt,
1562 unimp_device_detach_interrupt,
1563 unimp_device_interrupt,
1564 unimp_device_interrupt_ack,
1565 unimp_device_ioctl,
1566 };
1567
1568
1569 \f
1570 /* Simulator device: sim@0x<address>,<nr_bytes>
1571
1572 Eventually gives access to the hardware configuration. For
1573 instance, it could allow the setting (on the fly) of variables such
1574 as hardware floating-point or strict-alignment.
1575
1576 It's intended use is as part of testing the simulators
1577 functionality */
1578
1579 static device_callbacks const sim_callbacks = {
1580 ignore_device_init,
1581 unimp_device_attach_address,
1582 unimp_device_detach_address,
1583 unimp_device_io_read_buffer,
1584 unimp_device_io_write_buffer,
1585 unimp_device_dma_read_buffer,
1586 unimp_device_dma_write_buffer,
1587 unimp_device_attach_interrupt,
1588 unimp_device_detach_interrupt,
1589 unimp_device_interrupt,
1590 unimp_device_interrupt_ack,
1591 unimp_device_ioctl,
1592 };
1593
1594
1595 \f
1596 /* Load device: binary
1597
1598 Single property the name of which specifies the file (understood by
1599 BFD) that is to be DMAed into memory as part of init */
1600
1601 STATIC_INLINE_DEVICE_TABLE void
1602 update_for_binary_section(bfd *abfd,
1603 asection *the_section,
1604 PTR obj)
1605 {
1606 unsigned_word section_vma;
1607 unsigned_word section_size;
1608 access_type access;
1609 device *me = (device*)obj;
1610
1611 /* skip the section if no memory to allocate */
1612 if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
1613 return;
1614
1615 /* check/ignore any sections of size zero */
1616 section_size = bfd_get_section_size_before_reloc(the_section);
1617 if (section_size == 0)
1618 return;
1619
1620 /* find where it is to go */
1621 section_vma = bfd_get_section_vma(abfd, the_section);
1622
1623 DTRACE(binary,
1624 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
1625 bfd_get_section_name(abfd, the_section),
1626 (long)section_vma,
1627 (long)section_size,
1628 (long)bfd_get_section_flags(abfd, the_section),
1629 bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
1630 bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
1631 bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
1632 bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
1633 bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
1634 ));
1635
1636 /* determine the devices access */
1637 access = access_read;
1638 if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
1639 access |= access_exec;
1640 if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
1641 access |= access_write;
1642
1643 /* if a map, pass up a request to create the memory in core */
1644 if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
1645 device_attach_address(device_parent(me),
1646 device_name(me),
1647 attach_raw_memory,
1648 0 /*address space*/,
1649 section_vma,
1650 section_size,
1651 access,
1652 me);
1653
1654 /* if a load dma in the required data */
1655 if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
1656 void *section_init = zalloc(section_size);
1657 if (!bfd_get_section_contents(abfd,
1658 the_section,
1659 section_init, 0,
1660 section_size)) {
1661 bfd_perror("core:load_section()");
1662 error("load of data failed");
1663 return;
1664 }
1665 if (device_dma_write_buffer(device_parent(me),
1666 section_init,
1667 0 /*space*/,
1668 section_vma,
1669 section_size,
1670 1 /*violate_read_only*/)
1671 != section_size)
1672 error("data_init_callback() broken transfer for %s\n", device_name(me));
1673 zfree(section_init); /* only free if load */
1674 }
1675 }
1676
1677
1678 static void
1679 binary_init_callback(device *me,
1680 psim *system)
1681 {
1682 const char *file_name;
1683 bfd *image;
1684
1685
1686 /* get the property specifying the file name */
1687 file_name = device_find_next_property(me, NULL);
1688
1689 /* open the file */
1690 image = bfd_openr(file_name, NULL);
1691 if (image == NULL) {
1692 bfd_perror("devices/binary");
1693 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
1694 }
1695
1696 /* check it is valid */
1697 if (!bfd_check_format(image, bfd_object)) {
1698 bfd_close(image);
1699 error("devices/%s - the file %s has an invalid binary format\n",
1700 device_name(me), file_name);
1701 }
1702
1703 /* and the data sections */
1704 bfd_map_over_sections(image,
1705 update_for_binary_section,
1706 (PTR)me);
1707
1708 bfd_close(image);
1709 }
1710
1711
1712 static device_callbacks const binary_callbacks = {
1713 binary_init_callback,
1714 unimp_device_attach_address,
1715 unimp_device_detach_address,
1716 unimp_device_io_read_buffer,
1717 unimp_device_io_write_buffer,
1718 unimp_device_dma_read_buffer,
1719 unimp_device_dma_write_buffer,
1720 unimp_device_attach_interrupt,
1721 unimp_device_detach_interrupt,
1722 unimp_device_interrupt,
1723 unimp_device_interrupt_ack,
1724 unimp_device_ioctl,
1725 };
1726
1727
1728 \f
1729 /* Stack device: stack@<type>
1730
1731 Has a single IOCTL to create a stack frame of the specified type.
1732 If <type> is elf or xcoff then a corresponding stack is created.
1733 Any other value of type is ignored.
1734
1735 The IOCTL takes the additional arguments:
1736
1737 unsigned_word stack_end -- where the stack should come down from
1738 char **argv -- ...
1739 char **envp -- ...
1740
1741 */
1742
1743 STATIC_INLINE_DEVICE_TABLE int
1744 sizeof_argument_strings(char **arg)
1745 {
1746 int sizeof_strings = 0;
1747
1748 /* robust */
1749 if (arg == NULL)
1750 return 0;
1751
1752 /* add up all the string sizes (padding as we go) */
1753 for (; *arg != NULL; arg++) {
1754 int len = strlen(*arg) + 1;
1755 sizeof_strings += ALIGN_8(len);
1756 }
1757
1758 return sizeof_strings;
1759 }
1760
1761 STATIC_INLINE_DEVICE_TABLE int
1762 number_of_arguments(char **arg)
1763 {
1764 int nr;
1765 if (arg == NULL)
1766 return 0;
1767 for (nr = 0; *arg != NULL; arg++, nr++);
1768 return nr;
1769 }
1770
1771 STATIC_INLINE_DEVICE_TABLE int
1772 sizeof_arguments(char **arg)
1773 {
1774 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
1775 }
1776
1777 STATIC_INLINE_DEVICE_TABLE void
1778 write_stack_arguments(psim *system,
1779 char **arg,
1780 unsigned_word start_block,
1781 unsigned_word end_block,
1782 unsigned_word start_arg,
1783 unsigned_word end_arg)
1784 {
1785 DTRACE(stack,
1786 ("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",
1787 (long)system, (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
1788 if (arg == NULL)
1789 error("write_arguments: character array NULL\n");
1790 /* only copy in arguments, memory is already zero */
1791 for (; *arg != NULL; arg++) {
1792 int len = strlen(*arg)+1;
1793 unsigned_word target_start_block;
1794 DTRACE(stack,
1795 ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
1796 "**arg", *arg, "start_block", (long)start_block,
1797 "len", (long)len, "start_arg", (long)start_arg));
1798 if (psim_write_memory(system, 0, *arg,
1799 start_block, len,
1800 0/*violate_readonly*/) != len)
1801 error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
1802 *arg, start_block);
1803 target_start_block = H2T_word(start_block);
1804 if (psim_write_memory(system, 0, &target_start_block,
1805 start_arg, sizeof(target_start_block),
1806 0) != sizeof(target_start_block))
1807 error("write_stack_arguments() - write of *arg failed\n");
1808 start_block += ALIGN_8(len);
1809 start_arg += sizeof(start_block);
1810 }
1811 start_arg += sizeof(start_block); /*the null at the end*/
1812 if (start_block != end_block
1813 || ALIGN_8(start_arg) != end_arg)
1814 error("write_stack_arguments - possible corruption\n");
1815 DTRACE(stack,
1816 ("write_stack_arguments() = void\n"));
1817 }
1818
1819 STATIC_INLINE_DEVICE_TABLE void
1820 create_elf_stack_frame(psim *system,
1821 unsigned_word bottom_of_stack,
1822 char **argv,
1823 char **envp)
1824 {
1825 /* fixme - this is over aligned */
1826
1827 /* information block */
1828 const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
1829 const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
1830 const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
1831 const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
1832
1833 /* auxiliary vector - contains only one entry */
1834 const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
1835 const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
1836
1837 /* environment points (including null sentinal) */
1838 const unsigned sizeof_envp = sizeof_arguments(envp);
1839 const unsigned_word start_envp = start_aux - sizeof_envp;
1840
1841 /* argument pointers (including null sentinal) */
1842 const int argc = number_of_arguments(argv);
1843 const unsigned sizeof_argv = sizeof_arguments(argv);
1844 const unsigned_word start_argv = start_envp - sizeof_argv;
1845
1846 /* link register save address - alligned to a 16byte boundary */
1847 const unsigned_word top_of_stack = ((start_argv
1848 - 2 * sizeof(unsigned_word))
1849 & ~0xf);
1850
1851 /* install arguments on stack */
1852 write_stack_arguments(system, envp,
1853 start_envp_block, bottom_of_stack,
1854 start_envp, start_aux);
1855 write_stack_arguments(system, argv,
1856 start_argv_block, start_envp_block,
1857 start_argv, start_envp);
1858
1859 /* set up the registers */
1860 psim_write_register(system, -1,
1861 &top_of_stack, "sp", cooked_transfer);
1862 psim_write_register(system, -1,
1863 &argc, "r3", cooked_transfer);
1864 psim_write_register(system, -1,
1865 &start_argv, "r4", cooked_transfer);
1866 psim_write_register(system, -1,
1867 &start_envp, "r5", cooked_transfer);
1868 psim_write_register(system, -1,
1869 &start_aux, "r6", cooked_transfer);
1870 }
1871
1872 STATIC_INLINE_DEVICE_TABLE void
1873 create_aix_stack_frame(psim *system,
1874 unsigned_word bottom_of_stack,
1875 char **argv,
1876 char **envp)
1877 {
1878 unsigned_word core_envp;
1879 unsigned_word core_argv;
1880 unsigned_word core_argc;
1881 unsigned_word core_aux;
1882 unsigned_word top_of_stack;
1883
1884 /* cheat - create an elf stack frame */
1885 create_elf_stack_frame(system, bottom_of_stack, argv, envp);
1886
1887 /* extract argument addresses from registers */
1888 psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
1889 psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
1890 psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
1891 psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
1892 psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
1893
1894 /* extract arguments from registers */
1895 error("create_aix_stack_frame() - what happens next?\n");
1896 }
1897
1898
1899
1900 static void
1901 stack_ioctl_callback(device *me,
1902 psim *system,
1903 cpu *processor,
1904 unsigned_word cia,
1905 va_list ap)
1906 {
1907 unsigned_word stack_pointer;
1908 const char *stack_type;
1909 char **argv;
1910 char **envp;
1911 stack_pointer = va_arg(ap, unsigned_word);
1912 argv = va_arg(ap, char **);
1913 envp = va_arg(ap, char **);
1914 DTRACE(stack,
1915 ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
1916 (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
1917 stack_type = device_find_next_property(me, NULL);
1918 if (stack_type != NULL) {
1919 if (strcmp(stack_type, "elf") == 0)
1920 create_elf_stack_frame(system, stack_pointer, argv, envp);
1921 else if (strcmp(stack_type, "xcoff") == 0)
1922 create_aix_stack_frame(system, stack_pointer, argv, envp);
1923 }
1924 DTRACE(stack,
1925 ("stack_ioctl_callback() = void\n"));
1926 }
1927
1928 \f
1929
1930
1931 static device_callbacks const stack_callbacks = {
1932 ignore_device_init,
1933 unimp_device_attach_address,
1934 unimp_device_detach_address,
1935 unimp_device_io_read_buffer,
1936 unimp_device_io_write_buffer,
1937 unimp_device_dma_read_buffer,
1938 unimp_device_dma_write_buffer,
1939 unimp_device_attach_interrupt,
1940 unimp_device_detach_interrupt,
1941 unimp_device_interrupt,
1942 unimp_device_interrupt_ack,
1943 stack_ioctl_callback,
1944 };
1945
1946
1947 \f
1948 device_descriptor device_table[] = {
1949 { "console", console_create, &console_callbacks },
1950 { "memory", NULL, &memory_callbacks },
1951 { "vm", vea_vm_create, &vm_callbacks },
1952 { "halt", NULL, &halt_callbacks },
1953 { "icu", NULL, &icu_callbacks },
1954 { "register", NULL, &register_callbacks },
1955 { "iobus", NULL, &iobus_callbacks },
1956 { "file", NULL, &file_callbacks },
1957 { "data", NULL, &data_callbacks },
1958 { "htab", NULL, &htab_callbacks },
1959 { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
1960 { "stack", NULL, &stack_callbacks },
1961 { "sim", NULL, &sim_callbacks },
1962 { "load-binary", NULL, &binary_callbacks },
1963 { "map-binary", NULL, &binary_callbacks },
1964 { "options", NULL, &passthrough_callbacks },
1965 { "init", NULL, &passthrough_callbacks },
1966 { "chosen", NULL, &passthrough_callbacks },
1967 { NULL },
1968 };
1969
1970 #endif /* _DEVICE_TABLE_C_ */
This page took 0.071226 seconds and 4 git commands to generate.