aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/device_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/ppc/device_table.c')
-rw-r--r--sim/ppc/device_table.c1398
1 files changed, 0 insertions, 1398 deletions
diff --git a/sim/ppc/device_table.c b/sim/ppc/device_table.c
deleted file mode 100644
index f6b433c..0000000
--- a/sim/ppc/device_table.c
+++ /dev/null
@@ -1,1398 +0,0 @@
-/* This file is part of the program psim.
-
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
-
-
-#ifndef _DEVICE_TABLE_C_
-#define _DEVICE_TABLE_C_
-
-#ifndef STATIC_INLINE_DEVICE_TABLE
-#define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
-#endif
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-#include "device_table.h"
-
-#include "events.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include "cpu.h"
-
-#include "bfd.h"
-
-/* Helper functions */
-
-/* Generic device init: Attaches the device of size <nr_bytes> (taken
- from <name>@<int>,<nr_bytes>) to its parent at address zero and
- with read/write access. */
-
-typedef struct _generic_reg_spec {
- unsigned32 base;
- unsigned32 size;
-} generic_reg_spec;
-
-
-void
-generic_device_init_address(device *me)
-{
- const device_property *reg = device_find_array_property(me, "reg");
- const generic_reg_spec *spec = reg->array;
- int nr_entries = reg->sizeof_array / sizeof(generic_reg_spec);
-
- if ((reg->sizeof_array % sizeof(generic_reg_spec)) != 0)
- error("devices/%s reg property is of wrong size\n", device_name(me));
-
- while (nr_entries > 0) {
- device_attach_address(device_parent(me),
- device_name(me),
- attach_callback,
- 0 /*space*/,
- BE2H_4(spec->base),
- BE2H_4(spec->size),
- access_read_write_exec,
- me);
- spec++;
- nr_entries--;
- }
-}
-
-int
-generic_device_unit_decode(device *me,
- const char *unit,
- device_unit *phys)
-{
- memset(phys, 0, sizeof(device_unit));
- if (unit == NULL)
- return 0;
- else {
- char *pos = (char*)unit; /* force for strtoul() */
- while (1) {
- char *old_pos = pos;
- long int val = strtoul(pos, &pos, 0);
- if (old_pos == pos && *pos == '\0')
- return phys->nr_cells;
- if (old_pos == pos && *pos != '\0')
- return -1;
- if (phys->nr_cells == 4)
- return -1;
- phys->cells[phys->nr_cells] = val;
- phys->nr_cells++;
- }
- }
-}
-
-int
-generic_device_unit_encode(device *me,
- const device_unit *phys,
- char *buf,
- int sizeof_buf)
-{
- int i;
- int len;
- char *pos = buf; /* force for strtoul() */
- for (i = 0; i < phys->nr_cells; i++) {
- if (pos != buf) {
- strcat(pos, ",");
- pos = strchr(pos, '\0');
- }
- sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
- pos = strchr(pos, '\0');
- }
- len = pos - buf;
- if (len >= sizeof_buf)
- error("generic_unit_encode - buffer overflow\n");
- return len;
-}
-
-/* DMA a file into memory */
-STATIC_INLINE_DEVICE_TABLE int
-dma_file(device *me,
- const char *file_name,
- unsigned_word addr)
-{
- int count;
- int inc;
- FILE *image;
- char buf[1024];
-
- /* get it open */
- image = fopen(file_name, "r");
- if (image == NULL)
- return -1;
-
- /* read it in slowly */
- count = 0;
- while (1) {
- inc = fread(buf, 1, sizeof(buf), image);
- if (feof(image) || ferror(image))
- break;
- if (device_dma_write_buffer(device_parent(me),
- buf,
- 0 /*address-space*/,
- addr+count,
- inc /*nr-bytes*/,
- 1 /*violate ro*/) != inc) {
- fclose(image);
- return -1;
- }
- count += inc;
- }
-
- /* close down again */
- fclose(image);
-
- return count;
-}
-
-
-
-/* ignore/passthrough versions of each function */
-
-void
-passthrough_device_address_attach(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- device_attach_address(device_parent(me), name, attach,
- space, addr, nr_bytes,
- access,
- who);
-}
-
-void
-passthrough_device_address_detach(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- device_detach_address(device_parent(me), name, attach,
- space, addr, nr_bytes, access,
- who);
-}
-
-unsigned
-passthrough_device_dma_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- return device_dma_read_buffer(device_parent(me), dest,
- space, addr, nr_bytes);
-}
-
-unsigned
-passthrough_device_dma_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
-{
- return device_dma_write_buffer(device_parent(me), source,
- space, addr,
- nr_bytes,
- violate_read_only_section);
-}
-
-int
-ignore_device_unit_decode(device *me,
- const char *unit,
- device_unit *phys)
-{
- memset(phys, 0, sizeof(device_unit));
- return 0;
-}
-
-
-static const device_callbacks passthrough_callbacks = {
- { NULL, }, /* init */
- { passthrough_device_address_attach,
- passthrough_device_address_detach, },
- { NULL, }, /* IO */
- { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
- { NULL, }, /* interrupt */
- { generic_device_unit_decode,
- generic_device_unit_encode, },
-};
-
-
-
-/* Register init device: register@<nothing>
-
- Properties attached to the register device specify the name/value
- initialization pair for cpu registers.
-
- A specific processor can be initialized by creating a property with
- a name like `0.pc'.
-
- Properties are normally processed old-to-new and this function
- needs to allow older (first in) properties to override new (last
- in) ones. The suport function do_register_init() manages this. */
-
-static void
-do_register_init(device *me,
- const device_property *prop)
-{
- psim *system = device_system(me);
- if (prop != NULL) {
- const char *name = prop->name;
- unsigned32 value = device_find_integer_property(me, name);
- int processor;
-
- do_register_init(me, device_next_property(prop));
-
- if (strchr(name, '.') == NULL) {
- processor = -1;
- DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
- }
- else {
- char *end;
- processor = strtoul(name, &end, 0);
- ASSERT(end[0] == '.');
- name = end+1;
- DTRACE(register, ("%d.%s=0x%lx\n", processor, name,
- (unsigned long)value));
- }
- psim_write_register(system, processor, /* all processors */
- &value,
- name,
- cooked_transfer);
- }
-}
-
-
-static void
-register_init_data_callback(device *me)
-{
- const device_property *prop = device_find_property(me, NULL);
- do_register_init(me, prop);
-}
-
-
-static device_callbacks const register_callbacks = {
- { NULL, register_init_data_callback, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
-};
-
-
-
-/* Trace device:
-
- Properties attached to the trace device are names and values for
- the various trace variables. When initialized trace goes through
- the propertie and sets the global trace variables so that they
- match what was specified in the device tree. */
-
-static void
-trace_init_data_callback(device *me)
-{
- const device_property *prop = device_find_property(me, NULL);
- while (prop != NULL) {
- const char *name = prop->name;
- unsigned32 value = device_find_integer_property(me, name);
- trace_option(name, value);
- prop = device_next_property(prop);
- }
-}
-
-
-static device_callbacks const trace_callbacks = {
- { NULL, trace_init_data_callback, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
-};
-
-
-
-/* VEA VM:
-
- vm@<stack-base>
- stack-base =
- nr-bytes =
-
- A VEA mode device. This sets its self up as the default memory
- device capturing all accesses (reads/writes) to currently unmapped
- addresses. If the unmaped access falls within unallocated stack or
- heap address ranges then memory is allocated and the access is
- allowed to continue.
-
- During init phase, this device expects to receive `attach' requests
- from its children for the text/data/bss memory areas. Typically,
- this would be done by the binary device.
-
- STACK: The location of the stack in memory is specified as part of
- the devices name. Unmaped accesses that fall within the stack
- space result in the allocated stack being grown downwards so that
- it includes the page of the culprit access.
-
- HEAP: During initialization, the vm device monitors all `attach'
- operations from its children using this to determine the initial
- location of the heap. The heap is then extended by system calls
- that frob the heap upper bound variable (see system.c). */
-
-
-typedef struct _vm_device {
- /* area of memory valid for stack addresses */
- unsigned_word stack_base; /* min possible stack value */
- unsigned_word stack_bound;
- unsigned_word stack_lower_limit;
- /* area of memory valid for heap addresses */
- unsigned_word heap_base;
- unsigned_word heap_bound;
- unsigned_word heap_upper_limit;
-} vm_device;
-
-
-static void
-vm_init_address_callback(device *me)
-{
- vm_device *vm = (vm_device*)device_data(me);
-
- /* revert the stack/heap variables to their defaults */
- vm->stack_base = device_find_integer_property(me, "stack-base");
- vm->stack_bound = (vm->stack_base
- + device_find_integer_property(me, "nr-bytes"));
- vm->stack_lower_limit = vm->stack_bound;
- vm->heap_base = 0;
- vm->heap_bound = 0;
- vm->heap_upper_limit = 0;
-
- /* establish this device as the default memory handler */
- device_attach_address(device_parent(me),
- device_name(me),
- attach_callback + 1,
- 0 /*address space - ignore*/,
- 0 /*addr - ignore*/,
- (((unsigned)0)-1) /*nr_bytes - ignore*/,
- access_read_write /*access*/,
- me);
-}
-
-
-static void
-vm_attach_address(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- vm_device *vm = (vm_device*)device_data(me);
- /* update end of bss if necessary */
- if (vm->heap_base < addr + nr_bytes) {
- vm->heap_base = addr + nr_bytes;
- vm->heap_bound = addr + nr_bytes;
- vm->heap_upper_limit = addr + nr_bytes;
- }
- device_attach_address(device_parent(me),
- "vm@0x0,0", /* stop remap */
- attach_raw_memory,
- 0 /*address space*/,
- addr,
- nr_bytes,
- access,
- me);
-}
-
-
-STATIC_INLINE_DEVICE_TABLE unsigned
-add_vm_space(device *me,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- vm_device *vm = (vm_device*)device_data(me);
- unsigned_word block_addr;
- unsigned block_nr_bytes;
-
- /* an address in the stack area, allocate just down to the addressed
- page */
- if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
- block_addr = FLOOR_PAGE(addr);
- block_nr_bytes = vm->stack_lower_limit - block_addr;
- vm->stack_lower_limit = block_addr;
- }
- /* an address in the heap area, allocate all of the required heap */
- else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
- block_addr = vm->heap_upper_limit;
- block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
- vm->heap_upper_limit = vm->heap_bound;
- }
- /* oops - an invalid address - abort the cpu */
- else if (processor != NULL) {
- cpu_halt(processor, cia, was_signalled, SIGSEGV);
- return 0;
- }
- /* 2*oops - an invalid address and no processor */
- else {
- return 0;
- }
-
- /* got the parameters, allocate the space */
- device_attach_address(device_parent(me),
- "vm@0x0,0", /* stop remap */
- attach_raw_memory,
- 0 /*address space*/,
- block_addr,
- block_nr_bytes,
- access_read_write,
- me);
- return block_nr_bytes;
-}
-
-
-static unsigned
-vm_io_read_buffer_callback(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
- memset(dest, 0, nr_bytes); /* always initialized to zero */
- return nr_bytes;
- }
- else
- return 0;
-}
-
-
-static unsigned
-vm_io_write_buffer_callback(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
- return device_dma_write_buffer(device_parent(me), source,
- space, addr,
- nr_bytes,
- 0/*violate_read_only*/);
- }
- else
- return 0;
-}
-
-
-static int
-vm_ioctl_callback(device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- va_list ap)
-{
- /* While the caller is notified that the heap has grown by the
- requested amount, the heap is actually extended out to a page
- boundary. */
- vm_device *vm = (vm_device*)device_data(me);
- unsigned_word requested_break = va_arg(ap, unsigned_word);
- unsigned_word new_break = ALIGN_8(requested_break);
- unsigned_word old_break = vm->heap_bound;
- signed_word delta = new_break - old_break;
- if (delta > 0)
- vm->heap_bound = ALIGN_PAGE(new_break);
- return 0;
-}
-
-
-static device_callbacks const vm_callbacks = {
- { vm_init_address_callback, },
- { vm_attach_address,
- passthrough_device_address_detach, },
- { vm_io_read_buffer_callback,
- vm_io_write_buffer_callback, },
- { NULL, passthrough_device_dma_write_buffer, },
- { NULL, }, /* interrupt */
- { generic_device_unit_decode,
- generic_device_unit_encode, },
- { NULL, }, /* instance */
- vm_ioctl_callback,
-};
-
-
-static void *
-vea_vm_create(const char *name,
- const device_unit *address,
- const char *args,
- device *parent)
-{
- vm_device *vm = ZALLOC(vm_device);
- return vm;
-}
-
-
-
-/* FILE device: file@0x<address>,<file-name>
- (later - file@0x<address>,<size>,<file-offset>,<file-name>)
-
- Specifies a file to read directly into memory starting at <address> */
-
-
-static void
-file_init_data_callback(device *me)
-{
- int count;
- const char *file_name = device_find_string_property(me, "file-name");
- unsigned_word addr = device_find_integer_property(me, "real-address");
- /* load the file */
- count = dma_file(me, file_name, addr);
- if (count < 0)
- error("device_table/%s - Problem loading file %s\n",
- device_name(me), file_name);
-}
-
-
-static device_callbacks const file_callbacks = {
- { NULL, file_init_data_callback, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
-};
-
-
-
-/* DATA device: data@<address>
-
- <data> - property containing the value to store
- <real-address> - address to store data at
-
- Store <data> at <address> using approperiate byte order */
-
-static void
-data_init_data_callback(device *me)
-{
- unsigned_word addr = device_find_integer_property(me, "real-address");
- const device_property *data = device_find_property(me, "data");
- if (data == NULL)
- error("devices/data - missing data property\n");
- switch (data->type) {
- case integer_property:
- {
- unsigned32 buf = device_find_integer_property(me, "data");
- H2T(buf);
- if (device_dma_write_buffer(device_parent(me),
- &buf,
- 0 /*address-space*/,
- addr,
- sizeof(buf), /*nr-bytes*/
- 1 /*violate ro*/) != sizeof(buf))
- error("devices/%s - Problem storing integer 0x%x at 0x%lx\n",
- device_name(me), (long)buf, (unsigned long)addr);
- }
- break;
- default:
- error("devices/%s - write of this data is not yet implemented\n", device_name(me));
- break;
- }
-}
-
-
-static device_callbacks const data_callbacks = {
- { NULL, data_init_data_callback, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
-};
-
-
-
-/* HTAB:
-
- htab@<real-address>
- real-address =
- nr-bytes =
-
- pte@<real-address>
- real-address =
- virtual-address =
- nr-bytes =
- wimg =
- pp =
-
- pte@<real-address>
- real-address =
- file-name =
- wimg =
- pp =
-
- HTAB defines the location (in physical memory) of a HASH table.
- PTE (as a child of HTAB) defines a mapping that is to be entered
- into that table.
-
- NB: All the work in this device is done during init by the PTE.
- The pte, looks up its parent to determine the address of the HTAB
- and then uses DMA calls to establish the required mapping. */
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_decode_hash_table(device *parent,
- unsigned32 *htaborg,
- unsigned32 *htabmask)
-{
- unsigned_word htab_ra;
- unsigned htab_nr_bytes;
- unsigned n;
- /* determine the location/size of the hash table */
- if (parent == NULL
- || strcmp(device_name(parent), "htab") != 0)
- error("devices/htab - missing htab parent device\n");
- htab_ra = device_find_integer_property(parent, "real-address");
- htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
- for (n = htab_nr_bytes; n > 1; n = n / 2) {
- if (n % 2 != 0)
- error("devices/%s - htab size 0x%x not a power of two\n",
- device_name(parent), htab_nr_bytes);
- }
- *htaborg = htab_ra;
- *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
- if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
- error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
- device_name(parent), *htaborg, *htabmask);
- }
- DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
- (unsigned long)*htaborg, (unsigned long)*htabmask));
-}
-
-STATIC_INLINE void
-htab_map_page(device *me,
- unsigned_word ra,
- unsigned64 va,
- unsigned wimg,
- unsigned pp,
- unsigned32 htaborg,
- unsigned32 htabmask)
-{
- unsigned64 vpn = va << 12;
- unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
- unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
- unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
- ^ EXTRACTED32(page, 0, 15),
- 7, 31-6);
- int h;
- for (h = 0; h < 2; h++) {
- unsigned32 pteg = (htaborg | (hash & htabmask));
- int pti;
- for (pti = 0; pti < 8; pti++, pteg += 8) {
- unsigned32 current_target_pte0;
- unsigned32 current_pte0;
- if (device_dma_read_buffer(device_parent(me),
- &current_target_pte0,
- 0, /*space*/
- pteg,
- sizeof(current_target_pte0)) != 4)
- error("htab_init_callback() failed to read a pte at 0x%x\n",
- pteg);
- current_pte0 = T2H_4(current_target_pte0);
- if (!MASKED32(current_pte0, 0, 0)) {
- /* empty pte fill it */
- unsigned32 pte0 = (MASK32(0, 0)
- | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
- | INSERTED32(h, 25, 25)
- | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
- unsigned32 target_pte0 = H2T_4(pte0);
- unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
- | INSERTED32(wimg, 25, 28)
- | INSERTED32(pp, 30, 31));
- unsigned32 target_pte1 = H2T_4(pte1);
- if (device_dma_write_buffer(device_parent(me),
- &target_pte0,
- 0, /*space*/
- pteg,
- sizeof(target_pte0),
- 1/*ro?*/) != 4
- || device_dma_write_buffer(device_parent(me),
- &target_pte1,
- 0, /*space*/
- pteg + 4,
- sizeof(target_pte1),
- 1/*ro?*/) != 4)
- error("htab_init_callback() failed to write a pte a 0x%x\n",
- pteg);
- DTRACE(htab, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
- (unsigned long)va, (unsigned long)ra,
- (unsigned long)pteg,
- (unsigned long)pte0, (unsigned long)pte1));
- return;
- }
- }
- /* re-hash */
- hash = MASKED32(~hash, 0, 18);
- }
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_map_region(device *me,
- unsigned_word pte_ra,
- unsigned_word pte_va,
- unsigned nr_bytes,
- unsigned wimg,
- unsigned pp,
- unsigned32 htaborg,
- unsigned32 htabmask)
-{
- unsigned_word ra;
- unsigned64 va;
- /* go through all pages and create a pte for each */
- for (ra = pte_ra, va = (signed_word)pte_va;
- ra < pte_ra + nr_bytes;
- ra += 0x1000, va += 0x1000) {
- htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
- }
-}
-
-typedef struct _htab_binary_sizes {
- unsigned_word text_ra;
- unsigned_word text_base;
- unsigned_word text_bound;
- unsigned_word data_ra;
- unsigned_word data_base;
- unsigned data_bound;
- device *me;
-} htab_binary_sizes;
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_sum_binary(bfd *abfd,
- sec_ptr sec,
- PTR data)
-{
- htab_binary_sizes *sizes = (htab_binary_sizes*)data;
- unsigned_word size = bfd_get_section_size_before_reloc (sec);
- unsigned_word vma = bfd_get_section_vma (abfd, sec);
-
- /* skip the section if no memory to allocate */
- if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
- return;
-
- if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
- || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
- if (sizes->text_bound < vma + size)
- sizes->text_bound = ALIGN_PAGE(vma + size);
- if (sizes->text_base > vma)
- sizes->text_base = FLOOR_PAGE(vma);
- }
- else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
- || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
- if (sizes->data_bound < vma + size)
- sizes->data_bound = ALIGN_PAGE(vma + size);
- if (sizes->data_base > vma)
- sizes->data_base = FLOOR_PAGE(vma);
- }
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_dma_binary(bfd *abfd,
- sec_ptr sec,
- PTR data)
-{
- htab_binary_sizes *sizes = (htab_binary_sizes*)data;
- void *section_init;
- unsigned_word section_vma;
- unsigned_word section_size;
- unsigned_word section_ra;
- device *me = sizes->me;
-
- /* skip the section if no memory to allocate */
- if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
- return;
-
- /* check/ignore any sections of size zero */
- section_size = bfd_get_section_size_before_reloc(sec);
- if (section_size == 0)
- return;
-
- /* if nothing to load, ignore this one */
- if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
- return;
-
- /* find where it is to go */
- section_vma = bfd_get_section_vma(abfd, sec);
- section_ra = 0;
- if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
- || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
- section_ra = (section_vma - sizes->text_base + sizes->text_ra);
- else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
- section_ra = (section_vma - sizes->data_base + sizes->data_ra);
- else
- return; /* just ignore it */
-
- DTRACE(htab,
- ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
- bfd_get_section_name(abfd, sec),
- (long)section_vma,
- (long)section_size,
- (long)section_ra,
- (long)bfd_get_section_flags(abfd, sec),
- bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
- bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
- bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
- bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
- bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
- ));
-
- /* dma in the sections data */
- section_init = zalloc(section_size);
- if (!bfd_get_section_contents(abfd,
- sec,
- section_init, 0,
- section_size)) {
- bfd_perror("devices/pte");
- error("devices/%s - no data loaded\n", device_name(me));
- }
- if (device_dma_write_buffer(device_parent(me),
- section_init,
- 0 /*space*/,
- section_ra,
- section_size,
- 1 /*violate_read_only*/)
- != section_size)
- error("devices/%s - broken dma transfer\n", device_name(me));
- zfree(section_init); /* only free if load */
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_map_binary(device *me,
- unsigned_word ra,
- unsigned wimg,
- unsigned pp,
- const char *file_name,
- unsigned32 htaborg,
- unsigned32 htabmask)
-{
- htab_binary_sizes sizes;
- bfd *image;
- sizes.text_base = -1;
- sizes.data_base = -1;
- sizes.text_bound = 0;
- sizes.data_bound = 0;
- sizes.me = me;
-
- /* open the file */
- image = bfd_openr(file_name, NULL);
- if (image == NULL) {
- bfd_perror("devices/pte");
- error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
- }
-
- /* check it is valid */
- if (!bfd_check_format(image, bfd_object)) {
- bfd_close(image);
- error("devices/%s - the file %s has an invalid binary format\n",
- device_name(me), file_name);
- }
-
- /* determine the size of each of the files regions */
- bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
-
- /* determine the real addresses of the sections */
- sizes.text_ra = ra;
- sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
- (sizes.text_bound - sizes.text_base));
-
- DTRACE(htab, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
- (unsigned long)sizes.text_base,
- (unsigned long)sizes.text_bound,
- (unsigned long)sizes.text_ra));
- DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
- (unsigned long)sizes.data_base,
- (unsigned long)sizes.data_bound,
- (unsigned long)sizes.data_ra));
-
- /* set up virtual memory maps for each of the regions */
- htab_map_region(me, sizes.text_ra, sizes.text_base,
- sizes.text_bound - sizes.text_base,
- wimg, pp,
- htaborg, htabmask);
- htab_map_region(me, sizes.data_ra, sizes.data_base,
- sizes.data_bound - sizes.data_base,
- wimg, pp,
- htaborg, htabmask);
-
- /* dma the sections into physical memory */
- bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
-}
-
-static void
-htab_init_data_callback(device *me)
-{
- if (WITH_TARGET_WORD_BITSIZE != 32)
- error("devices/htab: only 32bit targets currently suported\n");
-
- /* only the pte does work */
- if (strcmp(device_name(me), "pte") == 0) {
- unsigned32 htaborg;
- unsigned32 htabmask;
-
- htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
-
- if (device_find_property(me, "file-name") != NULL) {
- /* map in a binary */
- unsigned32 pte_ra = device_find_integer_property(me, "real-address");
- unsigned pte_wimg = device_find_integer_property(me, "wimg");
- unsigned pte_pp = device_find_integer_property(me, "pp");
- const char *file_name = device_find_string_property(me, "file-name");
- DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
- (unsigned long)pte_ra,
- (unsigned long)pte_wimg,
- (long)pte_pp,
- file_name));
- htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
- htaborg, htabmask);
- }
- else {
- /* handle a normal mapping definition */
- /* so that 0xff...0 is make 0xffffff00 */
- signed32 pte_va = device_find_integer_property(me, "virtual-address");
- unsigned32 pte_ra = device_find_integer_property(me, "real-address");
- unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
- unsigned pte_wimg = device_find_integer_property(me, "wimg");
- unsigned pte_pp = device_find_integer_property(me, "pp");
- DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
- (unsigned long)pte_ra,
- (long)pte_wimg,
- (long)pte_pp,
- (unsigned long)pte_va,
- (long)pte_nr_bytes));
- htab_map_region(me, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
- htaborg, htabmask);
- }
- }
-}
-
-
-static device_callbacks const htab_callbacks = {
- { NULL, htab_init_data_callback, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { passthrough_device_dma_read_buffer,
- passthrough_device_dma_write_buffer, },
- { NULL, }, /* interrupt */
- { generic_device_unit_decode,
- generic_device_unit_encode, },
-};
-
-
-
-/* Load device: binary
-
- Single property the name of which specifies the file (understood by
- BFD) that is to be DMAed into memory as part of init */
-
-STATIC_INLINE_DEVICE_TABLE void
-update_for_binary_section(bfd *abfd,
- asection *the_section,
- PTR obj)
-{
- unsigned_word section_vma;
- unsigned_word section_size;
- access_type access;
- device *me = (device*)obj;
-
- /* skip the section if no memory to allocate */
- if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
- return;
-
- /* check/ignore any sections of size zero */
- section_size = bfd_get_section_size_before_reloc(the_section);
- if (section_size == 0)
- return;
-
- /* find where it is to go */
- section_vma = bfd_get_section_vma(abfd, the_section);
-
- DTRACE(binary,
- ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
- bfd_get_section_name(abfd, the_section),
- (long)section_vma,
- (long)section_size,
- (long)bfd_get_section_flags(abfd, the_section),
- bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
- ));
-
- /* If there is an .interp section, it means it needs a shared library interpreter. */
- if (strcmp(".interp", bfd_get_section_name(abfd, the_section)) == 0)
- error("Shared libraries are not yet supported.\n");
-
- /* determine the devices access */
- access = access_read;
- if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
- access |= access_exec;
- if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
- access |= access_write;
-
- /* if a map, pass up a request to create the memory in core */
- if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
- device_attach_address(device_parent(me),
- device_name(me),
- attach_raw_memory,
- 0 /*address space*/,
- section_vma,
- section_size,
- access,
- me);
-
- /* if a load dma in the required data */
- if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
- void *section_init = zalloc(section_size);
- if (!bfd_get_section_contents(abfd,
- the_section,
- section_init, 0,
- section_size)) {
- bfd_perror("core:load_section()");
- error("load of data failed");
- return;
- }
- if (device_dma_write_buffer(device_parent(me),
- section_init,
- 0 /*space*/,
- section_vma,
- section_size,
- 1 /*violate_read_only*/)
- != section_size)
- error("data_init_callback() broken transfer for %s\n", device_name(me));
- zfree(section_init); /* only free if load */
- }
-}
-
-
-static void
-binary_init_data_callback(device *me)
-{
- /* get the file name */
- const char *file_name = device_find_string_property(me, "file-name");
- bfd *image;
-
- /* open the file */
- image = bfd_openr(file_name, NULL);
- if (image == NULL) {
- bfd_perror("devices/binary");
- error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
- }
-
- /* check it is valid */
- if (!bfd_check_format(image, bfd_object)) {
- bfd_close(image);
- error("devices/%s - the file %s has an invalid binary format\n",
- device_name(me), file_name);
- }
-
- /* and the data sections */
- bfd_map_over_sections(image,
- update_for_binary_section,
- (PTR)me);
-
- bfd_close(image);
-}
-
-
-static device_callbacks const binary_callbacks = {
- { NULL, binary_init_data_callback, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
-};
-
-
-
-/* Stack device: stack@<type>
-
- Has a single IOCTL to create a stack frame of the specified type.
- If <type> is elf or xcoff then a corresponding stack is created.
- Any other value of type is ignored.
-
- The IOCTL takes the additional arguments:
-
- unsigned_word stack_end -- where the stack should come down from
- char **argv -- ...
- char **envp -- ...
-
- */
-
-STATIC_INLINE_DEVICE_TABLE int
-sizeof_argument_strings(char **arg)
-{
- int sizeof_strings = 0;
-
- /* robust */
- if (arg == NULL)
- return 0;
-
- /* add up all the string sizes (padding as we go) */
- for (; *arg != NULL; arg++) {
- int len = strlen(*arg) + 1;
- sizeof_strings += ALIGN_8(len);
- }
-
- return sizeof_strings;
-}
-
-STATIC_INLINE_DEVICE_TABLE int
-number_of_arguments(char **arg)
-{
- int nr;
- if (arg == NULL)
- return 0;
- for (nr = 0; *arg != NULL; arg++, nr++);
- return nr;
-}
-
-STATIC_INLINE_DEVICE_TABLE int
-sizeof_arguments(char **arg)
-{
- return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-write_stack_arguments(psim *system,
- char **arg,
- unsigned_word start_block,
- unsigned_word end_block,
- unsigned_word start_arg,
- unsigned_word end_arg)
-{
- DTRACE(stack,
- ("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",
- (long)system, (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
- if (arg == NULL)
- error("write_arguments: character array NULL\n");
- /* only copy in arguments, memory is already zero */
- for (; *arg != NULL; arg++) {
- int len = strlen(*arg)+1;
- unsigned_word target_start_block;
- DTRACE(stack,
- ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
- "**arg", *arg, "start_block", (long)start_block,
- "len", (long)len, "start_arg", (long)start_arg));
- if (psim_write_memory(system, 0, *arg,
- start_block, len,
- 0/*violate_readonly*/) != len)
- error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
- *arg, start_block);
- target_start_block = H2T_word(start_block);
- if (psim_write_memory(system, 0, &target_start_block,
- start_arg, sizeof(target_start_block),
- 0) != sizeof(target_start_block))
- error("write_stack_arguments() - write of *arg failed\n");
- start_block += ALIGN_8(len);
- start_arg += sizeof(start_block);
- }
- start_arg += sizeof(start_block); /*the null at the end*/
- if (start_block != end_block
- || ALIGN_8(start_arg) != end_arg)
- error("write_stack_arguments - possible corruption\n");
- DTRACE(stack,
- ("write_stack_arguments() = void\n"));
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-create_elf_stack_frame(psim *system,
- unsigned_word bottom_of_stack,
- char **argv,
- char **envp)
-{
- /* fixme - this is over aligned */
-
- /* information block */
- const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
- const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
- const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
- const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
-
- /* auxiliary vector - contains only one entry */
- const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
- const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
-
- /* environment points (including null sentinal) */
- const unsigned sizeof_envp = sizeof_arguments(envp);
- const unsigned_word start_envp = start_aux - sizeof_envp;
-
- /* argument pointers (including null sentinal) */
- const int argc = number_of_arguments(argv);
- const unsigned sizeof_argv = sizeof_arguments(argv);
- const unsigned_word start_argv = start_envp - sizeof_argv;
-
- /* link register save address - alligned to a 16byte boundary */
- const unsigned_word top_of_stack = ((start_argv
- - 2 * sizeof(unsigned_word))
- & ~0xf);
-
- /* install arguments on stack */
- write_stack_arguments(system, envp,
- start_envp_block, bottom_of_stack,
- start_envp, start_aux);
- write_stack_arguments(system, argv,
- start_argv_block, start_envp_block,
- start_argv, start_envp);
-
- /* set up the registers */
- psim_write_register(system, -1,
- &top_of_stack, "sp", cooked_transfer);
- psim_write_register(system, -1,
- &argc, "r3", cooked_transfer);
- psim_write_register(system, -1,
- &start_argv, "r4", cooked_transfer);
- psim_write_register(system, -1,
- &start_envp, "r5", cooked_transfer);
- psim_write_register(system, -1,
- &start_aux, "r6", cooked_transfer);
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-create_aix_stack_frame(psim *system,
- unsigned_word bottom_of_stack,
- char **argv,
- char **envp)
-{
- unsigned_word core_envp;
- unsigned_word core_argv;
- unsigned_word core_argc;
- unsigned_word core_aux;
- unsigned_word top_of_stack;
-
- /* cheat - create an elf stack frame */
- create_elf_stack_frame(system, bottom_of_stack, argv, envp);
-
- /* extract argument addresses from registers */
- psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
- psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
- psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
- psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
- psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
-
- /* extract arguments from registers */
- error("create_aix_stack_frame() - what happens next?\n");
-}
-
-
-
-static int
-stack_ioctl_callback(device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- va_list ap)
-{
- unsigned_word stack_pointer;
- const char *stack_type;
- char **argv;
- char **envp;
- stack_pointer = va_arg(ap, unsigned_word);
- argv = va_arg(ap, char **);
- envp = va_arg(ap, char **);
- DTRACE(stack,
- ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
- (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
- stack_type = device_find_string_property(me, "stack-type");
- if (strcmp(stack_type, "elf") == 0)
- create_elf_stack_frame(system, stack_pointer, argv, envp);
- else if (strcmp(stack_type, "xcoff") == 0)
- create_aix_stack_frame(system, stack_pointer, argv, envp);
- DTRACE(stack,
- ("stack_ioctl_callback() = void\n"));
- return 0;
-}
-
-static device_callbacks const stack_callbacks = {
- { NULL, },
- { NULL, }, /* address */
- { NULL, }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
- { NULL, }, /* instance */
- stack_ioctl_callback,
-};
-
-
-
-static const device_descriptor old_device_table[] = {
- { "vm", vea_vm_create, &vm_callbacks },
- { "register", NULL, &register_callbacks },
- { "file", NULL, &file_callbacks },
- { "data", NULL, &data_callbacks },
- { "htab", NULL, &htab_callbacks },
- { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
- { "stack", NULL, &stack_callbacks },
- { "load-binary", NULL, &binary_callbacks },
- { "map-binary", NULL, &binary_callbacks },
- /* standard OpenBoot devices */
- { "aliases", NULL, &passthrough_callbacks },
- { "options", NULL, &passthrough_callbacks },
- { "chosen", NULL, &passthrough_callbacks },
- { "packages", NULL, &passthrough_callbacks },
- { "cpus", NULL, &passthrough_callbacks },
- { "openprom", NULL, &passthrough_callbacks },
- { "init", NULL, &passthrough_callbacks },
- { "trace", NULL, &trace_callbacks },
- { NULL },
-};
-
-const device_descriptor *const device_table[] = {
- old_device_table,
-#include "hw.c"
- NULL,
-};
-
-
-#endif /* _DEVICE_TABLE_C_ */