diff options
author | Joel Sherrill <joel.sherrill@oarcorp.com> | 2008-11-18 21:30:37 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@oarcorp.com> | 2008-11-18 21:30:37 +0000 |
commit | 00a0b122cf3b524243c3cea05101bacd5a1595ba (patch) | |
tree | ae53946a87294331d26ad6f53352322c14a4f60b /sim/ppc/hw_shm.c | |
parent | 394a666683b04e52d011fdc548b2bc5e60091693 (diff) | |
download | gdb-00a0b122cf3b524243c3cea05101bacd5a1595ba.zip gdb-00a0b122cf3b524243c3cea05101bacd5a1595ba.tar.gz gdb-00a0b122cf3b524243c3cea05101bacd5a1595ba.tar.bz2 |
2008-11-18 Joel Sherrill <joel.sherrill@oarcorp.com>
* configure: Regenerated.
* configure.ac: Add test for System V shared memory and semaphore.
* debug.c, debug.h: Add trace support for new devices.
* hw_sem.c, hw_shm.c: New files.
* Makefile.in: Add hw_sem.c and hw_shm.c.
Diffstat (limited to 'sim/ppc/hw_shm.c')
-rw-r--r-- | sim/ppc/hw_shm.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/sim/ppc/hw_shm.c b/sim/ppc/hw_shm.c new file mode 100644 index 0000000..01a4a9a --- /dev/null +++ b/sim/ppc/hw_shm.c @@ -0,0 +1,236 @@ +/* This file is part of the program psim. + + Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com> + + 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 _HW_SHM_C_ +#define _HW_SHM_C_ + +#include "device_table.h" + +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif + +#include <sys/ipc.h> +#include <sys/shm.h> + + +/* DEVICE + + + shm - map unix shared memory into psim address space + + + DESCRIPTION + + + This device implements an area of memory which is mapped into UNIX + shared memory. + + + PROPERTIES + + + reg = <address> <size> (required) + + Determine where the memory lives in the parents address space. + The SHM area is assumed to be of the same length. + + key = <integer> (required) + + This is the key of the unix shared memory area. + + EXAMPLES + + + Enable tracing of the shm: + + | bash$ psim -t shm-device \ + + + Configure a 512 kilobytes of UNIX shared memory with the key 0x12345678 + mapped into psim address space at 0x0c000000. + + | -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \ + | -o '/shm@0x0c000000/key 0x12345678' \ + + sim/ppc/run -o '/#address-cells 1' \ + -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \ + -o '/shm@0x0c000000/key 0x12345678' ../psim-hello/hello + + BUGS + + None known. + + */ + +typedef struct _hw_shm_device { + unsigned_word physical_address; + char *shm_address; + unsigned sizeof_memory; + key_t key; + int id; +} hw_shm_device; + +static void +hw_shm_init_data(device *me) +{ + hw_shm_device *shm = (hw_shm_device*)device_data(me); + const device_unit *d; + reg_property_spec reg; + int i; + + /* Obtain the Key Value */ + if (device_find_property(me, "key") == NULL) + error("shm_init_data() required key property is missing\n"); + + shm->key = (key_t) device_find_integer_property(me, "key"); + DTRACE(shm, ("shm key (0x%08x)\n", shm->key) ); + + /* Figure out where this memory is in address space and how long it is */ + if ( !device_find_reg_array_property(me, "reg", 0, ®) ) + error("hw_shm_init_data() no address registered\n"); + + /* Determine the address and length being as paranoid as possible */ + shm->physical_address = 0xffffffff; + shm->sizeof_memory = 0xffffffff; + + for ( i=0 ; i<reg.address.nr_cells; i++ ) { + if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0) + continue; + + if ( shm->physical_address != 0xffffffff ) + device_error(me, "Only single celled address ranges supported\n"); + + shm->physical_address = reg.address.cells[i]; + DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address)); + + shm->sizeof_memory = reg.size.cells[i]; + DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory)); + } + + if ( shm->physical_address == 0xffffffff ) + device_error(me, "Address not specified\n" ); + + if ( shm->sizeof_memory == 0xffffffff ) + device_error(me, "Length not specified\n" ); + + /* Now actually attach to or create the shared memory area */ + shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660); + if (shm->id == -1) + error("hw_shm_init_data() shmget failed\n"); + + shm->shm_address = shmat(shm->id, (char *)0, SHM_RND); + if (shm->shm_address == (void *)-1) + error("hw_shm_init_data() shmat failed\n"); +} + +static void +hw_shm_attach_address_callback(device *me, + attach_type attach, + int space, + unsigned_word addr, + unsigned nr_bytes, + access_type access, + device *client) /*callback/default*/ +{ + hw_shm_device *shm = (hw_shm_device*)device_data(me); + + if (space != 0) + error("shm_attach_address_callback() invalid address space\n"); + + if (nr_bytes == 0) + error("shm_attach_address_callback() invalid size\n"); +} + + +static unsigned +hw_shm_io_read_buffer(device *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes, + cpu *processor, + unsigned_word cia) +{ + hw_shm_device *shm = (hw_shm_device*)device_data(me); + + /* do we need to worry about out of range addresses? */ + + DTRACE(shm, ("read %p %x %x %x\n", \ + shm->shm_address, shm->physical_address, addr, nr_bytes) ); + + memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes); + return nr_bytes; +} + + +static unsigned +hw_shm_io_write_buffer(device *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes, + cpu *processor, + unsigned_word cia) +{ + hw_shm_device *shm = (hw_shm_device*)device_data(me); + + /* do we need to worry about out of range addresses? */ + + DTRACE(shm, ("write %p %x %x %x\n", \ + shm->shm_address, shm->physical_address, addr, nr_bytes) ); + + memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes); + return nr_bytes; +} + +static device_callbacks const hw_shm_callbacks = { + { generic_device_init_address, hw_shm_init_data }, + { hw_shm_attach_address_callback, }, /* address */ + { hw_shm_io_read_buffer, + hw_shm_io_write_buffer }, /* IO */ + { NULL, }, /* DMA */ + { NULL, }, /* interrupt */ + { NULL, }, /* unit */ + NULL, +}; + +static void * +hw_shm_create(const char *name, + const device_unit *unit_address, + const char *args) +{ + hw_shm_device *shm = ZALLOC(hw_shm_device); + return shm; +} + + + +const device_descriptor hw_shm_device_descriptor[] = { + { "shm", hw_shm_create, &hw_shm_callbacks }, + { NULL }, +}; + +#endif /* _HW_SHM_C_ */ |