OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [ppc/] [hw_vm.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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
7
    the Free Software Foundation; either version 2 of the License, or
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
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _HW_VM_C_
23
#define _HW_VM_C_
24
 
25
#include "device_table.h"
26
#include "cpu.h"
27
 
28
#include <signal.h>
29
 
30
/* DEVICE
31
 
32
   vm - virtual memory device for user simulation modes
33
 
34
   DESCRIPTION
35
 
36
   In user mode, mapped text, data and stack addresses are managed by
37
   the core.  Unmapped addresses are passed onto this device (because
38
   it establishes its self as the fallback device) for processing.
39
 
40
   During initialization, children of this device will request the
41
   mapping of the initial text and data segments.  Those requests are
42
   passed onto the core device so that that may establish the initial
43
   memory regions.
44
 
45
   Once the simulation has started (as noted above) any access to an
46
   unmapped address range will be passed down to this device as an IO
47
   access.  This device will then either attach additional memory to
48
   the core device or signal the access as being invalid.
49
 
50
   The IOCTL function is used to notify this device of any changes to
51
   the users `brk' point.
52
 
53
   PROPERTIES
54
 
55
   stack-base = <number>
56
 
57
   Specifies the lower address of the stack segment in the users
58
   virtual address space.  The initial stack page is defined by
59
   stack-base + nr-bytes.
60
 
61
   nr-bytes = <number>
62
 
63
   Specifies the maximum size of the stack segment in the users
64
   address space.
65
 
66
   */
67
 
68
typedef struct _hw_vm_device {
69
  /* area of memory valid for stack addresses */
70
  unsigned_word stack_base; /* min possible stack value */
71
  unsigned_word stack_bound;
72
  unsigned_word stack_lower_limit;
73
  /* area of memory valid for heap addresses */
74
  unsigned_word heap_base;
75
  unsigned_word heap_bound;
76
  unsigned_word heap_upper_limit;
77
} hw_vm_device;
78
 
79
 
80
static void
81
hw_vm_init_address_callback(device *me)
82
{
83
  hw_vm_device *vm = (hw_vm_device*)device_data(me);
84
 
85
  /* revert the stack/heap variables to their defaults */
86
  vm->stack_base = device_find_integer_property(me, "stack-base");
87
  vm->stack_bound = (vm->stack_base
88
                     + device_find_integer_property(me, "nr-bytes"));
89
  vm->stack_lower_limit = vm->stack_bound;
90
  vm->heap_base = 0;
91
  vm->heap_bound = 0;
92
  vm->heap_upper_limit = 0;
93
 
94
  /* establish this device as the default memory handler */
95
  device_attach_address(device_parent(me),
96
                        attach_callback + 1,
97
 
98
 
99
                        (((unsigned)0)-1) /*nr_bytes - ignore*/,
100
                        access_read_write /*access*/,
101
                        me);
102
}
103
 
104
 
105
static void
106
hw_vm_attach_address(device *me,
107
                     attach_type attach,
108
                     int space,
109
                     unsigned_word addr,
110
                     unsigned nr_bytes,
111
                     access_type access,
112
                     device *client) /*callback/default*/
113
{
114
  hw_vm_device *vm = (hw_vm_device*)device_data(me);
115
  /* update end of bss if necessary */
116
  if (vm->heap_base < addr + nr_bytes) {
117
    vm->heap_base = addr + nr_bytes;
118
    vm->heap_bound = addr + nr_bytes;
119
    vm->heap_upper_limit = addr + nr_bytes;
120
  }
121
  device_attach_address(device_parent(me),
122
                        attach_raw_memory,
123
 
124
                        addr,
125
                        nr_bytes,
126
                        access,
127
                        me);
128
}
129
 
130
 
131
static unsigned
132
hw_vm_add_space(device *me,
133
                unsigned_word addr,
134
                unsigned nr_bytes,
135
                cpu *processor,
136
                unsigned_word cia)
137
{
138
  hw_vm_device *vm = (hw_vm_device*)device_data(me);
139
  unsigned_word block_addr;
140
  unsigned block_nr_bytes;
141
 
142
  /* an address in the stack area, allocate just down to the addressed
143
     page */
144
  if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
145
    block_addr = FLOOR_PAGE(addr);
146
    block_nr_bytes = vm->stack_lower_limit - block_addr;
147
    vm->stack_lower_limit = block_addr;
148
  }
149
  /* an address in the heap area, allocate all of the required heap */
150
  else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
151
    block_addr = vm->heap_upper_limit;
152
    block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
153
    vm->heap_upper_limit = vm->heap_bound;
154
  }
155
  /* oops - an invalid address - abort the cpu */
156
  else if (processor != NULL) {
157
    cpu_halt(processor, cia, was_signalled, SIGSEGV);
158
    return 0;
159
  }
160
  /* 2*oops - an invalid address and no processor */
161
  else {
162
    return 0;
163
  }
164
 
165
  /* got the parameters, allocate the space */
166
  device_attach_address(device_parent(me),
167
                        attach_raw_memory,
168
 
169
                        block_addr,
170
                        block_nr_bytes,
171
                        access_read_write,
172
                        me);
173
  return block_nr_bytes;
174
}
175
 
176
 
177
static unsigned
178
hw_vm_io_read_buffer_callback(device *me,
179
                           void *dest,
180
                           int space,
181
                           unsigned_word addr,
182
                           unsigned nr_bytes,
183
                           cpu *processor,
184
                           unsigned_word cia)
185
{
186
  if (hw_vm_add_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
187
    memset(dest, 0, nr_bytes); /* always initialized to zero */
188
    return nr_bytes;
189
  }
190
  else
191
    return 0;
192
}
193
 
194
 
195
static unsigned
196
hw_vm_io_write_buffer_callback(device *me,
197
                            const void *source,
198
                            int space,
199
                            unsigned_word addr,
200
                            unsigned nr_bytes,
201
                            cpu *processor,
202
                            unsigned_word cia)
203
{
204
  if (hw_vm_add_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
205
    return device_dma_write_buffer(device_parent(me), source,
206
                                   space, addr,
207
                                   nr_bytes,
208
                                   0/*violate_read_only*/);
209
  }
210
  else
211
    return 0;
212
}
213
 
214
 
215
static int
216
hw_vm_ioctl(device *me,
217
            cpu *processor,
218
            unsigned_word cia,
219
            device_ioctl_request request,
220
            va_list ap)
221
{
222
  /* While the caller is notified that the heap has grown by the
223
     requested amount, the heap is actually extended out to a page
224
     boundary. */
225
  hw_vm_device *vm = (hw_vm_device*)device_data(me);
226
  switch (request) {
227
  case device_ioctl_break:
228
    {
229
      unsigned_word requested_break = va_arg(ap, unsigned_word);
230
      unsigned_word new_break = ALIGN_8(requested_break);
231
      unsigned_word old_break = vm->heap_bound;
232
      signed_word delta = new_break - old_break;
233
      if (delta > 0)
234
        vm->heap_bound = ALIGN_PAGE(new_break);
235
      break;
236
    }
237
  default:
238
    device_error(me, "Unsupported ioctl request");
239
    break;
240
  }
241
  return 0;
242
 
243
}
244
 
245
 
246
static device_callbacks const hw_vm_callbacks = {
247
  { hw_vm_init_address_callback, },
248
  { hw_vm_attach_address,
249
    passthrough_device_address_detach, },
250
  { hw_vm_io_read_buffer_callback,
251
    hw_vm_io_write_buffer_callback, },
252
  { NULL, passthrough_device_dma_write_buffer, },
253
  { NULL, }, /* interrupt */
254
  { generic_device_unit_decode,
255
    generic_device_unit_encode, },
256
  NULL, /* instance */
257
  hw_vm_ioctl,
258
};
259
 
260
 
261
static void *
262
hw_vm_create(const char *name,
263
             const device_unit *address,
264
             const char *args)
265
{
266
  hw_vm_device *vm = ZALLOC(hw_vm_device);
267
  return vm;
268
}
269
 
270
const device_descriptor hw_vm_device_descriptor[] = {
271
  { "vm", hw_vm_create, &hw_vm_callbacks },
272
  { NULL },
273
};
274
 
275
#endif _HW_VM_C_

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.