aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/hw_shm.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@oarcorp.com>2008-11-18 21:30:37 +0000
committerJoel Sherrill <joel.sherrill@oarcorp.com>2008-11-18 21:30:37 +0000
commit00a0b122cf3b524243c3cea05101bacd5a1595ba (patch)
treeae53946a87294331d26ad6f53352322c14a4f60b /sim/ppc/hw_shm.c
parent394a666683b04e52d011fdc548b2bc5e60091693 (diff)
downloadgdb-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.c236
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, &reg) )
+ 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_ */