gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / sim / ppc / hw_init.c
CommitLineData
c906108c
SS
1/* This file is part of the program psim.
2
dcb74f96 3 Copyright 1994, 1997, 2003, 2004 Andrew Cagney
c906108c
SS
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
3fd725ef 7 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
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
51b318de 16 along with this program; if not, see <http://www.gnu.org/licenses/>.
c906108c
SS
17
18 */
19
20
21#ifndef _HW_INIT_C_
22#define _HW_INIT_C_
23
24#include "device_table.h"
25#include "bfd.h"
26#include "psim.h"
27
28
29/* DMA a file into memory */
30static int
31dma_file(device *me,
32 const char *file_name,
33 unsigned_word addr)
34{
35 int count;
36 int inc;
37 FILE *image;
38 char buf[1024];
39
40 /* get it open */
41 image = fopen(file_name, "r");
42 if (image == NULL)
43 return -1;
44
45 /* read it in slowly */
46 count = 0;
47 while (1) {
48 inc = fread(buf, 1, sizeof(buf), image);
d4481806 49 if (inc <= 0)
c906108c
SS
50 break;
51 if (device_dma_write_buffer(device_parent(me),
52 buf,
53 0 /*address-space*/,
54 addr+count,
55 inc /*nr-bytes*/,
56 1 /*violate ro*/) != inc) {
57 fclose(image);
58 return -1;
59 }
60 count += inc;
61 }
62
63 /* close down again */
64 fclose(image);
65
66 return count;
67}
68
69
70/* DEVICE
71
72 file - load a file into memory
73
74 DESCRIPTION
75
76 Loads the entire contents of <file-name> into memory at starting at
77 <<real-address>>. Assumes that memory exists for the load.
78
79 PROPERTIES
80
81 file-name = <string>
82
83 Name of the file to be loaded into memory
84
85 real-address = <integer>
86
87 Real address at which the file is to be loaded */
88
89static void
90hw_file_init_data_callback(device *me)
91{
92 int count;
93 const char *file_name = device_find_string_property(me, "file-name");
94 unsigned_word addr = device_find_integer_property(me, "real-address");
95 /* load the file */
96 count = dma_file(me, file_name, addr);
97 if (count < 0)
98 device_error(me, "Problem loading file %s\n", file_name);
99}
100
101
102static device_callbacks const hw_file_callbacks = {
103 { NULL, hw_file_init_data_callback, },
104 { NULL, }, /* address */
105 { NULL, }, /* IO */
106 { NULL, }, /* DMA */
107 { NULL, }, /* interrupt */
108 { NULL, }, /* unit */
109};
110
111
112/* DEVICE
113
114
115 data - initialize a memory location with specified data
116
117
118 DESCRIPTION
119
120
121 The pseudo device <<data>> provides a mechanism specifying the
122 initialization of a small section of memory.
123
124 Normally, the data would be written using a dma operation.
125 However, for some addresses this will not result in the desired
126 result. For instance, to initialize an address in an eeprom,
127 instead of a simple dma of the data, a sequence of writes (and then
128 real delays) that program the eeprom would be required.
129
130 For dma write initialization, the data device will write the
131 specified <<data>> to <<real-address>> using a normal dma.
132
133 For instance write initialization, the specified <<instance>> is
134 opened. Then a seek to the <<real-address>> is performed followed
135 by a write of the data.
136
137
138 Integer properties are stored using the target's endian mode.
139
140
141 PROPERTIES
142
143
144 data = <any-valid-property> (required)
145
146 Data to be loaded into memory. The property type determines how it
147 is loaded.
148
149
150 real-address = <integer> (required)
151
152 Start address at which the data is to be stored.
153
154
155 instance = <string> (optional)
156
157 Instance specification of the device that is to be opened so that
158 the specified data can be written to it.
159
160
161 EXAMPLES
162
163
164 The examples below illustrate the two alternative mechanisms that
165 can be used to store the value 0x12345678 at address 0xfff00c00,
166 which is normally part of the 512k system eeprom.
167
168
169 If the eeprom is being modeled by ram (<<memory>> device) then the
170 standard dma initialization can be used. By convention: the data
171 devices are uniquely identified by argumenting them with the
172 destinations real address; and all data devices are put under the
173 node <</openprom/init>>.
174
175 | /openprom/memory@0xfff00000/reg 0xfff00000 0x80000
176 | /openprom/init/data@0x1000/data 0x12345678
177 | /openprom/init/data@0x1000/real-address 0x1000
178
179
180 If instead a real eeprom was being used the instance write method
181 would instead need to be used (storing just a single byte in an
182 eeprom requires a complex sequence of accesses). The
183 <<real-address>> is specified as <<0x0c00>> which is the offset
184 into the eeprom. For brevity, most of the eeprom properties have
185 been omited.
186
187 | /iobus/eeprom@0xfff00000/reg 0xfff00000 0x80000
188 | /openprom/init/data@0xfff00c00/real-address 0x0c00
189 | /openprom/init/data@0xfff00c00/data 0x12345667
190 | /openprom/init/data@0xfff00c00/instance /iobus/eeprom@0xfff00000/reg
191
192
193 BUGS
194
195
196 At present, only <<integer>> properties can be specified for an
197 initial data value.
198
199 */
200
201
202static void
203hw_data_init_data_callback(device *me)
204{
205 unsigned_word addr = device_find_integer_property(me, "real-address");
206 const device_property *data = device_find_property(me, "data");
207 const char *instance_spec = (device_find_property(me, "instance") != NULL
208 ? device_find_string_property(me, "instance")
209 : NULL);
210 device_instance *instance = NULL;
211 if (data == NULL)
212 device_error(me, "missing property <data>\n");
213 if (instance_spec != NULL)
214 instance = tree_instance(me, instance_spec);
215 switch (data->type) {
216 case integer_property:
217 {
218 unsigned_cell buf = device_find_integer_property(me, "data");
219 H2T(buf);
220 if (instance == NULL) {
221 if (device_dma_write_buffer(device_parent(me),
222 &buf,
223 0 /*address-space*/,
224 addr,
225 sizeof(buf), /*nr-bytes*/
226 1 /*violate ro*/) != sizeof(buf))
227 device_error(me, "Problem storing integer 0x%x at 0x%lx\n",
228 (unsigned)buf, (unsigned long)addr);
229 }
230 else {
231 if (device_instance_seek(instance, 0, addr) < 0
232 || device_instance_write(instance, &buf, sizeof(buf)) != sizeof(buf))
233 device_error(me, "Problem storing integer 0x%x at 0x%lx of instance %s\n",
234 (unsigned)buf, (unsigned long)addr, instance_spec);
235 }
236 }
237 break;
238 default:
239 device_error(me, "Write of this data is not yet implemented\n");
240 break;
241 }
242 if (instance != NULL)
243 device_instance_delete(instance);
244}
245
246
247static device_callbacks const hw_data_callbacks = {
248 { NULL, hw_data_init_data_callback, },
249 { NULL, }, /* address */
250 { NULL, }, /* IO */
251 { NULL, }, /* DMA */
252 { NULL, }, /* interrupt */
253 { NULL, }, /* unit */
254};
255
256
257/* DEVICE
258
259
260 load-binary - load binary segments into memory
261
262
263 DESCRIPTION
264
265 Each loadable segment of the specified binary is loaded into memory
266 at its required address. It is assumed that the memory at those
267 addresses already exists.
268
269 This device is normally used to load an executable into memory as
270 part of real mode simulation.
271
272
273 PROPERTIES
274
275
276 file-name = <string>
277
278 Name of the binary to be loaded.
279
280
281 claim = <anything> (optional)
282
283 If this property is present, the real memory that is to be used by
284 the image being loaded will be claimed from the memory node
285 (specified by the ihandle <</chosen/memory>>).
286
287
288 BUGS
289
290
291 When loading the binary the bfd virtual-address is used. It should
292 be using the bfd load-address.
293
294 */
295
296/* DEVICE
297
298 map-binary - map the binary into the users address space
299
300 DESCRIPTION
301
302 Similar to load-binary except that memory for each segment is
303 created before the corresponding data for the segment is loaded.
304
305 This device is normally used to load an executable into a user mode
306 simulation.
307
308 PROPERTIES
309
310 file-name = <string>
311
312 Name of the binary to be loaded.
313
314 */
315
316static void
317update_for_binary_section(bfd *abfd,
318 asection *the_section,
319 PTR obj)
320{
321 unsigned_word section_vma;
322 unsigned_word section_size;
323 access_type access;
324 device *me = (device*)obj;
325
326 /* skip the section if no memory to allocate */
fd361982 327 if (! (bfd_section_flags (the_section) & SEC_ALLOC))
c906108c
SS
328 return;
329
330 /* check/ignore any sections of size zero */
fd361982 331 section_size = bfd_section_size (the_section);
c906108c
SS
332 if (section_size == 0)
333 return;
334
335 /* find where it is to go */
fd361982 336 section_vma = bfd_section_vma (the_section);
c906108c
SS
337
338 DTRACE(binary,
339 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
fd361982 340 bfd_section_name (the_section),
c906108c
SS
341 (long)section_vma,
342 (long)section_size,
fd361982
AM
343 (long)bfd_section_flags (the_section),
344 bfd_section_flags (the_section) & SEC_LOAD ? " LOAD" : "",
345 bfd_section_flags (the_section) & SEC_CODE ? " CODE" : "",
346 bfd_section_flags (the_section) & SEC_DATA ? " DATA" : "",
347 bfd_section_flags (the_section) & SEC_ALLOC ? " ALLOC" : "",
348 bfd_section_flags (the_section) & SEC_READONLY ? " READONLY" : ""
c906108c
SS
349 ));
350
351 /* If there is an .interp section, it means it needs a shared library interpreter. */
fd361982 352 if (strcmp(".interp", bfd_section_name (the_section)) == 0)
c906108c
SS
353 error("Shared libraries are not yet supported.\n");
354
355 /* determine the devices access */
356 access = access_read;
fd361982 357 if (bfd_section_flags (the_section) & SEC_CODE)
c906108c 358 access |= access_exec;
fd361982 359 if (!(bfd_section_flags (the_section) & SEC_READONLY))
c906108c
SS
360 access |= access_write;
361
362 /* if claim specified, allocate region from the memory device */
363 if (device_find_property(me, "claim") != NULL) {
364 device_instance *memory = tree_find_ihandle_property(me, "/chosen/memory");
365 unsigned_cell mem_in[3];
366 unsigned_cell mem_out[1];
367 mem_in[0] = 0; /*alignment - top-of-stack*/
368 mem_in[1] = section_size;
369 mem_in[2] = section_vma;
370 if (device_instance_call_method(memory, "claim", 3, mem_in, 1, mem_out) < 0)
371 device_error(me, "failed to claim memory for section at 0x%lx (0x%lx",
372 section_vma,
373 section_size);
374 if (mem_out[0] != section_vma)
375 device_error(me, "section address not as requested");
376 }
377
378 /* if a map, pass up a request to create the memory in core */
379 if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
380 device_attach_address(device_parent(me),
381 attach_raw_memory,
382 0 /*address space*/,
383 section_vma,
384 section_size,
385 access,
386 me);
387
388 /* if a load dma in the required data */
fd361982 389 if (bfd_section_flags (the_section) & SEC_LOAD) {
c906108c
SS
390 void *section_init = zalloc(section_size);
391 if (!bfd_get_section_contents(abfd,
392 the_section,
393 section_init, 0,
394 section_size)) {
395 bfd_perror("binary");
396 device_error(me, "load of data failed");
397 return;
398 }
399 if (device_dma_write_buffer(device_parent(me),
400 section_init,
401 0 /*space*/,
402 section_vma,
403 section_size,
404 1 /*violate_read_only*/)
405 != section_size)
406 device_error(me, "broken transfer\n");
d79fe0d6 407 free(section_init); /* only free if load */
c906108c
SS
408 }
409}
410
411static void
412hw_binary_init_data_callback(device *me)
413{
414 /* get the file name */
415 const char *file_name = device_find_string_property(me, "file-name");
416 bfd *image;
417
418 /* open the file */
419 image = bfd_openr(file_name, NULL);
420 if (image == NULL) {
421 bfd_perror("binary");
422 device_error(me, "Failed to open file %s\n", file_name);
423 }
424
425 /* check it is valid */
426 if (!bfd_check_format(image, bfd_object)) {
427 bfd_close(image);
428 device_error(me, "The file %s has an invalid binary format\n", file_name);
429 }
430
431 /* and the data sections */
432 bfd_map_over_sections(image,
433 update_for_binary_section,
434 (PTR)me);
435
436 bfd_close(image);
437}
438
439
440static device_callbacks const hw_binary_callbacks = {
441 { NULL, hw_binary_init_data_callback, },
442 { NULL, }, /* address */
443 { NULL, }, /* IO */
444 { NULL, }, /* DMA */
445 { NULL, }, /* interrupt */
446 { NULL, }, /* unit */
447};
448
449
450/* DEVICE
451
452 stack - create an initial stack frame in memory
453
454 DESCRIPTION
455
456 Creates a stack frame of the specified type in memory.
457
458 Due to the startup sequence gdb uses when commencing a simulation,
459 it is not possible for the data to be placed on the stack to be
460 specified as part of the device tree. Instead the arguments to be
461 pushed onto the stack are specified using an IOCTL call.
462
463 The IOCTL takes the additional arguments:
464
465 | unsigned_word stack_end -- where the stack should come down from
466 | char **argv -- ...
467 | char **envp -- ...
468
469 PROPERTIES
470
471 stack-type = <string>
472
473 The form of the stack frame that is to be created.
474
475 */
476
477static int
478sizeof_argument_strings(char **arg)
479{
480 int sizeof_strings = 0;
481
482 /* robust */
483 if (arg == NULL)
484 return 0;
485
486 /* add up all the string sizes (padding as we go) */
487 for (; *arg != NULL; arg++) {
488 int len = strlen(*arg) + 1;
489 sizeof_strings += ALIGN_8(len);
490 }
491
492 return sizeof_strings;
493}
494
495static int
496number_of_arguments(char **arg)
497{
498 int nr;
499 if (arg == NULL)
500 return 0;
501 for (nr = 0; *arg != NULL; arg++, nr++);
502 return nr;
503}
504
505static int
506sizeof_arguments(char **arg)
507{
508 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
509}
510
511static void
512write_stack_arguments(device *me,
513 char **arg,
514 unsigned_word start_block,
515 unsigned_word end_block,
516 unsigned_word start_arg,
517 unsigned_word end_arg)
518{
519 DTRACE(stack,
520 ("write_stack_arguments(device=%s, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
521 device_name(me), (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
522 if (arg == NULL)
523 device_error(me, "Attempt to write a null array onto the stack\n");
524 /* only copy in arguments, memory is already zero */
525 for (; *arg != NULL; arg++) {
526 int len = strlen(*arg)+1;
527 unsigned_word target_start_block;
528 DTRACE(stack,
529 ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
530 "**arg", *arg, "start_block", (long)start_block,
531 "len", (long)len, "start_arg", (long)start_arg));
532 if (psim_write_memory(device_system(me), 0, *arg,
533 start_block, len,
534 0/*violate_readonly*/) != len)
535 device_error(me, "Write of **arg (%s) at 0x%lx of stack failed\n",
536 *arg, (unsigned long)start_block);
537 target_start_block = H2T_word(start_block);
538 if (psim_write_memory(device_system(me), 0, &target_start_block,
539 start_arg, sizeof(target_start_block),
540 0) != sizeof(target_start_block))
541 device_error(me, "Write of *arg onto stack failed\n");
542 start_block += ALIGN_8(len);
543 start_arg += sizeof(start_block);
544 }
545 start_arg += sizeof(start_block); /*the null at the end*/
546 if (start_block != end_block
547 || ALIGN_8(start_arg) != end_arg)
548 device_error(me, "Probable corrpution of stack arguments\n");
549 DTRACE(stack, ("write_stack_arguments() = void\n"));
550}
551
552static void
553create_ppc_elf_stack_frame(device *me,
554 unsigned_word bottom_of_stack,
555 char **argv,
556 char **envp)
557{
558 /* fixme - this is over aligned */
559
560 /* information block */
561 const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
562 const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
563 const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
564 const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
565
566 /* auxiliary vector - contains only one entry */
567 const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
568 const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
569
570 /* environment points (including null sentinal) */
571 const unsigned sizeof_envp = sizeof_arguments(envp);
572 const unsigned_word start_envp = start_aux - sizeof_envp;
573
574 /* argument pointers (including null sentinal) */
575 const int argc = number_of_arguments(argv);
576 const unsigned sizeof_argv = sizeof_arguments(argv);
577 const unsigned_word start_argv = start_envp - sizeof_argv;
578
579 /* link register save address - alligned to a 16byte boundary */
580 const unsigned_word top_of_stack = ((start_argv
581 - 2 * sizeof(unsigned_word))
582 & ~0xf);
583
584 /* install arguments on stack */
585 write_stack_arguments(me, envp,
586 start_envp_block, bottom_of_stack,
587 start_envp, start_aux);
588 write_stack_arguments(me, argv,
589 start_argv_block, start_envp_block,
590 start_argv, start_envp);
591
592 /* set up the registers */
601cecf0
AC
593 ASSERT (psim_write_register(device_system(me), -1,
594 &top_of_stack, "sp", cooked_transfer) > 0);
595 ASSERT (psim_write_register(device_system(me), -1,
596 &argc, "r3", cooked_transfer) > 0);
597 ASSERT (psim_write_register(device_system(me), -1,
598 &start_argv, "r4", cooked_transfer) > 0);
599 ASSERT (psim_write_register(device_system(me), -1,
600 &start_envp, "r5", cooked_transfer) > 0);
601 ASSERT (psim_write_register(device_system(me), -1,
602 &start_aux, "r6", cooked_transfer) > 0);
c906108c
SS
603}
604
605static void
606create_ppc_aix_stack_frame(device *me,
607 unsigned_word bottom_of_stack,
608 char **argv,
609 char **envp)
610{
611 unsigned_word core_envp;
612 unsigned_word core_argv;
613 unsigned_word core_argc;
614 unsigned_word core_aux;
615 unsigned_word top_of_stack;
616
617 /* cheat - create an elf stack frame */
618 create_ppc_elf_stack_frame(me, bottom_of_stack, argv, envp);
619
620 /* extract argument addresses from registers */
601cecf0
AC
621 ASSERT (psim_read_register(device_system(me), 0,
622 &top_of_stack, "r1", cooked_transfer) > 0);
623 ASSERT (psim_read_register(device_system(me), 0,
624 &core_argc, "r3", cooked_transfer) > 0);
625 ASSERT (psim_read_register(device_system(me), 0,
626 &core_argv, "r4", cooked_transfer) > 0);
627 ASSERT (psim_read_register(device_system(me), 0,
628 &core_envp, "r5", cooked_transfer) > 0);
629 ASSERT (psim_read_register(device_system(me), 0,
630 &core_aux, "r6", cooked_transfer) > 0);
c906108c
SS
631
632 /* extract arguments from registers */
633 device_error(me, "Unfinished procedure create_ppc_aix_stack_frame\n");
634}
635
636
637static void
638create_ppc_chirp_bootargs(device *me,
639 char **argv)
640{
641 /* concat the arguments */
642 char args[1024];
643 char **chp = argv + 1;
644 args[0] = '\0';
645 while (*chp != NULL) {
646 if (strlen(args) > 0)
647 strcat(args, " ");
648 if (strlen(args) + strlen(*chp) >= sizeof(args))
649 device_error(me, "buffer overflow");
650 strcat(args, *chp);
651 chp++;
652 }
653
654 /* set the arguments property */
655 tree_parse(me, "/chosen/bootargs \"%s", args);
656}
657
658
659static int
660hw_stack_ioctl(device *me,
661 cpu *processor,
662 unsigned_word cia,
663 device_ioctl_request request,
664 va_list ap)
665{
666 switch (request) {
667 case device_ioctl_create_stack:
668 {
669 unsigned_word stack_pointer = va_arg(ap, unsigned_word);
670 char **argv = va_arg(ap, char **);
671 char **envp = va_arg(ap, char **);
672 const char *stack_type;
673 DTRACE(stack,
674 ("stack_ioctl_callback(me=0x%lx:%s processor=0x%lx cia=0x%lx argv=0x%lx envp=0x%lx)\n",
675 (long)me, device_name(me),
676 (long)processor,
677 (long)cia,
678 (long)argv,
679 (long)envp));
680 stack_type = device_find_string_property(me, "stack-type");
681 if (strcmp(stack_type, "ppc-elf") == 0)
682 create_ppc_elf_stack_frame(me, stack_pointer, argv, envp);
683 else if (strcmp(stack_type, "ppc-xcoff") == 0)
684 create_ppc_aix_stack_frame(me, stack_pointer, argv, envp);
685 else if (strcmp(stack_type, "chirp") == 0)
686 create_ppc_chirp_bootargs(me, argv);
687 else if (strcmp(stack_type, "none") != 0)
688 device_error(me, "Unknown initial stack frame type %s", stack_type);
689 DTRACE(stack,
690 ("stack_ioctl_callback() = void\n"));
691 break;
692 }
693 default:
694 device_error(me, "Unsupported ioctl requested");
695 break;
696 }
697 return 0;
698}
699
700static device_callbacks const hw_stack_callbacks = {
701 { NULL, },
702 { NULL, }, /* address */
703 { NULL, }, /* IO */
704 { NULL, }, /* DMA */
705 { NULL, }, /* interrupt */
706 { NULL, }, /* unit */
707 NULL, /* instance */
708 hw_stack_ioctl,
709};
710
711const device_descriptor hw_init_device_descriptor[] = {
712 { "file", NULL, &hw_file_callbacks },
713 { "data", NULL, &hw_data_callbacks },
714 { "load-binary", NULL, &hw_binary_callbacks },
715 { "map-binary", NULL, &hw_binary_callbacks },
716 { "stack", NULL, &hw_stack_callbacks },
717 { NULL },
718};
719
50427dbf 720#endif /* _HW_INIT_C_ */
This page took 0.971387 seconds and 4 git commands to generate.