/[dynamips]/trunk/memory.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/memory.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 8411 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 */
5
6 #define _GNU_SOURCE
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mman.h>
14 #include <fcntl.h>
15 #include <assert.h>
16
17 #include "cpu.h"
18 #include "vm.h"
19 #include "dynamips.h"
20 #include "memory.h"
21 #include "device.h"
22
23 /* Record a memory access */
24 void memlog_rec_access(cpu_gen_t *cpu,m_uint64_t vaddr,m_uint64_t data,
25 m_uint32_t op_size,m_uint32_t op_type)
26 {
27 memlog_access_t *acc;
28
29 acc = &cpu->memlog_array[cpu->memlog_pos];
30 acc->iaddr = cpu_get_pc(cpu);
31 acc->vaddr = vaddr;
32 acc->data = data;
33 acc->op_size = op_size;
34 acc->op_type = op_type;
35 acc->data_valid = (op_type == MTS_WRITE);
36
37 cpu->memlog_pos = (cpu->memlog_pos + 1) & (MEMLOG_COUNT - 1);
38 }
39
40 /* Show the latest memory accesses */
41 void memlog_dump(cpu_gen_t *cpu)
42 {
43 memlog_access_t *acc;
44 char s_data[64];
45 u_int i,pos;
46
47 for(i=0;i<MEMLOG_COUNT;i++) {
48 pos = cpu->memlog_pos + i;
49 pos &= (MEMLOG_COUNT-1);
50 acc = &cpu->memlog_array[pos];
51
52 if (cpu_get_pc(cpu)) {
53 if (acc->data_valid)
54 snprintf(s_data,sizeof(s_data),"0x%llx",acc->data);
55 else
56 snprintf(s_data,sizeof(s_data),"XXXXXXXX");
57
58 printf("CPU%u: pc=0x%8.8llx, vaddr=0x%8.8llx, "
59 "size=%u, type=%s, data=%s\n",
60 cpu->id,acc->iaddr,acc->vaddr,acc->op_size,
61 (acc->op_type == MTS_READ) ? "read " : "write",
62 s_data);
63 }
64 }
65 }
66
67 /* Update the data obtained by a read access */
68 void memlog_update_read(cpu_gen_t *cpu,m_iptr_t raddr)
69 {
70 memlog_access_t *acc;
71
72 acc = &cpu->memlog_array[(cpu->memlog_pos-1) & (MEMLOG_COUNT-1)];
73
74 if (acc->op_type == MTS_READ)
75 {
76 switch(acc->op_size) {
77 case 1:
78 acc->data = *(m_uint8_t *)raddr;
79 break;
80 case 2:
81 acc->data = vmtoh16(*(m_uint16_t *)raddr);
82 break;
83 case 4:
84 acc->data = vmtoh32(*(m_uint32_t *)raddr);
85 break;
86 case 8:
87 acc->data = vmtoh64(*(m_uint64_t *)raddr);
88 break;
89 }
90
91 acc->data_valid = TRUE;
92 }
93 }
94
95
96 /* === Operations on physical memory ====================================== */
97
98 /* Get host pointer for the physical address */
99 static inline void *physmem_get_hptr(vm_instance_t *vm,m_uint64_t paddr,
100 u_int op_size,u_int op_type,
101 m_uint64_t *data)
102 {
103 struct vdevice *dev;
104 m_uint32_t offset;
105 void *ptr;
106 int cow;
107
108 if (!(dev = dev_lookup(vm,paddr,FALSE)))
109 return NULL;
110
111 if (dev->flags & VDEVICE_FLAG_SPARSE) {
112 ptr = (void *)dev_sparse_get_host_addr(vm,dev,paddr,op_type,&cow);
113 if (!ptr) return NULL;
114
115 return(ptr + (paddr & VM_PAGE_IMASK));
116 }
117
118 if ((dev->host_addr != 0) && !(dev->flags & VDEVICE_FLAG_NO_MTS_MMAP))
119 return((void *)dev->host_addr + (paddr - dev->phys_addr));
120
121 if (op_size == 0)
122 return NULL;
123
124 offset = paddr - dev->phys_addr;
125 return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data));
126 }
127
128 /* Copy a memory block from VM physical RAM to real host */
129 void physmem_copy_from_vm(vm_instance_t *vm,void *real_buffer,
130 m_uint64_t paddr,size_t len)
131 {
132 m_uint64_t dummy;
133 m_uint32_t r;
134 u_char *ptr;
135
136 while(len > 0) {
137 r = m_min(VM_PAGE_SIZE - (paddr & VM_PAGE_IMASK), len);
138 ptr = physmem_get_hptr(vm,paddr,0,MTS_READ,&dummy);
139
140 if (likely(ptr != NULL)) {
141 memcpy(real_buffer,ptr,r);
142 } else {
143 r = m_min(len,4);
144 switch(r) {
145 case 4:
146 *(m_uint32_t *)real_buffer =
147 htovm32(physmem_copy_u32_from_vm(vm,paddr));
148 break;
149 case 2:
150 *(m_uint16_t *)real_buffer =
151 htovm16(physmem_copy_u16_from_vm(vm,paddr));
152 break;
153 case 1:
154 *(m_uint8_t *)real_buffer = physmem_copy_u8_from_vm(vm,paddr);
155 break;
156 }
157 }
158
159 real_buffer += r;
160 paddr += r;
161 len -= r;
162 }
163 }
164
165 /* Copy a memory block to VM physical RAM from real host */
166 void physmem_copy_to_vm(vm_instance_t *vm,void *real_buffer,
167 m_uint64_t paddr,size_t len)
168 {
169 m_uint64_t dummy;
170 m_uint32_t r;
171 u_char *ptr;
172
173 while(len > 0) {
174 r = m_min(VM_PAGE_SIZE - (paddr & VM_PAGE_IMASK), len);
175 ptr = physmem_get_hptr(vm,paddr,0,MTS_WRITE,&dummy);
176
177 if (likely(ptr != NULL)) {
178 memcpy(ptr,real_buffer,r);
179 } else {
180 r = m_min(len,4);
181 switch(r) {
182 case 4:
183 physmem_copy_u32_to_vm(vm,paddr,
184 htovm32(*(m_uint32_t *)real_buffer));
185 break;
186 case 2:
187 physmem_copy_u16_to_vm(vm,paddr,
188 htovm16(*(m_uint16_t *)real_buffer));
189 break;
190 case 1:
191 physmem_copy_u8_to_vm(vm,paddr,*(m_uint8_t *)real_buffer);
192 break;
193 }
194 }
195
196 real_buffer += r;
197 paddr += r;
198 len -= r;
199 }
200 }
201
202 /* Copy a 32-bit word from the VM physical RAM to real host */
203 m_uint32_t physmem_copy_u32_from_vm(vm_instance_t *vm,m_uint64_t paddr)
204 {
205 m_uint64_t tmp = 0;
206 m_uint32_t *ptr;
207
208 if ((ptr = physmem_get_hptr(vm,paddr,4,MTS_READ,&tmp)) != NULL)
209 return(vmtoh32(*ptr));
210
211 return(tmp);
212 }
213
214 /* Copy a 32-bit word to the VM physical RAM from real host */
215 void physmem_copy_u32_to_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint32_t val)
216 {
217 m_uint64_t tmp = val;
218 m_uint32_t *ptr;
219
220 if ((ptr = physmem_get_hptr(vm,paddr,4,MTS_WRITE,&tmp)) != NULL)
221 *ptr = htovm32(val);
222 }
223
224 /* Copy a 16-bit word from the VM physical RAM to real host */
225 m_uint16_t physmem_copy_u16_from_vm(vm_instance_t *vm,m_uint64_t paddr)
226 {
227 m_uint64_t tmp = 0;
228 m_uint16_t *ptr;
229
230 if ((ptr = physmem_get_hptr(vm,paddr,2,MTS_READ,&tmp)) != NULL)
231 return(vmtoh16(*ptr));
232
233 return(tmp);
234 }
235
236 /* Copy a 16-bit word to the VM physical RAM from real host */
237 void physmem_copy_u16_to_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint16_t val)
238 {
239 m_uint64_t tmp = val;
240 m_uint16_t *ptr;
241
242 if ((ptr = physmem_get_hptr(vm,paddr,2,MTS_WRITE,&tmp)) != NULL)
243 *ptr = htovm16(val);
244 }
245
246 /* Copy a byte from the VM physical RAM to real host */
247 m_uint8_t physmem_copy_u8_from_vm(vm_instance_t *vm,m_uint64_t paddr)
248 {
249 m_uint64_t tmp = 0;
250 m_uint8_t *ptr;
251
252 if ((ptr = physmem_get_hptr(vm,paddr,1,MTS_READ,&tmp)) != NULL)
253 return(*ptr);
254
255 return(tmp);
256 }
257
258 /* Copy a 16-bit word to the VM physical RAM from real host */
259 void physmem_copy_u8_to_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint8_t val)
260 {
261 m_uint64_t tmp = val;
262 m_uint8_t *ptr;
263
264 if ((ptr = physmem_get_hptr(vm,paddr,1,MTS_WRITE,&tmp)) != NULL)
265 *ptr = val;
266 }
267
268 /* DMA transfer operation */
269 void physmem_dma_transfer(vm_instance_t *vm,m_uint64_t src,m_uint64_t dst,
270 size_t len)
271 {
272 m_uint64_t dummy;
273 u_char *sptr,*dptr;
274 size_t clen,sl,dl;
275
276 while(len > 0) {
277 sptr = physmem_get_hptr(vm,src,0,MTS_READ,&dummy);
278 dptr = physmem_get_hptr(vm,dst,0,MTS_WRITE,&dummy);
279
280 if (!sptr || !dptr) {
281 vm_log(vm,"DMA","unable to transfer from 0x%llx to 0x%llx\n",src,dst);
282 return;
283 }
284
285 sl = VM_PAGE_SIZE - (src & VM_PAGE_IMASK);
286 dl = VM_PAGE_SIZE - (dst & VM_PAGE_IMASK);
287 clen = m_min(sl,dl);
288 clen = m_min(clen,len);
289
290 memcpy(dptr,sptr,clen);
291
292 src += clen;
293 dst += clen;
294 len -= clen;
295 }
296 }
297
298 /* strlen in VM physical memory */
299 size_t physmem_strlen(vm_instance_t *vm,m_uint64_t paddr)
300 {
301 struct vdevice *vm_ram;
302 size_t len = 0;
303 char *ptr;
304
305 if ((vm_ram = dev_lookup(vm,paddr,TRUE)) != NULL) {
306 ptr = (char *)vm_ram->host_addr + (paddr - vm_ram->phys_addr);
307 len = strlen(ptr);
308 }
309
310 return(len);
311 }
312
313 /* Physical memory dump (32-bit words) */
314 void physmem_dump_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint32_t u32_count)
315 {
316 m_uint32_t i;
317
318 for(i=0;i<u32_count;i++) {
319 vm_log(vm,"physmem_dump","0x%8.8llx: 0x%8.8x\n",
320 paddr+(i<<2),physmem_copy_u32_from_vm(vm,paddr+(i<<2)));
321 }
322 }

  ViewVC Help
Powered by ViewVC 1.1.26