dev_ram.cc Source File

Back to the index.

dev_ram.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2011 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: A generic RAM (memory) device
29  *
30  * Note: This device can also be used to mirror/alias another part of RAM.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/mman.h>
38 
39 #include "cpu.h"
40 #include "devices.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44 
45 
46 struct ram_data {
47  uint64_t baseaddress;
48  const char* name;
49 
50  bool trace;
51  int mode;
52  uint64_t otheraddress;
53 
54  /* If mode = DEV_RAM_MIRROR: */
55  uint64_t offset;
56 
57  /* If mode = DEV_RAM_RAM: */
58  unsigned char *data;
59  uint64_t length;
60 };
61 
62 
64 {
65  struct ram_data *d = (struct ram_data *) extra;
66 
67  if (cpu->running && d->trace && writeflag == MEM_WRITE) {
68  fatal("[ %s: write %i byte%s from 0x%x:",
69  d->name, (int)len, len==1? "":"s", (int)relative_addr);
70  for (size_t i=0; i<len; i++)
71  fatal(" %02x", data[i]);
72  fatal(" ]\n");
73  }
74 
75  switch (d->mode) {
76 
77  case DEV_RAM_MIRROR:
78  /* TODO: how about caches? */
79  {
80  int result = cpu->memory_rw(cpu, mem,
81  d->otheraddress + relative_addr, data, len,
82  writeflag, PHYSICAL);
83 
84  if (cpu->running && d->trace) {
85  fatal("[ %s: read %i byte%s from 0x%x:",
86  d->name, (int)len, len==1? "":"s", (int)relative_addr);
87  for (size_t i=0; i<len; i++)
88  fatal(" %02x", data[i]);
89  fatal(" ]\n");
90  }
91 
92  return result;
93  }
94 
95  case DEV_RAM_RAM:
96  if (writeflag == MEM_WRITE) {
97  memcpy(&d->data[relative_addr], data, len);
98 
99  /* Invalidate any code translations on a write: */
100  if (cpu->invalidate_code_translation != NULL) {
102  cpu, d->baseaddress + relative_addr,
104  }
105  } else {
106  memcpy(data, &d->data[relative_addr], len);
107 
108  if (cpu->running && d->trace) {
109  fatal("[ %s: read %i byte%s from 0x%x:",
110  d->name, (int)len, len==1? "":"s", (int)relative_addr);
111  for (size_t i=0; i<len; i++)
112  fatal(" %02x", data[i]);
113  fatal(" ]\n");
114  }
115  }
116  break;
117 
118  default:
119  fatal("dev_ram_access(): unknown mode %i\n", d->mode);
120  exit(1);
121  }
122 
123  return 1;
124 }
125 
126 
127 /*
128  * dev_ram_init():
129  *
130  * Initializes a RAM or mirror device. Things get a bit complicated because
131  * of dyntrans (i.e. mirrored memory ranges should be entered into the
132  * translation arrays just as normal memory and other devices are).
133  */
134 void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length,
135  int mode, uint64_t otheraddress, const char* name)
136 {
137  struct ram_data *d;
138  int flags = DM_DEFAULT, points_to_ram = 1;
139 
140  CHECK_ALLOCATION(d = (struct ram_data *) malloc(sizeof(struct ram_data)));
141  memset(d, 0, sizeof(struct ram_data));
142 
143  d->name = strdup((name == NULL) ? "ram" : name);
144 
147  points_to_ram = 0;
148  }
149 
152  d->trace = true;
153  }
154 
155  d->mode = mode;
156  d->baseaddress = baseaddr;
158 
159  switch (d->mode) {
160 
161  case DEV_RAM_MIRROR:
162  /*
163  * Calculate the amount that the mirror memory is offset from
164  * the real (physical) memory. This is used in src/memory_rw.c
165  * with dyntrans accesses if DM_EMULATED_RAM is set.
166  */
167  d->offset = baseaddr - otheraddress;
168  d->name = (string(d->name) + " [mirror]").c_str();
169 
170  /* Aligned RAM? Then it works with dyntrans. */
171  if (points_to_ram &&
172  (baseaddr & (machine->arch_pagesize-1)) == 0 &&
173  (otheraddress & (machine->arch_pagesize - 1)) == 0 &&
174  (length & (machine->arch_pagesize - 1)) == 0 &&
175  !d->trace)
177  | DM_EMULATED_RAM;
178 
180  baseaddr, length, dev_ram_access, d, flags
181  | DM_READS_HAVE_NO_SIDE_EFFECTS, (unsigned char*) (void *) &d->offset);
182  break;
183 
184  case DEV_RAM_RAM:
185  /*
186  * Allocate zero-filled RAM using mmap(). If mmap() failed,
187  * try malloc(), but then memset() must also be called, which
188  * can be slow for large chunks of memory.
189  */
190  d->length = length;
191  d->data = (unsigned char *) mmap(NULL, length,
192  PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
193  if (d->data == NULL) {
194  CHECK_ALLOCATION(d->data = (unsigned char *) malloc(length));
195  memset(d->data, 0, length);
196  }
197 
198  /* Aligned memory? Then it works with dyntrans. */
199  if ((baseaddr & (machine->arch_pagesize - 1)) == 0 &&
200  (length & (machine->arch_pagesize - 1)) == 0 &&
201  !d->trace)
203 
204  memory_device_register(machine->memory, d->name, baseaddr,
205  d->length, dev_ram_access, d, flags
207  break;
208 
209  default:
210  fatal("dev_ram_access(): %s: unknown mode %i\n", d->name, d->mode);
211  exit(1);
212  }
213 }
214 
ram_data::name
const char * name
Definition: dev_ram.cc:48
DM_EMULATED_RAM
#define DM_EMULATED_RAM
Definition: memory.h:134
ram_data::otheraddress
uint64_t otheraddress
Definition: dev_ram.cc:52
data
u_short data
Definition: siireg.h:79
machine::arch_pagesize
int arch_pagesize
Definition: machine.h:151
cpu::running
uint8_t running
Definition: cpu.h:353
ram_data::length
uint64_t length
Definition: dev_ram.cc:59
DEV_RAM_MIRROR
#define DEV_RAM_MIRROR
Definition: devices.h:365
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
DEV_RAM_RAM
#define DEV_RAM_RAM
Definition: devices.h:364
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
cpu::invalidate_code_translation
void(* invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:376
DM_DYNTRANS_WRITE_OK
#define DM_DYNTRANS_WRITE_OK
Definition: memory.h:132
ram_data::data
unsigned char * data
Definition: dev_ram.cc:58
DEVICE_ACCESS
DEVICE_ACCESS(ram)
Definition: dev_ram.cc:63
PHYSICAL
#define PHYSICAL
Definition: memory.h:126
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
misc.h
machine.h
machine
Definition: machine.h:97
dev_ram_access
int dev_ram_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
ram_data
Definition: dev_ram.cc:46
cpu.h
machine::memory
struct memory * memory
Definition: machine.h:126
DEV_RAM_MIGHT_POINT_TO_DEVICES
#define DEV_RAM_MIGHT_POINT_TO_DEVICES
Definition: devices.h:366
ram_data::offset
uint64_t offset
Definition: dev_ram.cc:55
DM_READS_HAVE_NO_SIDE_EFFECTS
#define DM_READS_HAVE_NO_SIDE_EFFECTS
Definition: memory.h:133
ram_data::baseaddress
uint64_t baseaddress
Definition: dev_ram.cc:47
ram_data::trace
bool trace
Definition: dev_ram.cc:50
INVALIDATE_PADDR
#define INVALIDATE_PADDR
Definition: cpu.h:479
devices.h
cpu
Definition: cpu.h:326
DM_DYNTRANS_OK
#define DM_DYNTRANS_OK
Definition: memory.h:131
cpu::memory_rw
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:365
dev_ram_init
void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length, int mode, uint64_t otheraddress, const char *name)
Definition: dev_ram.cc:134
memory.h
DEV_RAM_TRACE_ALL_ACCESSES
#define DEV_RAM_TRACE_ALL_ACCESSES
Definition: devices.h:367
ram_data::mode
int mode
Definition: dev_ram.cc:51
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17