/[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 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  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.187 2006/01/14 12:51:59 debug Exp $   *  $Id: memory.c,v 1.201 2006/12/30 13:30:52 debug Exp $
29   *   *
30   *  Functions for handling the memory of an emulated machine.   *  Functions for handling the memory of an emulated machine.
31   */   */
# Line 43  Line 43 
43    
44    
45  extern int verbose;  extern int verbose;
46    extern int quiet_mode;
47    
48    
49  /*  /*
# Line 120  void *zeroed_alloc(size_t s) Line 121  void *zeroed_alloc(size_t s)
121  {  {
122          void *p = mmap(NULL, s, PROT_READ | PROT_WRITE,          void *p = mmap(NULL, s, PROT_READ | PROT_WRITE,
123              MAP_ANON | MAP_PRIVATE, -1, 0);              MAP_ANON | MAP_PRIVATE, -1, 0);
124    
125          if (p == NULL) {          if (p == NULL) {
126    #if 1
127                    fprintf(stderr, "zeroed_alloc(): mmap() failed. This should"
128                        " not usually happen. If you can reproduce this, then"
129                        " please contact me with details about your run-time"
130                        " environment.\n");
131                    exit(1);
132    #else
133                  p = malloc(s);                  p = malloc(s);
134                  if (p == NULL) {                  if (p == NULL) {
135                          fprintf(stderr, "out of memory\n");                          fprintf(stderr, "out of memory\n");
136                          exit(1);                          exit(1);
137                  }                  }
138                  memset(p, 0, s);                  memset(p, 0, s);
139    #endif
140          }          }
141    
142          return p;          return p;
143  }  }
144    
# Line 270  char *memory_conv_to_string(struct cpu * Line 281  char *memory_conv_to_string(struct cpu *
281  void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,  void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,
282          void *extra, uint64_t *low, uint64_t *high)          void *extra, uint64_t *low, uint64_t *high)
283  {  {
         int i, j;  
284          size_t s;          size_t s;
285          int need_inval = 0;          int i, need_inval = 0;
286    
287          /*  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.
288              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
289              called too often.  */              called too often.  */
290    
291          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
292                  if (mem->dev_extra[i] == extra &&                  if (mem->devices[i].extra == extra &&
293                      mem->dev_flags[i] & DM_DYNTRANS_WRITE_OK &&                      mem->devices[i].flags & DM_DYNTRANS_WRITE_OK &&
294                      mem->dev_dyntrans_data[i] != NULL) {                      mem->devices[i].dyntrans_data != NULL) {
295                          if (mem->dev_dyntrans_write_low[i] != (uint64_t) -1)                          if (mem->devices[i].dyntrans_write_low != (uint64_t) -1)
296                                  need_inval = 1;                                  need_inval = 1;
297                          if (low != NULL)                          if (low != NULL)
298                                  *low = mem->dev_dyntrans_write_low[i];                                  *low = mem->devices[i].dyntrans_write_low;
299                          mem->dev_dyntrans_write_low[i] = (uint64_t) -1;                          mem->devices[i].dyntrans_write_low = (uint64_t) -1;
300    
301                          if (high != NULL)                          if (high != NULL)
302                                  *high = mem->dev_dyntrans_write_high[i];                                  *high = mem->devices[i].dyntrans_write_high;
303                          mem->dev_dyntrans_write_high[i] = 0;                          mem->devices[i].dyntrans_write_high = 0;
304    
305                          if (!need_inval)                          if (!need_inval)
306                                  return;                                  return;
# Line 299  void memory_device_dyntrans_access(struc Line 309  void memory_device_dyntrans_access(struc
309                              be in the dyntrans load/store cache, by marking                              be in the dyntrans load/store cache, by marking
310                              the pages read-only.  */                              the pages read-only.  */
311                          if (cpu->invalidate_translation_caches != NULL) {                          if (cpu->invalidate_translation_caches != NULL) {
312                                  for (s=0; s<mem->dev_length[i];                                  for (s = *low; s <= *high;
313                                      s+=cpu->machine->arch_pagesize)                                      s += cpu->machine->arch_pagesize)
314                                          cpu->invalidate_translation_caches                                          cpu->invalidate_translation_caches
315                                              (cpu, mem->dev_baseaddr[i] + s,                                              (cpu, mem->devices[i].baseaddr + s,
316                                              JUST_MARK_AS_NON_WRITABLE                                              JUST_MARK_AS_NON_WRITABLE
317                                              | INVALIDATE_PADDR);                                              | INVALIDATE_PADDR);
318                          }                          }
319    
                         if (cpu->machine->arch == ARCH_MIPS) {  
                                 /*  
                                  *  ... and invalidate the "fast_vaddr_to_  
                                  *  hostaddr" 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_dyntrans_data[i] &&  
                                             cpu->cd.mips.  
                                             bintrans_data_hostpage[j] <  
                                             mem->dev_dyntrans_data[i] +  
                                             mem->dev_length[i])  
                                                 cpu->cd.mips.  
                                                     bintrans_data_hostpage[j]  
                                                     = NULL;  
                                 }  
                         }  
320                          return;                          return;
321                  }                  }
322          }          }
# Line 334  void memory_device_dyntrans_access(struc Line 324  void memory_device_dyntrans_access(struc
324    
325    
326  /*  /*
327     *  memory_device_update_data():
328     *
329     *  Update a device' dyntrans data pointer.
330     *
331     *  SUPER-IMPORTANT NOTE: Anyone who changes a dyntrans data pointer while
332     *  things are running also needs to invalidate all CPUs' address translation
333     *  caches!  Otherwise, these may contain old pointers to the old data.
334     */
335    void memory_device_update_data(struct memory *mem, void *extra,
336            unsigned char *data)
337    {
338            int i;
339    
340            for (i=0; i<mem->n_mmapped_devices; i++) {
341                    if (mem->devices[i].extra != extra)
342                            continue;
343    
344                    mem->devices[i].dyntrans_data = data;
345                    mem->devices[i].dyntrans_write_low = (uint64_t)-1;
346                    mem->devices[i].dyntrans_write_high = 0;
347            }
348    }
349    
350    
351    /*
352   *  memory_device_register():   *  memory_device_register():
353   *   *
354   *  Register a (memory mapped) device by adding it to the dev_* fields of a   *  Register a memory mapped device.
  *  memory struct.  
355   */   */
356  void memory_device_register(struct memory *mem, const char *device_name,  void memory_device_register(struct memory *mem, const char *device_name,
357          uint64_t baseaddr, uint64_t len,          uint64_t baseaddr, uint64_t len,
# Line 347  void memory_device_register(struct memor Line 361  void memory_device_register(struct memor
361  {  {
362          int i, newi = 0;          int i, newi = 0;
363    
         if (mem->n_mmapped_devices >= MAX_DEVICES) {  
                 fprintf(stderr, "memory_device_register(): too many "  
                     "devices registered, cannot register '%s'\n", device_name);  
                 exit(1);  
         }  
   
364          /*          /*
365           *  Figure out at which index to insert this device, and simultaneously           *  Figure out at which index to insert this device, and simultaneously
366           *  check for collisions:           *  check for collisions:
367           */           */
368          newi = -1;          newi = -1;
369          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
370                  if (i == 0 && baseaddr + len <= mem->dev_baseaddr[i])                  if (i == 0 && baseaddr + len <= mem->devices[i].baseaddr)
371                          newi = i;                          newi = i;
372                  if (i > 0 && baseaddr + len <= mem->dev_baseaddr[i] &&                  if (i > 0 && baseaddr + len <= mem->devices[i].baseaddr &&
373                      baseaddr >= mem->dev_endaddr[i-1])                      baseaddr >= mem->devices[i-1].endaddr)
374                          newi = i;                          newi = i;
375                  if (i == mem->n_mmapped_devices - 1 &&                  if (i == mem->n_mmapped_devices - 1 &&
376                      baseaddr >= mem->dev_endaddr[i])                      baseaddr >= mem->devices[i].endaddr)
377                          newi = i + 1;                          newi = i + 1;
378    
379                  /*  If we are not colliding with device i, then continue:  */                  /*  If this is not colliding with device i, then continue:  */
380                  if (baseaddr + len <= mem->dev_baseaddr[i])                  if (baseaddr + len <= mem->devices[i].baseaddr)
381                          continue;                          continue;
382                  if (baseaddr >= mem->dev_endaddr[i])                  if (baseaddr >= mem->devices[i].endaddr)
383                          continue;                          continue;
384    
385                  fatal("\nERROR! \"%s\" collides with device %i (\"%s\")!\n",                  fatal("\nERROR! \"%s\" collides with device %i (\"%s\")!\n",
386                      device_name, i, mem->dev_name[i]);                      device_name, i, mem->devices[i].name);
387                  exit(1);                  exit(1);
388          }          }
389          if (mem->n_mmapped_devices == 0)          if (mem->n_mmapped_devices == 0)
# Line 387  void memory_device_register(struct memor Line 395  void memory_device_register(struct memor
395    
396          if (verbose >= 2) {          if (verbose >= 2) {
397                  /*  (40 bits of physical address is displayed)  */                  /*  (40 bits of physical address is displayed)  */
398                  debug("device at 0x%010llx: %s", (long long)baseaddr,                  debug("device at 0x%010"PRIx64": %s", (uint64_t) baseaddr,
399                      device_name);                      device_name);
400    
401                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
402                      && (baseaddr & mem->dev_dyntrans_alignment) != 0) {                      && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
403                          fatal("\nWARNING: Device dyntrans access, but unaligned"                          fatal("\nWARNING: Device dyntrans access, but unaligned"
404                              " baseaddr 0x%llx.\n", (long long)baseaddr);                              " baseaddr 0x%"PRIx64".\n", (uint64_t) baseaddr);
405                  }                  }
406    
407                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
# Line 404  void memory_device_register(struct memor Line 412  void memory_device_register(struct memor
412          }          }
413    
414          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
415                  if (dyntrans_data == mem->dev_dyntrans_data[i] &&                  if (dyntrans_data == mem->devices[i].dyntrans_data &&
416                      mem->dev_flags[i] & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)                      mem->devices[i].flags&(DM_DYNTRANS_OK|DM_DYNTRANS_WRITE_OK)
417                      && flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {                      && flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
418                          fatal("ERROR: the data pointer used for dyntrans "                          fatal("ERROR: the data pointer used for dyntrans "
419                              "accesses must only be used once!\n");                              "accesses must only be used once!\n");
420                          fatal("(%p cannot be used by '%s'; already in use by '"                          fatal("(%p cannot be used by '%s'; already in use by '"
421                              "%s')\n", dyntrans_data, device_name,                              "%s')\n", dyntrans_data, device_name,
422                              mem->dev_name[i]);                              mem->devices[i].name);
423                          exit(1);                          exit(1);
424                  }                  }
425          }          }
426    
427          mem->n_mmapped_devices++;          mem->n_mmapped_devices++;
428    
429          /*          mem->devices = realloc(mem->devices, sizeof(struct memory_device)
430           *  YUCK! This is ugly. TODO: fix              * mem->n_mmapped_devices);
431           */          if (mem->devices == NULL) {
432                    fprintf(stderr, "out of memory\n");
433                    exit(1);
434            }
435    
436          /*  Make space for the new entry:  */          /*  Make space for the new entry:  */
437          memmove(&mem->dev_name[newi+1], &mem->dev_name[newi], sizeof(char *) *          if (newi + 1 != mem->n_mmapped_devices)
438              (MAX_DEVICES - newi - 1));                  memmove(&mem->devices[newi+1], &mem->devices[newi],
439          memmove(&mem->dev_baseaddr[newi+1], &mem->dev_baseaddr[newi],                      sizeof(struct memory_device)
440              sizeof(uint64_t) * (MAX_DEVICES - newi - 1));                      * (mem->n_mmapped_devices - newi - 1));
441          memmove(&mem->dev_endaddr[newi+1], &mem->dev_endaddr[newi],  
442              sizeof(uint64_t) * (MAX_DEVICES - newi - 1));          mem->devices[newi].name = strdup(device_name);
443          memmove(&mem->dev_length[newi+1], &mem->dev_length[newi],          mem->devices[newi].baseaddr = baseaddr;
444              sizeof(uint64_t) * (MAX_DEVICES - newi - 1));          mem->devices[newi].endaddr = baseaddr + len;
445          memmove(&mem->dev_flags[newi+1], &mem->dev_flags[newi], sizeof(int) *          mem->devices[newi].length = len;
446              (MAX_DEVICES - newi - 1));          mem->devices[newi].flags = flags;
447          memmove(&mem->dev_extra[newi+1], &mem->dev_extra[newi], sizeof(void *) *          mem->devices[newi].dyntrans_data = dyntrans_data;
             (MAX_DEVICES - newi - 1));  
         memmove(&mem->dev_f[newi+1], &mem->dev_f[newi], sizeof(void *) *  
             (MAX_DEVICES - newi - 1));  
         memmove(&mem->dev_dyntrans_data[newi+1], &mem->dev_dyntrans_data[newi],  
             sizeof(void *) * (MAX_DEVICES - newi - 1));  
         memmove(&mem->dev_dyntrans_write_low[newi+1],  
             &mem->dev_dyntrans_write_low[newi],  
             sizeof(uint64_t) * (MAX_DEVICES - newi - 1));  
         memmove(&mem->dev_dyntrans_write_high[newi+1],  
             &mem->dev_dyntrans_write_high[newi],  
             sizeof(uint64_t) * (MAX_DEVICES - newi - 1));  
   
   
         mem->dev_name[newi] = strdup(device_name);  
         mem->dev_baseaddr[newi] = baseaddr;  
         mem->dev_endaddr[newi] = baseaddr + len;  
         mem->dev_length[newi] = len;  
         mem->dev_flags[newi] = flags;  
         mem->dev_dyntrans_data[newi] = dyntrans_data;  
448    
449          if (mem->dev_name[newi] == NULL) {          if (mem->devices[newi].name == NULL) {
450                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
451                  exit(1);                  exit(1);
452          }          }
# Line 472  void memory_device_register(struct memor Line 465  void memory_device_register(struct memor
465                  exit(1);                  exit(1);
466          }          }
467    
468          mem->dev_dyntrans_write_low[newi] = (uint64_t)-1;          mem->devices[newi].dyntrans_write_low = (uint64_t)-1;
469          mem->dev_dyntrans_write_high[newi] = 0;          mem->devices[newi].dyntrans_write_high = 0;
470          mem->dev_f[newi] = f;          mem->devices[newi].f = f;
471          mem->dev_extra[newi] = extra;          mem->devices[newi].extra = extra;
472    
473          if (baseaddr < mem->mmap_dev_minaddr)          if (baseaddr < mem->mmap_dev_minaddr)
474                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
475          if (baseaddr + len > mem->mmap_dev_maxaddr)          if (baseaddr + len > mem->mmap_dev_maxaddr)
476                  mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) |                  mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) |
477                      mem->dev_dyntrans_alignment) + 1;                      mem->dev_dyntrans_alignment) + 1;
478    
479            if (newi < mem->last_accessed_device)
480                    mem->last_accessed_device ++;
481  }  }
482    
483    
484  /*  /*
485   *  memory_device_remove():   *  memory_device_remove():
486   *   *
487   *  Unregister a (memory mapped) device from a memory struct.   *  Unregister a memory mapped device from a memory object.
488   */   */
489  void memory_device_remove(struct memory *mem, int i)  void memory_device_remove(struct memory *mem, int i)
490  {  {
491          if (i < 0 || i >= mem->n_mmapped_devices) {          if (i < 0 || i >= mem->n_mmapped_devices) {
492                  fatal("memory_device_remove(): invalid device number %i\n", i);                  fatal("memory_device_remove(): invalid device number %i\n", i);
493                  return;                  exit(1);
494          }          }
495    
496          mem->n_mmapped_devices --;          mem->n_mmapped_devices --;
# Line 502  void memory_device_remove(struct memory Line 498  void memory_device_remove(struct memory
498          if (i == mem->n_mmapped_devices)          if (i == mem->n_mmapped_devices)
499                  return;                  return;
500    
501          /*          memmove(&mem->devices[i], &mem->devices[i+1],
502           *  YUCK! This is ugly. TODO: fix              sizeof(struct memory_device) * (mem->n_mmapped_devices - i));
          */  
503    
504          memmove(&mem->dev_name[i], &mem->dev_name[i+1], sizeof(char *) *          if (i <= mem->last_accessed_device)
505              (MAX_DEVICES - i - 1));                  mem->last_accessed_device --;
506          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],          if (mem->last_accessed_device < 0)
507              sizeof(uint64_t) * (MAX_DEVICES - i - 1));                  mem->last_accessed_device = 0;
         memmove(&mem->dev_endaddr[i], &mem->dev_endaddr[i+1],  
             sizeof(uint64_t) * (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_length[i], &mem->dev_length[i+1], sizeof(uint64_t) *  
             (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_flags[i], &mem->dev_flags[i+1], sizeof(int) *  
             (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_extra[i], &mem->dev_extra[i+1], sizeof(void *) *  
             (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *  
             (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],  
             sizeof(void *) * (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low  
             [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));  
         memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high  
             [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));  
508  }  }
509    
510    
# Line 539  void memory_device_remove(struct memory Line 518  void memory_device_remove(struct memory
518  /*  /*
519   *  memory_paddr_to_hostaddr():   *  memory_paddr_to_hostaddr():
520   *   *
521   *  Translate a physical address into a host address.   *  Translate a physical address into a host address. The usual way to call
522     *  this function is to make sure that paddr is page aligned, which will result
523     *  in the host _page_ corresponding to that address.
524   *   *
525   *  Return value is a pointer to a host memblock, or NULL on failure.   *  Return value is a pointer to the address in the host, or NULL on failure.
526   *  On reads, a NULL return value should be interpreted as reading all zeroes.   *  On reads, a NULL return value should be interpreted as reading all zeroes.
527   */   */
528  unsigned char *memory_paddr_to_hostaddr(struct memory *mem,  unsigned char *memory_paddr_to_hostaddr(struct memory *mem,
# Line 551  unsigned char *memory_paddr_to_hostaddr( Line 532  unsigned char *memory_paddr_to_hostaddr(
532          int entry;          int entry;
533          const int mask = (1 << BITS_PER_PAGETABLE) - 1;          const int mask = (1 << BITS_PER_PAGETABLE) - 1;
534          const int shrcount = MAX_BITS - BITS_PER_PAGETABLE;          const int shrcount = MAX_BITS - BITS_PER_PAGETABLE;
535            unsigned char *hostptr;
536    
537          table = mem->pagetable;          table = mem->pagetable;
538          entry = (paddr >> shrcount) & mask;          entry = (paddr >> shrcount) & mask;
539    
540          /*  printf("memory_paddr_to_hostaddr(): p=%16llx w=%i => entry=0x%x\n",          /*  printf("memory_paddr_to_hostaddr(): p=%16"PRIx64
541              (long long)paddr, writeflag, entry);  */              " w=%i => entry=0x%x\n", (uint64_t) paddr, writeflag, entry);  */
542    
543          if (table[entry] == NULL) {          if (table[entry] == NULL) {
544                  size_t alloclen;                  size_t alloclen;
# Line 590  unsigned char *memory_paddr_to_hostaddr( Line 572  unsigned char *memory_paddr_to_hostaddr(
572                  }                  }
573          }          }
574    
575          return (unsigned char *) table[entry];          hostptr = (unsigned char *) table[entry];
576    
577            if (hostptr != NULL)
578                    hostptr += (paddr & ((1 << BITS_PER_MEMBLOCK) - 1));
579    
580            return hostptr;
581    }
582    
583    
584    #define UPDATE_CHECKSUM(value) {                                        \
585                    internal_state -= 0x118c7771c0c0a77fULL;                \
586                    internal_state = ((internal_state + (value)) << 7) ^    \
587                        (checksum >> 11) ^ ((checksum - (value)) << 3) ^    \
588                        (internal_state - checksum) ^ ((value) - internal_state); \
589                    checksum ^= internal_state;                             \
590            }
591    
592    
593    /*
594     *  memory_checksum():
595     *
596     *  Calculate a 64-bit checksum of everything in a struct memory. This is
597     *  useful for tracking down bugs; an old (presumably working) version of
598     *  the emulator can be compared to a newer (buggy) version.
599     */
600    uint64_t memory_checksum(struct memory *mem)
601    {
602            uint64_t internal_state = 0x80624185376feff2ULL;
603            uint64_t checksum = 0xcb9a87d5c010072cULL;
604            const int n_entries = (1 << BITS_PER_PAGETABLE) - 1;
605            const size_t len = (1 << BITS_PER_MEMBLOCK) / sizeof(uint64_t);
606            size_t entry, i;
607    
608            for (entry=0; entry<=n_entries; entry++) {
609                    uint64_t **table = mem->pagetable;
610                    uint64_t *memblock = table[entry];
611    
612                    if (memblock == NULL) {
613                            UPDATE_CHECKSUM(0x1198ab7c8174a76fULL);
614                            continue;
615                    }
616    
617                    for (i=0; i<len; i++)
618                            UPDATE_CHECKSUM(memblock[i]);
619            }
620    
621            return checksum;
622    }
623    
624    
625    /*
626     *  memory_warn_about_unimplemented_addr():
627     *
628     *  Called from memory_rw whenever memory outside of the physical address space
629     *  is accessed (and quiet_mode isn't set).
630     */
631    void memory_warn_about_unimplemented_addr(struct cpu *cpu, struct memory *mem,
632            int writeflag, uint64_t paddr, uint8_t *data, size_t len)
633    {
634            uint64_t offset, old_pc = cpu->pc;
635            char *symbol;
636    
637            /*
638             *  This allows guest OS kernels to probe memory a few KBs past the
639             *  end of memory, without giving too many warnings.
640             */
641            if (paddr < mem->physical_max + 0x40000)
642                    return;
643    
644            if (!cpu->machine->halt_on_nonexistant_memaccess && quiet_mode)
645                    return;
646    
647            fatal("[ memory_rw(): %s ", writeflag? "write":"read");
648    
649            if (writeflag) {
650                    unsigned int i;
651                    debug("data={", writeflag);
652                    if (len > 16) {
653                            int start2 = len-16;
654                            for (i=0; i<16; i++)
655                                    debug("%s%02x", i?",":"", data[i]);
656                            debug(" .. ");
657                            if (start2 < 16)
658                                    start2 = 16;
659                            for (i=start2; i<len; i++)
660                                    debug("%s%02x", i?",":"", data[i]);
661                    } else
662                            for (i=0; i<len; i++)
663                                    debug("%s%02x", i?",":"", data[i]);
664                    debug("} ");
665            }
666    
667            fatal("paddr=0x%llx >= physical_max; pc=", (long long)paddr);
668            if (cpu->is_32bit)
669                    fatal("0x%08"PRIx32, (uint32_t) old_pc);
670            else
671                    fatal("0x%016"PRIx64, (uint64_t) old_pc);
672            symbol = get_symbol_name(&cpu->machine->symbol_context,
673                old_pc, &offset);
674            fatal(" <%s> ]\n", symbol? symbol : " no symbol ");
675    
676            if (cpu->machine->halt_on_nonexistant_memaccess) {
677                    /*  TODO: Halt in a nicer way. Not possible with the
678                        current dyntrans system...  */
679                    exit(1);
680            }
681  }  }
682    

Legend:
Removed from v.22  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26