/[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

Annotation of /trunk/memory.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC1/memory.c
File MIME type: text/plain
File size: 8414 byte(s)
dynamips-0.2.7-RC1

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * 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 dpavlin 7 #include "cpu.h"
18     #include "vm.h"
19 dpavlin 1 #include "dynamips.h"
20     #include "memory.h"
21     #include "device.h"
22    
23     /* Record a memory access */
24 dpavlin 7 void memlog_rec_access(cpu_gen_t *cpu,m_uint64_t vaddr,m_uint64_t data,
25 dpavlin 1 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 dpavlin 7 acc->iaddr = cpu_get_pc(cpu);
31 dpavlin 1 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 dpavlin 7 void memlog_dump(cpu_gen_t *cpu)
42 dpavlin 1 {
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 dpavlin 7 if (cpu_get_pc(cpu)) {
53 dpavlin 1 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 dpavlin 7 cpu->id,acc->iaddr,acc->vaddr,acc->op_size,
61 dpavlin 1 (acc->op_type == MTS_READ) ? "read " : "write",
62     s_data);
63     }
64     }
65     }
66    
67     /* Update the data obtained by a read access */
68 dpavlin 7 void memlog_update_read(cpu_gen_t *cpu,m_iptr_t raddr)
69 dpavlin 1 {
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 dpavlin 7 /* === Operations on physical memory ====================================== */
97 dpavlin 1
98 dpavlin 7 /* 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 dpavlin 1
108 dpavlin 7 if (!(dev = dev_lookup(vm,paddr,FALSE)))
109     return NULL;
110 dpavlin 1
111 dpavlin 7 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 dpavlin 1
115 dpavlin 7 return(ptr + (paddr & VM_PAGE_IMASK));
116 dpavlin 1 }
117    
118 dpavlin 7 if ((dev->host_addr != 0) && !(dev->flags & VDEVICE_FLAG_NO_MTS_MMAP))
119     return((void *)dev->host_addr + (paddr - dev->phys_addr));
120 dpavlin 1
121 dpavlin 7 if (op_size == 0)
122     return NULL;
123 dpavlin 1
124 dpavlin 7 offset = paddr - dev->phys_addr;
125     return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data));
126     }
127 dpavlin 1
128 dpavlin 7 /* 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 dpavlin 1 {
132 dpavlin 7 m_uint64_t dummy;
133     m_uint32_t r;
134     u_char *ptr;
135 dpavlin 1
136 dpavlin 7 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 dpavlin 1 break;
149 dpavlin 7 case 2:
150     *(m_uint16_t *)real_buffer =
151     htovm16(physmem_copy_u16_from_vm(vm,paddr));
152 dpavlin 1 break;
153 dpavlin 7 case 1:
154     *(m_uint8_t *)real_buffer = physmem_copy_u8_from_vm(vm,paddr);
155 dpavlin 1 break;
156     }
157     }
158    
159 dpavlin 7 real_buffer += r;
160     paddr += r;
161     len -= r;
162 dpavlin 1 }
163     }
164 dpavlin 2
165 dpavlin 1 /* 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 dpavlin 7 m_uint64_t dummy;
170     m_uint32_t r;
171 dpavlin 1 u_char *ptr;
172    
173 dpavlin 7 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 dpavlin 1 }
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 dpavlin 7 m_uint64_t tmp = 0;
206     m_uint32_t *ptr;
207 dpavlin 1
208 dpavlin 7 if ((ptr = physmem_get_hptr(vm,paddr,4,MTS_READ,&tmp)) != NULL)
209     return(vmtoh32(*ptr));
210 dpavlin 1
211 dpavlin 7 return(tmp);
212 dpavlin 1 }
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 dpavlin 7 m_uint64_t tmp = val;
218     m_uint32_t *ptr;
219 dpavlin 1
220 dpavlin 7 if ((ptr = physmem_get_hptr(vm,paddr,4,MTS_WRITE,&tmp)) != NULL)
221     *ptr = htovm32(val);
222 dpavlin 1 }
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 dpavlin 7 m_uint64_t tmp = 0;
228     m_uint16_t *ptr;
229 dpavlin 1
230 dpavlin 7 if ((ptr = physmem_get_hptr(vm,paddr,2,MTS_READ,&tmp)) != NULL)
231     return(vmtoh16(*ptr));
232 dpavlin 1
233 dpavlin 7 return(tmp);
234 dpavlin 1 }
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 dpavlin 7 m_uint64_t tmp = val;
240     m_uint16_t *ptr;
241 dpavlin 1
242 dpavlin 7 if ((ptr = physmem_get_hptr(vm,paddr,2,MTS_WRITE,&tmp)) != NULL)
243     *ptr = htovm16(val);
244     }
245 dpavlin 1
246 dpavlin 7 /* 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 dpavlin 1
252 dpavlin 7 if ((ptr = physmem_get_hptr(vm,paddr,1,MTS_READ,&tmp)) != NULL)
253     return(*ptr);
254    
255     return(tmp);
256 dpavlin 1 }
257    
258 dpavlin 7 /* 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 dpavlin 1 /* 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 dpavlin 7 m_uint64_t dummy;
273 dpavlin 1 u_char *sptr,*dptr;
274 dpavlin 7 size_t clen,sl,dl;
275 dpavlin 1
276 dpavlin 7 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 dpavlin 1
280 dpavlin 7 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 dpavlin 1 }
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