/[gxemul]/trunk/src/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

Diff of /trunk/src/memory.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory.c,v 1.164 2005/04/09 21:10:54 debug Exp $   *  $Id: memory.c,v 1.190 2006/06/16 18:31:25 debug Exp $
29   *   *
30   *  Functions for handling the memory of an emulated machine.   *  Functions for handling the memory of an emulated machine.
31   */   */
# Line 36  Line 36 
36  #include <sys/types.h>  #include <sys/types.h>
37  #include <sys/mman.h>  #include <sys/mman.h>
38    
 #include "bintrans.h"  
 #include "cop0.h"  
39  #include "cpu.h"  #include "cpu.h"
40  #include "machine.h"  #include "machine.h"
41  #include "memory.h"  #include "memory.h"
 #include "mips_cpu_types.h"  
42  #include "misc.h"  #include "misc.h"
43    
44    
45  extern int quiet_mode;  extern int verbose;
 extern volatile int single_step;  
46    
47    
48  /*  /*
# Line 59  extern volatile int single_step; Line 55  extern volatile int single_step;
55   */   */
56  uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)  uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
57  {  {
58          int i;          int i, byte_order = cpu->byte_order;
59          uint64_t x = 0;          uint64_t x = 0;
60    
61            if (len & MEM_PCI_LITTLE_ENDIAN) {
62                    len &= ~MEM_PCI_LITTLE_ENDIAN;
63                    byte_order = EMUL_LITTLE_ENDIAN;
64            }
65    
66          /*  Switch byte order for incoming data, if necessary:  */          /*  Switch byte order for incoming data, if necessary:  */
67          if (cpu->byte_order == EMUL_BIG_ENDIAN)          if (byte_order == EMUL_BIG_ENDIAN)
68                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
69                          x <<= 8;                          x <<= 8;
70                          x |= buf[i];                          x |= buf[i];
# Line 89  uint64_t memory_readmax64(struct cpu *cp Line 90  uint64_t memory_readmax64(struct cpu *cp
90  void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,  void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,
91          uint64_t data)          uint64_t data)
92  {  {
93          int i;          int i, byte_order = cpu->byte_order;
94    
95            if (len & MEM_PCI_LITTLE_ENDIAN) {
96                    len &= ~MEM_PCI_LITTLE_ENDIAN;
97                    byte_order = EMUL_LITTLE_ENDIAN;
98            }
99    
100          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)          if (byte_order == EMUL_LITTLE_ENDIAN)
101                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
102                          buf[i] = data & 255;                          buf[i] = data & 255;
103                          data >>= 8;                          data >>= 8;
# Line 108  void memory_writemax64(struct cpu *cpu, Line 114  void memory_writemax64(struct cpu *cpu,
114   *  zeroed_alloc():   *  zeroed_alloc():
115   *   *
116   *  Allocates a block of memory using mmap(), and if that fails, try   *  Allocates a block of memory using mmap(), and if that fails, try
117   *  malloc() + memset().   *  malloc() + memset(). The returned memory block contains only zeroes.
118   */   */
119  void *zeroed_alloc(size_t s)  void *zeroed_alloc(size_t s)
120  {  {
# Line 132  void *zeroed_alloc(size_t s) Line 138  void *zeroed_alloc(size_t s)
138   *  This function creates a new memory object. An emulated machine needs one   *  This function creates a new memory object. An emulated machine needs one
139   *  of these.   *  of these.
140   */   */
141  struct memory *memory_new(uint64_t physical_max)  struct memory *memory_new(uint64_t physical_max, int arch)
142  {  {
143          struct memory *mem;          struct memory *mem;
144          int bits_per_pagetable = BITS_PER_PAGETABLE;          int bits_per_pagetable = BITS_PER_PAGETABLE;
# Line 157  struct memory *memory_new(uint64_t physi Line 163  struct memory *memory_new(uint64_t physi
163          }          }
164    
165          mem->physical_max = physical_max;          mem->physical_max = physical_max;
166            mem->dev_dyntrans_alignment = 4095;
167            if (arch == ARCH_ALPHA)
168                    mem->dev_dyntrans_alignment = 8191;
169    
170          s = entries_per_pagetable * sizeof(void *);          s = entries_per_pagetable * sizeof(void *);
171    
# Line 181  struct memory *memory_new(uint64_t physi Line 190  struct memory *memory_new(uint64_t physi
190  /*  /*
191   *  memory_points_to_string():   *  memory_points_to_string():
192   *   *
193   *  Returns 1 if there's something string-like at addr, otherwise 0.   *  Returns 1 if there's something string-like in emulated memory at address
194     *  addr, otherwise 0.
195   */   */
196  int memory_points_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,  int memory_points_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,
197          int min_string_length)          int min_string_length)
# Line 210  int memory_points_to_string(struct cpu * Line 220  int memory_points_to_string(struct cpu *
220  /*  /*
221   *  memory_conv_to_string():   *  memory_conv_to_string():
222   *   *
223   *  Convert virtual memory contents to a string, placing it in a   *  Convert emulated memory contents to a string, placing it in a buffer
224   *  buffer provided by the caller.   *  provided by the caller.
225   */   */
226  char *memory_conv_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,  char *memory_conv_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,
227          char *buf, int bufsize)          char *buf, int bufsize)
# Line 253  char *memory_conv_to_string(struct cpu * Line 263  char *memory_conv_to_string(struct cpu *
263    
264    
265  /*  /*
266   *  memory_device_bintrans_access():   *  memory_device_dyntrans_access():
267   *   *
268   *  Get the lowest and highest bintrans access since last time.   *  Get the lowest and highest dyntrans access since last time.
269   */   */
270  void memory_device_bintrans_access(struct cpu *cpu, struct memory *mem,  void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,
271          void *extra, uint64_t *low, uint64_t *high)          void *extra, uint64_t *low, uint64_t *high)
272  {  {
 #ifdef BINTRANS  
         int i, j;  
273          size_t s;          size_t s;
274          int need_inval = 0;          int i, need_inval = 0;
275    
276          /*  TODO: This is O(n), so it might be good to rewrite it some day.          /*  TODO: This is O(n), so it might be good to rewrite it some day.
277              For now, it will be enough, as long as this function is not              For now, it will be enough, as long as this function is not
# Line 271  void memory_device_bintrans_access(struc Line 279  void memory_device_bintrans_access(struc
279    
280          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
281                  if (mem->dev_extra[i] == extra &&                  if (mem->dev_extra[i] == extra &&
282                      mem->dev_bintrans_data[i] != NULL) {                      mem->dev_flags[i] & DM_DYNTRANS_WRITE_OK &&
283                          if (mem->dev_bintrans_write_low[i] != (uint64_t) -1)                      mem->dev_dyntrans_data[i] != NULL) {
284                            if (mem->dev_dyntrans_write_low[i] != (uint64_t) -1)
285                                  need_inval = 1;                                  need_inval = 1;
286                          if (low != NULL)                          if (low != NULL)
287                                  *low = mem->dev_bintrans_write_low[i];                                  *low = mem->dev_dyntrans_write_low[i];
288                          mem->dev_bintrans_write_low[i] = (uint64_t) -1;                          mem->dev_dyntrans_write_low[i] = (uint64_t) -1;
289    
290                          if (high != NULL)                          if (high != NULL)
291                                  *high = mem->dev_bintrans_write_high[i];                                  *high = mem->dev_dyntrans_write_high[i];
292                          mem->dev_bintrans_write_high[i] = 0;                          mem->dev_dyntrans_write_high[i] = 0;
293    
294                          if (!need_inval)                          if (!need_inval)
295                                  return;                                  return;
296    
                         if (cpu->machine->arch != ARCH_MIPS) {  
                                 /*  TODO!  */  
   
                                 return;  
                         }  
   
297                          /*  Invalidate any pages of this device that might                          /*  Invalidate any pages of this device that might
298                              be in the bintrans load/store cache, by marking                              be in the dyntrans load/store cache, by marking
299                              the pages read-only.  */                              the pages read-only.  */
300                            if (cpu->invalidate_translation_caches != NULL) {
301                          for (s=0; s<mem->dev_length[i]; s+=4096) {                                  for (s=0; s<mem->dev_length[i];
302                                  mips_invalidate_translation_caches_paddr(                                      s+=cpu->machine->arch_pagesize)
303                                      cpu, mem->dev_baseaddr[i] + s);                                          cpu->invalidate_translation_caches
304                          }                                              (cpu, mem->dev_baseaddr[i] + s,
305                                                JUST_MARK_AS_NON_WRITABLE
306                          /*  ... and invalidate the "fast_vaddr_to_hostaddr"                                              | INVALIDATE_PADDR);
                             cache entries that contain pointers to this  
                             device:  (NOTE: Device i, cache entry j)  */  
                         for (j=0; j<N_BINTRANS_VADDR_TO_HOST; j++) {  
                                 if (cpu->cd.mips.bintrans_data_hostpage[j] >=  
                                     mem->dev_bintrans_data[i] &&  
                                     cpu->cd.mips.bintrans_data_hostpage[j] <  
                                     mem->dev_bintrans_data[i] +  
                                     mem->dev_length[i])  
                                         cpu->cd.mips.  
                                             bintrans_data_hostpage[j] = NULL;  
307                          }                          }
308    
309                          return;                          return;
310                  }                  }
311          }          }
 #endif  
 }  
   
   
 /*  
  *  memory_device_register_statefunction():  
  *  
  *  TODO: Hm. This is semi-ugly. Should probably be rewritten/redesigned  
  *  some day.  
  */  
 void memory_device_register_statefunction(  
         struct memory *mem, void *extra,  
         int (*dev_f_state)(struct cpu *,  
             struct memory *, void *extra, int wf, int nr,  
             int *type, char **namep, void **data, size_t *len))  
 {  
         int i;  
   
         for (i=0; i<mem->n_mmapped_devices; i++)  
                 if (mem->dev_extra[i] == extra) {  
                         mem->dev_f_state[i] = dev_f_state;  
                         return;  
                 }  
   
         printf("memory_device_register_statefunction(): "  
             "couldn't find the device\n");  
         exit(1);  
312  }  }
313    
314    
# Line 356  void memory_device_register(struct memor Line 322  void memory_device_register(struct memor
322          uint64_t baseaddr, uint64_t len,          uint64_t baseaddr, uint64_t len,
323          int (*f)(struct cpu *,struct memory *,uint64_t,unsigned char *,          int (*f)(struct cpu *,struct memory *,uint64_t,unsigned char *,
324                  size_t,int,void *),                  size_t,int,void *),
325          void *extra, int flags, unsigned char *bintrans_data)          void *extra, int flags, unsigned char *dyntrans_data)
326  {  {
327          int i;          int i, newi = 0;
328    
329          if (mem->n_mmapped_devices >= MAX_DEVICES) {          if (mem->n_mmapped_devices >= MAX_DEVICES) {
330                  fprintf(stderr, "memory_device_register(): too many "                  fprintf(stderr, "memory_device_register(): too many "
# Line 366  void memory_device_register(struct memor Line 332  void memory_device_register(struct memor
332                  exit(1);                  exit(1);
333          }          }
334    
335          /*  Check for collisions:  */          /*
336             *  Figure out at which index to insert this device, and simultaneously
337             *  check for collisions:
338             */
339            newi = -1;
340          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
341                    if (i == 0 && baseaddr + len <= mem->dev_baseaddr[i])
342                            newi = i;
343                    if (i > 0 && baseaddr + len <= mem->dev_baseaddr[i] &&
344                        baseaddr >= mem->dev_endaddr[i-1])
345                            newi = i;
346                    if (i == mem->n_mmapped_devices - 1 &&
347                        baseaddr >= mem->dev_endaddr[i])
348                            newi = i + 1;
349    
350                  /*  If we are not colliding with device i, then continue:  */                  /*  If we are not colliding with device i, then continue:  */
351                  if (baseaddr + len <= mem->dev_baseaddr[i])                  if (baseaddr + len <= mem->dev_baseaddr[i])
352                          continue;                          continue;
353                  if (baseaddr >= mem->dev_baseaddr[i] + mem->dev_length[i])                  if (baseaddr >= mem->dev_endaddr[i])
354                          continue;                          continue;
355    
356                  fatal("\nWARNING! \"%s\" collides with device %i (\"%s\")!\n"                  fatal("\nERROR! \"%s\" collides with device %i (\"%s\")!\n",
                     "         Run-time behaviour will be undefined!\n\n",  
357                      device_name, i, mem->dev_name[i]);                      device_name, i, mem->dev_name[i]);
358                    exit(1);
359            }
360            if (mem->n_mmapped_devices == 0)
361                    newi = 0;
362            if (newi == -1) {
363                    fatal("INTERNAL ERROR\n");
364                    exit(1);
365            }
366    
367            if (verbose >= 2) {
368                    /*  (40 bits of physical address is displayed)  */
369                    debug("device at 0x%010"PRIx64": %s", (uint64_t) baseaddr,
370                        device_name);
371    
372                    if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
373                        && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
374                            fatal("\nWARNING: Device dyntrans access, but unaligned"
375                                " baseaddr 0x%"PRIx64".\n", (uint64_t) baseaddr);
376                    }
377    
378                    if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
379                            debug(" (dyntrans %s)",
380                                (flags & DM_DYNTRANS_WRITE_OK)? "R/W" : "R");
381                    }
382                    debug("\n");
383            }
384    
385            for (i=0; i<mem->n_mmapped_devices; i++) {
386                    if (dyntrans_data == mem->dev_dyntrans_data[i] &&
387                        mem->dev_flags[i] & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
388                        && flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
389                            fatal("ERROR: the data pointer used for dyntrans "
390                                "accesses must only be used once!\n");
391                            fatal("(%p cannot be used by '%s'; already in use by '"
392                                "%s')\n", dyntrans_data, device_name,
393                                mem->dev_name[i]);
394                            exit(1);
395                    }
396          }          }
397    
398          /*  (40 bits of physical address is displayed)  */          mem->n_mmapped_devices++;
399          debug("device %2i at 0x%010llx: %s",  
400              mem->n_mmapped_devices, (long long)baseaddr, device_name);          /*
401             *  YUCK! This is ugly. TODO: fix
402  #ifdef BINTRANS           */
403          if (flags & (MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK)          /*  Make space for the new entry:  */
404              && (baseaddr & 0xfff) != 0) {          memmove(&mem->dev_name[newi+1], &mem->dev_name[newi], sizeof(char *) *
405                  fatal("\nWARNING: Device bintrans access, but unaligned"              (MAX_DEVICES - newi - 1));
406                      " baseaddr 0x%llx.\n", (long long)baseaddr);          memmove(&mem->dev_baseaddr[newi+1], &mem->dev_baseaddr[newi],
407          }              sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
408            memmove(&mem->dev_endaddr[newi+1], &mem->dev_endaddr[newi],
409          if (flags & (MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK)) {              sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
410                  debug(" (bintrans %s)",          memmove(&mem->dev_length[newi+1], &mem->dev_length[newi],
411                      (flags & MEM_BINTRANS_WRITE_OK)? "R/W" : "R");              sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
412          }          memmove(&mem->dev_flags[newi+1], &mem->dev_flags[newi], sizeof(int) *
413  #endif              (MAX_DEVICES - newi - 1));
414          debug("\n");          memmove(&mem->dev_extra[newi+1], &mem->dev_extra[newi], sizeof(void *) *
415                (MAX_DEVICES - newi - 1));
416          mem->dev_name[mem->n_mmapped_devices] = strdup(device_name);          memmove(&mem->dev_f[newi+1], &mem->dev_f[newi], sizeof(void *) *
417          mem->dev_baseaddr[mem->n_mmapped_devices] = baseaddr;              (MAX_DEVICES - newi - 1));
418          mem->dev_length[mem->n_mmapped_devices] = len;          memmove(&mem->dev_dyntrans_data[newi+1], &mem->dev_dyntrans_data[newi],
419          mem->dev_flags[mem->n_mmapped_devices] = flags;              sizeof(void *) * (MAX_DEVICES - newi - 1));
420          mem->dev_bintrans_data[mem->n_mmapped_devices] = bintrans_data;          memmove(&mem->dev_dyntrans_write_low[newi+1],
421                &mem->dev_dyntrans_write_low[newi],
422                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
423            memmove(&mem->dev_dyntrans_write_high[newi+1],
424                &mem->dev_dyntrans_write_high[newi],
425                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
426    
427    
428            mem->dev_name[newi] = strdup(device_name);
429            mem->dev_baseaddr[newi] = baseaddr;
430            mem->dev_endaddr[newi] = baseaddr + len;
431            mem->dev_length[newi] = len;
432            mem->dev_flags[newi] = flags;
433            mem->dev_dyntrans_data[newi] = dyntrans_data;
434    
435          if (mem->dev_name[mem->n_mmapped_devices] == NULL) {          if (mem->dev_name[newi] == NULL) {
436                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
437                  exit(1);                  exit(1);
438          }          }
439    
440          if ((size_t)bintrans_data & 1) {          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
441                && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {
442                    fatal("\nERROR: Device dyntrans access, but dyntrans_data"
443                        " = NULL!\n");
444                    exit(1);
445            }
446    
447            if ((size_t)dyntrans_data & (sizeof(void *) - 1)) {
448                  fprintf(stderr, "memory_device_register():"                  fprintf(stderr, "memory_device_register():"
449                      " bintrans_data not aligned correctly\n");                      " dyntrans_data not aligned correctly (%p)\n",
450                        dyntrans_data);
451                  exit(1);                  exit(1);
452          }          }
453    
454  #ifdef BINTRANS          mem->dev_dyntrans_write_low[newi] = (uint64_t)-1;
455          mem->dev_bintrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1;          mem->dev_dyntrans_write_high[newi] = 0;
456          mem->dev_bintrans_write_high[mem->n_mmapped_devices] = 0;          mem->dev_f[newi] = f;
457  #endif          mem->dev_extra[newi] = extra;
         mem->dev_f[mem->n_mmapped_devices] = f;  
         mem->dev_extra[mem->n_mmapped_devices] = extra;  
         mem->n_mmapped_devices++;  
458    
459          if (baseaddr < mem->mmap_dev_minaddr)          if (baseaddr < mem->mmap_dev_minaddr)
460                  mem->mmap_dev_minaddr = baseaddr & ~0xfff;                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
461          if (baseaddr + len > mem->mmap_dev_maxaddr)          if (baseaddr + len > mem->mmap_dev_maxaddr)
462                  mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) | 0xfff) + 1;                  mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) |
463                        mem->dev_dyntrans_alignment) + 1;
464  }  }
465    
466    
# Line 454  void memory_device_remove(struct memory Line 489  void memory_device_remove(struct memory
489              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
490          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],
491              sizeof(uint64_t) * (MAX_DEVICES - i - 1));              sizeof(uint64_t) * (MAX_DEVICES - i - 1));
492            memmove(&mem->dev_endaddr[i], &mem->dev_endaddr[i+1],
493                sizeof(uint64_t) * (MAX_DEVICES - i - 1));
494          memmove(&mem->dev_length[i], &mem->dev_length[i+1], sizeof(uint64_t) *          memmove(&mem->dev_length[i], &mem->dev_length[i+1], sizeof(uint64_t) *
495              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
496          memmove(&mem->dev_flags[i], &mem->dev_flags[i+1], sizeof(int) *          memmove(&mem->dev_flags[i], &mem->dev_flags[i+1], sizeof(int) *
# Line 462  void memory_device_remove(struct memory Line 499  void memory_device_remove(struct memory
499              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
500          memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *          memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *
501              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
502          memmove(&mem->dev_f_state[i], &mem->dev_f_state[i+1], sizeof(void *) *          memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],
             (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_bintrans_data[i], &mem->dev_bintrans_data[i+1],  
503              sizeof(void *) * (MAX_DEVICES - i - 1));              sizeof(void *) * (MAX_DEVICES - i - 1));
504  #ifdef BINTRANS          memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low
505          memmove(&mem->dev_bintrans_write_low[i], &mem->dev_bintrans_write_low              [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));
506              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));          memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high
507          memmove(&mem->dev_bintrans_write_high[i], &mem->dev_bintrans_write_high              [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));
             [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));  
 #endif  
508  }  }
509    
510    
# Line 501  unsigned char *memory_paddr_to_hostaddr( Line 534  unsigned char *memory_paddr_to_hostaddr(
534          table = mem->pagetable;          table = mem->pagetable;
535          entry = (paddr >> shrcount) & mask;          entry = (paddr >> shrcount) & mask;
536    
537          /*  printf("   entry = %x\n", entry);  */          /*  printf("memory_paddr_to_hostaddr(): p=%16"PRIx64
538                " w=%i => entry=0x%x\n", (uint64_t) paddr, writeflag, entry);  */
539    
540          if (table[entry] == NULL) {          if (table[entry] == NULL) {
541                  size_t alloclen;                  size_t alloclen;
# Line 524  unsigned char *memory_paddr_to_hostaddr( Line 558  unsigned char *memory_paddr_to_hostaddr(
558                  /*  Anonymous mmap() should return zero-filled memory,                  /*  Anonymous mmap() should return zero-filled memory,
559                      try malloc + memset if mmap failed.  */                      try malloc + memset if mmap failed.  */
560                  table[entry] = (void *) mmap(NULL, alloclen,                  table[entry] = (void *) mmap(NULL, alloclen,
561                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
                     -1, 0);  
562                  if (table[entry] == NULL) {                  if (table[entry] == NULL) {
563                          table[entry] = malloc(alloclen);                          table[entry] = malloc(alloclen);
564                          if (table[entry] == NULL) {                          if (table[entry] == NULL) {
# Line 539  unsigned char *memory_paddr_to_hostaddr( Line 572  unsigned char *memory_paddr_to_hostaddr(
572          return (unsigned char *) table[entry];          return (unsigned char *) table[entry];
573  }  }
574    
575    
576    #define UPDATE_CHECKSUM(value) {                                        \
577                    internal_state -= 0x118c7771c0c0a77fULL;                \
578                    internal_state = ((internal_state + (value)) << 7) ^    \
579                        (checksum >> 11) ^ ((checksum - (value)) << 3) ^    \
580                        (internal_state - checksum) ^ ((value) - internal_state); \
581                    checksum ^= internal_state;                             \
582            }
583    
584    
585    /*
586     *  memory_checksum():
587     *
588     *  Calculate a 64-bit checksum of everything in a struct memory. This is
589     *  useful for tracking down bugs; an old (presumably working) version of
590     *  the emulator can be compared to a newer (buggy) version.
591     */
592    uint64_t memory_checksum(struct memory *mem)
593    {
594            uint64_t internal_state = 0x80624185376feff2ULL;
595            uint64_t checksum = 0xcb9a87d5c010072cULL;
596            const int n_entries = (1 << BITS_PER_PAGETABLE) - 1;
597            const size_t len = (1 << BITS_PER_MEMBLOCK) / sizeof(uint64_t);
598            size_t entry, i;
599    
600            for (entry=0; entry<=n_entries; entry++) {
601                    uint64_t **table = mem->pagetable;
602                    uint64_t *memblock = table[entry];
603    
604                    if (memblock == NULL) {
605                            UPDATE_CHECKSUM(0x1198ab7c8174a76fULL);
606                            continue;
607                    }
608    
609                    for (i=0; i<len; i++)
610                            UPDATE_CHECKSUM(memblock[i]);
611            }
612    
613            return checksum;
614    }
615    

Legend:
Removed from v.4  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26