* gennltvals.sh: Add fr30 support.
[deliverable/binutils-gdb.git] / sim / ppc / device_table.c
CommitLineData
cb7a6892
MM
1/* This file is part of the program psim.
2
d6103e8e 3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
cb7a6892
MM
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
93fac324
MM
22#ifndef _DEVICE_TABLE_C_
23#define _DEVICE_TABLE_C_
cb7a6892 24
93fac324
MM
25#ifndef STATIC_INLINE_DEVICE_TABLE
26#define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
cb7a6892
MM
27#endif
28
cb7a6892 29#include <stdio.h>
cb7a6892 30#include <fcntl.h>
dec38dac
MM
31#include <signal.h>
32#include <stdarg.h>
979c3c25 33#include <ctype.h>
cb7a6892 34
93fac324
MM
35#include "device_table.h"
36
cb7a6892
MM
37#include "events.h"
38
c494cadd
MM
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
43#ifdef HAVE_STDLIB_H
44#include <stdlib.h>
45#endif
46
dec38dac
MM
47#include "cpu.h"
48
49#include "bfd.h"
cb7a6892
MM
50
51/* Helper functions */
52
dec38dac
MM
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
fe098bf4 57typedef struct _generic_reg_spec {
d6103e8e
MM
58 unsigned32 base;
59 unsigned32 size;
fe098bf4
MM
60} generic_reg_spec;
61
d6103e8e
MM
62
63void
fe098bf4 64generic_device_init_address(device *me)
cb7a6892 65{
d6103e8e 66 const device_property *reg = device_find_array_property(me, "reg");
fe098bf4
MM
67 const generic_reg_spec *spec = reg->array;
68 int nr_entries = reg->sizeof_array / sizeof(generic_reg_spec);
d6103e8e 69
fe098bf4 70 if ((reg->sizeof_array % sizeof(generic_reg_spec)) != 0)
d6103e8e
MM
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 }
cb7a6892
MM
85}
86
d6103e8e
MM
87int
88generic_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
112int
113generic_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}
cb7a6892 134
1dc7c0ed 135/* DMA a file into memory */
93fac324
MM
136STATIC_INLINE_DEVICE_TABLE int
137dma_file(device *me,
1dc7c0ed
MM
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) {
93fac324
MM
154 inc = fread(buf, 1, sizeof(buf), image);
155 if (feof(image) || ferror(image))
1dc7c0ed 156 break;
93fac324
MM
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) {
1dc7c0ed
MM
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
dec38dac
MM
176\f
177/* ignore/passthrough versions of each function */
178
93fac324 179void
fe098bf4 180passthrough_device_address_attach(device *me,
93fac324
MM
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*/
dec38dac 188{
93fac324
MM
189 device_attach_address(device_parent(me), name, attach,
190 space, addr, nr_bytes,
191 access,
192 who);
dec38dac
MM
193}
194
93fac324 195void
fe098bf4 196passthrough_device_address_detach(device *me,
93fac324
MM
197 const char *name,
198 attach_type attach,
199 int space,
200 unsigned_word addr,
d6103e8e
MM
201 unsigned nr_bytes,
202 access_type access,
203 device *who) /*callback/default*/
dec38dac 204{
93fac324
MM
205 device_detach_address(device_parent(me), name, attach,
206 space, addr, nr_bytes, access,
207 who);
dec38dac
MM
208}
209
93fac324
MM
210unsigned
211passthrough_device_dma_read_buffer(device *me,
d6103e8e
MM
212 void *dest,
213 int space,
214 unsigned_word addr,
215 unsigned nr_bytes)
dec38dac 216{
93fac324
MM
217 return device_dma_read_buffer(device_parent(me), dest,
218 space, addr, nr_bytes);
dec38dac
MM
219}
220
93fac324
MM
221unsigned
222passthrough_device_dma_write_buffer(device *me,
dec38dac 223 const void *source,
5b4d72dd 224 int space,
dec38dac
MM
225 unsigned_word addr,
226 unsigned nr_bytes,
227 int violate_read_only_section)
228{
93fac324
MM
229 return device_dma_write_buffer(device_parent(me), source,
230 space, addr,
231 nr_bytes,
232 violate_read_only_section);
dec38dac
MM
233}
234
d6103e8e
MM
235int
236ignore_device_unit_decode(device *me,
237 const char *unit,
238 device_unit *phys)
dec38dac 239{
d6103e8e
MM
240 memset(phys, 0, sizeof(device_unit));
241 return 0;
dec38dac
MM
242}
243
244
93fac324 245static const device_callbacks passthrough_callbacks = {
fe098bf4
MM
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, },
dec38dac
MM
254};
255
256
257\f
d6103e8e 258/* Register init device: register@<nothing>
dec38dac 259
93fac324 260 Properties attached to the register device specify the name/value
979c3c25
MM
261 initialization pair for cpu registers.
262
d6103e8e
MM
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. */
dec38dac 269
93fac324 270static void
d6103e8e 271do_register_init(device *me,
d6103e8e
MM
272 const device_property *prop)
273{
fe098bf4 274 psim *system = device_system(me);
d6103e8e
MM
275 if (prop != NULL) {
276 const char *name = prop->name;
277 unsigned32 value = device_find_integer_property(me, name);
278 int processor;
279
fe098bf4 280 do_register_init(me, device_next_property(prop));
d6103e8e
MM
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);
979c3c25 298 }
93fac324 299}
d6103e8e 300
93fac324
MM
301
302static void
fe098bf4 303register_init_data_callback(device *me)
dec38dac 304{
d6103e8e 305 const device_property *prop = device_find_property(me, NULL);
fe098bf4 306 do_register_init(me, prop);
dec38dac
MM
307}
308
309
310static device_callbacks const register_callbacks = {
fe098bf4
MM
311 { NULL, register_init_data_callback, },
312 { NULL, }, /* address */
313 { NULL, }, /* IO */
314 { NULL, }, /* DMA */
315 { NULL, }, /* interrupt */
316 { NULL, }, /* unit */
dec38dac
MM
317};
318
319
320\f
d6103e8e
MM
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
328static void
fe098bf4 329trace_init_data_callback(device *me)
d6103e8e
MM
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
341static device_callbacks const trace_callbacks = {
fe098bf4
MM
342 { NULL, trace_init_data_callback, },
343 { NULL, }, /* address */
344 { NULL, }, /* IO */
345 { NULL, }, /* DMA */
346 { NULL, }, /* interrupt */
347 { NULL, }, /* unit */
d6103e8e
MM
348};
349
350
351\f
352/* VEA VM:
353
354 vm@<stack-base>
355 stack-base =
356 nr-bytes =
dec38dac
MM
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
379typedef 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
93fac324 391static void
fe098bf4 392vm_init_address_callback(device *me)
dec38dac 393{
93fac324 394 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
395
396 /* revert the stack/heap variables to their defaults */
d6103e8e
MM
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"));
dec38dac
MM
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 */
93fac324
MM
406 device_attach_address(device_parent(me),
407 device_name(me),
fe098bf4 408 attach_callback + 1,
93fac324
MM
409 0 /*address space - ignore*/,
410 0 /*addr - ignore*/,
fe098bf4 411 (((unsigned)0)-1) /*nr_bytes - ignore*/,
93fac324
MM
412 access_read_write /*access*/,
413 me);
dec38dac
MM
414}
415
416
93fac324
MM
417static void
418vm_attach_address(device *me,
dec38dac 419 const char *name,
5b4d72dd
MM
420 attach_type attach,
421 int space,
dec38dac
MM
422 unsigned_word addr,
423 unsigned nr_bytes,
424 access_type access,
93fac324 425 device *who) /*callback/default*/
dec38dac 426{
93fac324 427 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
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 }
93fac324
MM
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);
dec38dac
MM
442}
443
444
93fac324
MM
445STATIC_INLINE_DEVICE_TABLE unsigned
446add_vm_space(device *me,
dec38dac
MM
447 unsigned_word addr,
448 unsigned nr_bytes,
449 cpu *processor,
450 unsigned_word cia)
451{
93fac324 452 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
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 */
93fac324
MM
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);
dec38dac
MM
488 return block_nr_bytes;
489}
490
491
93fac324
MM
492static unsigned
493vm_io_read_buffer_callback(device *me,
dec38dac 494 void *dest,
5b4d72dd 495 int space,
dec38dac
MM
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) {
1dc7c0ed 502 memset(dest, 0, nr_bytes); /* always initialized to zero */
dec38dac
MM
503 return nr_bytes;
504 }
505 else
506 return 0;
507}
508
509
93fac324
MM
510static unsigned
511vm_io_write_buffer_callback(device *me,
dec38dac 512 const void *source,
5b4d72dd 513 int space,
dec38dac
MM
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) {
93fac324
MM
520 return device_dma_write_buffer(device_parent(me), source,
521 space, addr,
522 nr_bytes,
523 0/*violate_read_only*/);
dec38dac
MM
524 }
525 else
526 return 0;
527}
528
529
fe098bf4 530static int
93fac324 531vm_ioctl_callback(device *me,
dec38dac
MM
532 psim *system,
533 cpu *processor,
534 unsigned_word cia,
93fac324 535 va_list ap)
dec38dac
MM
536{
537 /* While the caller is notified that the heap has grown by the
fe098bf4 538 requested amount, the heap is actually extended out to a page
dec38dac 539 boundary. */
93fac324 540 vm_device *vm = (vm_device*)device_data(me);
fe098bf4
MM
541 unsigned_word requested_break = va_arg(ap, unsigned_word);
542 unsigned_word new_break = ALIGN_8(requested_break);
dec38dac
MM
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);
fe098bf4 547 return 0;
dec38dac
MM
548}
549
550
551static device_callbacks const vm_callbacks = {
fe098bf4
MM
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 */
dec38dac
MM
562 vm_ioctl_callback,
563};
564
565
93fac324 566static void *
dec38dac 567vea_vm_create(const char *name,
d6103e8e
MM
568 const device_unit *address,
569 const char *args,
93fac324 570 device *parent)
dec38dac
MM
571{
572 vm_device *vm = ZALLOC(vm_device);
93fac324 573 return vm;
dec38dac
MM
574}
575
576
dec38dac
MM
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
93fac324 584static void
fe098bf4 585file_init_data_callback(device *me)
cb7a6892 586{
1dc7c0ed 587 int count;
d6103e8e
MM
588 const char *file_name = device_find_string_property(me, "file-name");
589 unsigned_word addr = device_find_integer_property(me, "real-address");
1dc7c0ed
MM
590 /* load the file */
591 count = dma_file(me, file_name, addr);
592 if (count < 0)
d6103e8e
MM
593 error("device_table/%s - Problem loading file %s\n",
594 device_name(me), file_name);
dec38dac 595}
cb7a6892 596
cb7a6892 597
dec38dac 598static device_callbacks const file_callbacks = {
fe098bf4
MM
599 { NULL, file_init_data_callback, },
600 { NULL, }, /* address */
601 { NULL, }, /* IO */
602 { NULL, }, /* DMA */
603 { NULL, }, /* interrupt */
604 { NULL, }, /* unit */
dec38dac
MM
605};
606
607
93fac324 608\f
d6103e8e
MM
609/* DATA device: data@<address>
610
611 <data> - property containing the value to store
612 <real-address> - address to store data at
93fac324 613
d6103e8e 614 Store <data> at <address> using approperiate byte order */
93fac324
MM
615
616static void
fe098bf4 617data_init_data_callback(device *me)
93fac324 618{
d6103e8e
MM
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 }
93fac324 637 break;
d6103e8e
MM
638 default:
639 error("devices/%s - write of this data is not yet implemented\n", device_name(me));
93fac324
MM
640 break;
641 }
93fac324
MM
642}
643
644
645static device_callbacks const data_callbacks = {
fe098bf4
MM
646 { NULL, data_init_data_callback, },
647 { NULL, }, /* address */
648 { NULL, }, /* IO */
649 { NULL, }, /* DMA */
650 { NULL, }, /* interrupt */
651 { NULL, }, /* unit */
93fac324
MM
652};
653
654
dec38dac 655\f
d6103e8e
MM
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
dec38dac
MM
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
93fac324
MM
683STATIC_INLINE_DEVICE_TABLE void
684htab_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
d6103e8e
MM
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");
93fac324
MM
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 }
979c3c25
MM
708 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
709 (unsigned long)*htaborg, (unsigned long)*htabmask));
93fac324
MM
710}
711
93fac324
MM
712STATIC_INLINE void
713htab_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) {
979c3c25
MM
732 unsigned32 current_target_pte0;
733 unsigned32 current_pte0;
93fac324 734 if (device_dma_read_buffer(device_parent(me),
979c3c25 735 &current_target_pte0,
93fac324
MM
736 0, /*space*/
737 pteg,
979c3c25 738 sizeof(current_target_pte0)) != 4)
93fac324
MM
739 error("htab_init_callback() failed to read a pte at 0x%x\n",
740 pteg);
979c3c25
MM
741 current_pte0 = T2H_4(current_target_pte0);
742 if (!MASKED32(current_pte0, 0, 0)) {
93fac324
MM
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));
979c3c25 748 unsigned32 target_pte0 = H2T_4(pte0);
93fac324
MM
749 unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
750 | INSERTED32(wimg, 25, 28)
751 | INSERTED32(pp, 30, 31));
979c3c25 752 unsigned32 target_pte1 = H2T_4(pte1);
93fac324 753 if (device_dma_write_buffer(device_parent(me),
979c3c25 754 &target_pte0,
93fac324
MM
755 0, /*space*/
756 pteg,
979c3c25 757 sizeof(target_pte0),
93fac324
MM
758 1/*ro?*/) != 4
759 || device_dma_write_buffer(device_parent(me),
979c3c25 760 &target_pte1,
93fac324
MM
761 0, /*space*/
762 pteg + 4,
979c3c25 763 sizeof(target_pte1),
93fac324
MM
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
779STATIC_INLINE_DEVICE_TABLE void
780htab_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
799typedef 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
809STATIC_INLINE_DEVICE_TABLE void
810htab_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
838STATIC_INLINE_DEVICE_TABLE void
839htab_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
93fac324
MM
908STATIC_INLINE_DEVICE_TABLE void
909htab_map_binary(device *me,
910 unsigned_word ra,
911 unsigned wimg,
912 unsigned pp,
d6103e8e 913 const char *file_name,
93fac324
MM
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",
979c3c25
MM
948 (unsigned long)sizes.text_base,
949 (unsigned long)sizes.text_bound,
950 (unsigned long)sizes.text_ra));
93fac324 951 DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
979c3c25
MM
952 (unsigned long)sizes.data_base,
953 (unsigned long)sizes.data_bound,
954 (unsigned long)sizes.data_ra));
93fac324
MM
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
970static void
fe098bf4 971htab_init_data_callback(device *me)
dec38dac 972{
1dc7c0ed
MM
973 if (WITH_TARGET_WORD_BITSIZE != 32)
974 error("devices/htab: only 32bit targets currently suported\n");
93fac324 975
dec38dac 976 /* only the pte does work */
d6103e8e 977 if (strcmp(device_name(me), "pte") == 0) {
93fac324
MM
978 unsigned32 htaborg;
979 unsigned32 htabmask;
1dc7c0ed 980
93fac324 981 htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
1dc7c0ed 982
d6103e8e
MM
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",
979c3c25
MM
990 (unsigned long)pte_ra,
991 (unsigned long)pte_wimg,
992 (long)pte_pp,
993 file_name));
93fac324
MM
994 htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
995 htaborg, htabmask);
996 }
997 else {
d6103e8e
MM
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);
1dc7c0ed 1013 }
dec38dac 1014 }
cb7a6892
MM
1015}
1016
dec38dac
MM
1017
1018static device_callbacks const htab_callbacks = {
fe098bf4
MM
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, },
dec38dac 1027};
cb7a6892
MM
1028
1029
dec38dac 1030\f
93fac324 1031/* Load device: binary
cb7a6892 1032
93fac324
MM
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 */
cb7a6892 1035
93fac324 1036STATIC_INLINE_DEVICE_TABLE void
5b4d72dd
MM
1037update_for_binary_section(bfd *abfd,
1038 asection *the_section,
1039 PTR obj)
cb7a6892 1040{
dec38dac
MM
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
5b4d72dd 1058 DTRACE(binary,
c5addc19 1059 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
5b4d72dd 1060 bfd_get_section_name(abfd, the_section),
c5addc19
MM
1061 (long)section_vma,
1062 (long)section_size,
1063 (long)bfd_get_section_flags(abfd, the_section),
5b4d72dd
MM
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 ));
dec38dac 1070
fe098bf4
MM
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
dec38dac
MM
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 */
93fac324
MM
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);
dec38dac
MM
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 }
93fac324
MM
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*/)
dec38dac 1110 != section_size)
93fac324 1111 error("data_init_callback() broken transfer for %s\n", device_name(me));
dec38dac
MM
1112 zfree(section_init); /* only free if load */
1113 }
cb7a6892
MM
1114}
1115
dec38dac 1116
93fac324 1117static void
fe098bf4 1118binary_init_data_callback(device *me)
cb7a6892 1119{
d6103e8e
MM
1120 /* get the file name */
1121 const char *file_name = device_find_string_property(me, "file-name");
dec38dac
MM
1122 bfd *image;
1123
dec38dac
MM
1124 /* open the file */
1125 image = bfd_openr(file_name, NULL);
1126 if (image == NULL) {
1dc7c0ed 1127 bfd_perror("devices/binary");
93fac324 1128 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
dec38dac
MM
1129 }
1130
1131 /* check it is valid */
1132 if (!bfd_check_format(image, bfd_object)) {
dec38dac 1133 bfd_close(image);
93fac324
MM
1134 error("devices/%s - the file %s has an invalid binary format\n",
1135 device_name(me), file_name);
dec38dac
MM
1136 }
1137
1138 /* and the data sections */
1139 bfd_map_over_sections(image,
5b4d72dd 1140 update_for_binary_section,
dec38dac
MM
1141 (PTR)me);
1142
1143 bfd_close(image);
cb7a6892
MM
1144}
1145
1146
dec38dac 1147static device_callbacks const binary_callbacks = {
fe098bf4
MM
1148 { NULL, binary_init_data_callback, },
1149 { NULL, }, /* address */
1150 { NULL, }, /* IO */
1151 { NULL, }, /* DMA */
1152 { NULL, }, /* interrupt */
1153 { NULL, }, /* unit */
cb7a6892
MM
1154};
1155
dec38dac
MM
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
93fac324 1172STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
1173sizeof_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
93fac324 1190STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
1191number_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
93fac324 1200STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
1201sizeof_arguments(char **arg)
1202{
1203 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
1204}
1205
93fac324 1206STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1207write_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{
5b4d72dd 1214 DTRACE(stack,
c5addc19
MM
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));
dec38dac
MM
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;
5b4d72dd 1223 DTRACE(stack,
c5addc19
MM
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));
dec38dac
MM
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");
5b4d72dd
MM
1244 DTRACE(stack,
1245 ("write_stack_arguments() = void\n"));
dec38dac
MM
1246}
1247
93fac324 1248STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1249create_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
93fac324 1301STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1302create_aix_stack_frame(psim *system,
1303 unsigned_word bottom_of_stack,
1304 char **argv,
1305 char **envp)
cb7a6892 1306{
dec38dac
MM
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
cb7a6892 1328
fe098bf4 1329static int
93fac324 1330stack_ioctl_callback(device *me,
dec38dac
MM
1331 psim *system,
1332 cpu *processor,
1333 unsigned_word cia,
93fac324 1334 va_list ap)
dec38dac 1335{
dec38dac 1336 unsigned_word stack_pointer;
93fac324 1337 const char *stack_type;
dec38dac
MM
1338 char **argv;
1339 char **envp;
dec38dac
MM
1340 stack_pointer = va_arg(ap, unsigned_word);
1341 argv = va_arg(ap, char **);
1342 envp = va_arg(ap, char **);
5b4d72dd 1343 DTRACE(stack,
c5addc19 1344 ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
93fac324 1345 (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
d6103e8e
MM
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);
5b4d72dd
MM
1351 DTRACE(stack,
1352 ("stack_ioctl_callback() = void\n"));
fe098bf4 1353 return 0;
cb7a6892
MM
1354}
1355
dec38dac 1356static device_callbacks const stack_callbacks = {
fe098bf4
MM
1357 { NULL, },
1358 { NULL, }, /* address */
1359 { NULL, }, /* IO */
1360 { NULL, }, /* DMA */
1361 { NULL, }, /* interrupt */
1362 { NULL, }, /* unit */
1363 { NULL, }, /* instance */
dec38dac 1364 stack_ioctl_callback,
cb7a6892
MM
1365};
1366
1367
dec38dac 1368\f
fe098bf4 1369static const device_descriptor old_device_table[] = {
93fac324 1370 { "vm", vea_vm_create, &vm_callbacks },
dec38dac 1371 { "register", NULL, &register_callbacks },
dec38dac 1372 { "file", NULL, &file_callbacks },
93fac324 1373 { "data", NULL, &data_callbacks },
dec38dac
MM
1374 { "htab", NULL, &htab_callbacks },
1375 { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
1376 { "stack", NULL, &stack_callbacks },
dec38dac
MM
1377 { "load-binary", NULL, &binary_callbacks },
1378 { "map-binary", NULL, &binary_callbacks },
d6103e8e
MM
1379 /* standard OpenBoot devices */
1380 { "aliases", NULL, &passthrough_callbacks },
93fac324 1381 { "options", NULL, &passthrough_callbacks },
93fac324 1382 { "chosen", NULL, &passthrough_callbacks },
d6103e8e
MM
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 },
dec38dac 1388 { NULL },
cb7a6892
MM
1389};
1390
fe098bf4
MM
1391const device_descriptor *const device_table[] = {
1392 old_device_table,
1393#include "hw.c"
1394 NULL,
1395};
1396
1397
93fac324 1398#endif /* _DEVICE_TABLE_C_ */
This page took 0.188781 seconds and 4 git commands to generate.