/[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 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# 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.182 2005/11/22 16:26:36 debug Exp $
29   *   *
30   *  Functions for handling the memory of an emulated machine.   *  Functions for handling the memory of an emulated machine.
31   */   */
# Line 59  extern volatile int single_step; Line 59  extern volatile int single_step;
59   */   */
60  uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)  uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
61  {  {
62          int i;          int i, byte_order = cpu->byte_order;
63          uint64_t x = 0;          uint64_t x = 0;
64    
65            if (len & MEM_PCI_LITTLE_ENDIAN) {
66                    len &= ~MEM_PCI_LITTLE_ENDIAN;
67                    byte_order = EMUL_LITTLE_ENDIAN;
68            }
69    
70          /*  Switch byte order for incoming data, if necessary:  */          /*  Switch byte order for incoming data, if necessary:  */
71          if (cpu->byte_order == EMUL_BIG_ENDIAN)          if (byte_order == EMUL_BIG_ENDIAN)
72                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
73                          x <<= 8;                          x <<= 8;
74                          x |= buf[i];                          x |= buf[i];
# Line 89  uint64_t memory_readmax64(struct cpu *cp Line 94  uint64_t memory_readmax64(struct cpu *cp
94  void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,  void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,
95          uint64_t data)          uint64_t data)
96  {  {
97          int i;          int i, byte_order = cpu->byte_order;
98    
99          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)          if (len & MEM_PCI_LITTLE_ENDIAN) {
100                    len &= ~MEM_PCI_LITTLE_ENDIAN;
101                    byte_order = EMUL_LITTLE_ENDIAN;
102            }
103    
104            if (byte_order == EMUL_LITTLE_ENDIAN)
105                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
106                          buf[i] = data & 255;                          buf[i] = data & 255;
107                          data >>= 8;                          data >>= 8;
# Line 108  void memory_writemax64(struct cpu *cpu, Line 118  void memory_writemax64(struct cpu *cpu,
118   *  zeroed_alloc():   *  zeroed_alloc():
119   *   *
120   *  Allocates a block of memory using mmap(), and if that fails, try   *  Allocates a block of memory using mmap(), and if that fails, try
121   *  malloc() + memset().   *  malloc() + memset(). The returned memory block contains only zeroes.
122   */   */
123  void *zeroed_alloc(size_t s)  void *zeroed_alloc(size_t s)
124  {  {
# Line 132  void *zeroed_alloc(size_t s) Line 142  void *zeroed_alloc(size_t s)
142   *  This function creates a new memory object. An emulated machine needs one   *  This function creates a new memory object. An emulated machine needs one
143   *  of these.   *  of these.
144   */   */
145  struct memory *memory_new(uint64_t physical_max)  struct memory *memory_new(uint64_t physical_max, int arch)
146  {  {
147          struct memory *mem;          struct memory *mem;
148          int bits_per_pagetable = BITS_PER_PAGETABLE;          int bits_per_pagetable = BITS_PER_PAGETABLE;
# Line 157  struct memory *memory_new(uint64_t physi Line 167  struct memory *memory_new(uint64_t physi
167          }          }
168    
169          mem->physical_max = physical_max;          mem->physical_max = physical_max;
170            mem->dev_dyntrans_alignment = 4095;
171            if (arch == ARCH_ALPHA)
172                    mem->dev_dyntrans_alignment = 8191;
173    
174          s = entries_per_pagetable * sizeof(void *);          s = entries_per_pagetable * sizeof(void *);
175    
# Line 253  char *memory_conv_to_string(struct cpu * Line 266  char *memory_conv_to_string(struct cpu *
266    
267    
268  /*  /*
269   *  memory_device_bintrans_access():   *  memory_device_dyntrans_access():
270   *   *
271   *  Get the lowest and highest bintrans access since last time.   *  Get the lowest and highest dyntrans (or bintrans) access since last time.
272   */   */
273  void memory_device_bintrans_access(struct cpu *cpu, struct memory *mem,  void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,
274          void *extra, uint64_t *low, uint64_t *high)          void *extra, uint64_t *low, uint64_t *high)
275  {  {
 #ifdef BINTRANS  
276          int i, j;          int i, j;
277          size_t s;          size_t s;
278          int need_inval = 0;          int need_inval = 0;
# Line 271  void memory_device_bintrans_access(struc Line 283  void memory_device_bintrans_access(struc
283    
284          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
285                  if (mem->dev_extra[i] == extra &&                  if (mem->dev_extra[i] == extra &&
286                      mem->dev_bintrans_data[i] != NULL) {                      mem->dev_dyntrans_data[i] != NULL) {
287                          if (mem->dev_bintrans_write_low[i] != (uint64_t) -1)                          if (mem->dev_dyntrans_write_low[i] != (uint64_t) -1)
288                                  need_inval = 1;                                  need_inval = 1;
289                          if (low != NULL)                          if (low != NULL)
290                                  *low = mem->dev_bintrans_write_low[i];                                  *low = mem->dev_dyntrans_write_low[i];
291                          mem->dev_bintrans_write_low[i] = (uint64_t) -1;                          mem->dev_dyntrans_write_low[i] = (uint64_t) -1;
292    
293                          if (high != NULL)                          if (high != NULL)
294                                  *high = mem->dev_bintrans_write_high[i];                                  *high = mem->dev_dyntrans_write_high[i];
295                          mem->dev_bintrans_write_high[i] = 0;                          mem->dev_dyntrans_write_high[i] = 0;
296    
297                          if (!need_inval)                          if (!need_inval)
298                                  return;                                  return;
299    
                         if (cpu->machine->arch != ARCH_MIPS) {  
                                 /*  TODO!  */  
   
                                 return;  
                         }  
   
300                          /*  Invalidate any pages of this device that might                          /*  Invalidate any pages of this device that might
301                              be in the bintrans load/store cache, by marking                              be in the dyntrans load/store cache, by marking
302                              the pages read-only.  */                              the pages read-only.  */
303                            if (cpu->invalidate_translation_caches != NULL) {
304                          for (s=0; s<mem->dev_length[i]; s+=4096) {                                  for (s=0; s<mem->dev_length[i];
305                                  mips_invalidate_translation_caches_paddr(                                      s+=cpu->machine->arch_pagesize)
306                                      cpu, mem->dev_baseaddr[i] + s);                                          cpu->invalidate_translation_caches
307                                                (cpu, mem->dev_baseaddr[i] + s,
308                                                JUST_MARK_AS_NON_WRITABLE
309                                                | INVALIDATE_PADDR);
310                          }                          }
311    
312                          /*  ... and invalidate the "fast_vaddr_to_hostaddr"                          if (cpu->machine->arch == ARCH_MIPS) {
313                              cache entries that contain pointers to this                                  /*
314                              device:  (NOTE: Device i, cache entry j)  */                                   *  ... and invalidate the "fast_vaddr_to_
315                          for (j=0; j<N_BINTRANS_VADDR_TO_HOST; j++) {                                   *  hostaddr" cache entries that contain
316                                  if (cpu->cd.mips.bintrans_data_hostpage[j] >=                                   *  pointers to this device:  (NOTE: Device i,
317                                      mem->dev_bintrans_data[i] &&                                   *  cache entry j)
318                                      cpu->cd.mips.bintrans_data_hostpage[j] <                                   */
319                                      mem->dev_bintrans_data[i] +                                  for (j=0; j<N_BINTRANS_VADDR_TO_HOST; j++) {
320                                      mem->dev_length[i])                                          if (cpu->cd.
321                                          cpu->cd.mips.                                              mips.bintrans_data_hostpage[j] >=
322                                              bintrans_data_hostpage[j] = NULL;                                              mem->dev_dyntrans_data[i] &&
323                                                cpu->cd.mips.
324                                                bintrans_data_hostpage[j] <
325                                                mem->dev_dyntrans_data[i] +
326                                                mem->dev_length[i])
327                                                    cpu->cd.mips.
328                                                        bintrans_data_hostpage[j]
329                                                        = NULL;
330                                    }
331                          }                          }
   
332                          return;                          return;
333                  }                  }
334          }          }
 #endif  
335  }  }
336    
337    
# Line 356  void memory_device_register(struct memor Line 371  void memory_device_register(struct memor
371          uint64_t baseaddr, uint64_t len,          uint64_t baseaddr, uint64_t len,
372          int (*f)(struct cpu *,struct memory *,uint64_t,unsigned char *,          int (*f)(struct cpu *,struct memory *,uint64_t,unsigned char *,
373                  size_t,int,void *),                  size_t,int,void *),
374          void *extra, int flags, unsigned char *bintrans_data)          void *extra, int flags, unsigned char *dyntrans_data)
375  {  {
376          int i;          int i;
377    
# Line 383  void memory_device_register(struct memor Line 398  void memory_device_register(struct memor
398          debug("device %2i at 0x%010llx: %s",          debug("device %2i at 0x%010llx: %s",
399              mem->n_mmapped_devices, (long long)baseaddr, device_name);              mem->n_mmapped_devices, (long long)baseaddr, device_name);
400    
401  #ifdef BINTRANS          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
402          if (flags & (MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK)              && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
403              && (baseaddr & 0xfff) != 0) {                  fatal("\nWARNING: Device dyntrans access, but unaligned"
                 fatal("\nWARNING: Device bintrans access, but unaligned"  
404                      " baseaddr 0x%llx.\n", (long long)baseaddr);                      " baseaddr 0x%llx.\n", (long long)baseaddr);
405          }          }
406    
407          if (flags & (MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK)) {          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
408                  debug(" (bintrans %s)",                  debug(" (dyntrans %s)",
409                      (flags & MEM_BINTRANS_WRITE_OK)? "R/W" : "R");                      (flags & DM_DYNTRANS_WRITE_OK)? "R/W" : "R");
410          }          }
 #endif  
411          debug("\n");          debug("\n");
412    
413          mem->dev_name[mem->n_mmapped_devices] = strdup(device_name);          mem->dev_name[mem->n_mmapped_devices] = strdup(device_name);
414          mem->dev_baseaddr[mem->n_mmapped_devices] = baseaddr;          mem->dev_baseaddr[mem->n_mmapped_devices] = baseaddr;
415            mem->dev_endaddr[mem->n_mmapped_devices] = baseaddr + len;
416          mem->dev_length[mem->n_mmapped_devices] = len;          mem->dev_length[mem->n_mmapped_devices] = len;
417          mem->dev_flags[mem->n_mmapped_devices] = flags;          mem->dev_flags[mem->n_mmapped_devices] = flags;
418          mem->dev_bintrans_data[mem->n_mmapped_devices] = bintrans_data;          mem->dev_dyntrans_data[mem->n_mmapped_devices] = dyntrans_data;
419    
420          if (mem->dev_name[mem->n_mmapped_devices] == NULL) {          if (mem->dev_name[mem->n_mmapped_devices] == NULL) {
421                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
422                  exit(1);                  exit(1);
423          }          }
424    
425          if ((size_t)bintrans_data & 1) {          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
426                && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {
427                    fatal("\nERROR: Device dyntrans access, but dyntrans_data"
428                        " = NULL!\n");
429                    exit(1);
430            }
431    
432            if ((size_t)dyntrans_data & (sizeof(void *) - 1)) {
433                  fprintf(stderr, "memory_device_register():"                  fprintf(stderr, "memory_device_register():"
434                      " bintrans_data not aligned correctly\n");                      " dyntrans_data not aligned correctly (%p)\n",
435                        dyntrans_data);
436                  exit(1);                  exit(1);
437          }          }
438    
439  #ifdef BINTRANS          mem->dev_dyntrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1;
440          mem->dev_bintrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1;          mem->dev_dyntrans_write_high[mem->n_mmapped_devices] = 0;
         mem->dev_bintrans_write_high[mem->n_mmapped_devices] = 0;  
 #endif  
441          mem->dev_f[mem->n_mmapped_devices] = f;          mem->dev_f[mem->n_mmapped_devices] = f;
442          mem->dev_extra[mem->n_mmapped_devices] = extra;          mem->dev_extra[mem->n_mmapped_devices] = extra;
443          mem->n_mmapped_devices++;          mem->n_mmapped_devices++;
444    
445          if (baseaddr < mem->mmap_dev_minaddr)          if (baseaddr < mem->mmap_dev_minaddr)
446                  mem->mmap_dev_minaddr = baseaddr & ~0xfff;                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
447          if (baseaddr + len > mem->mmap_dev_maxaddr)          if (baseaddr + len > mem->mmap_dev_maxaddr)
448                  mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) | 0xfff) + 1;                  mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) |
449                        mem->dev_dyntrans_alignment) + 1;
450  }  }
451    
452    
# Line 464  void memory_device_remove(struct memory Line 485  void memory_device_remove(struct memory
485              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
486          memmove(&mem->dev_f_state[i], &mem->dev_f_state[i+1], sizeof(void *) *          memmove(&mem->dev_f_state[i], &mem->dev_f_state[i+1], sizeof(void *) *
487              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
488          memmove(&mem->dev_bintrans_data[i], &mem->dev_bintrans_data[i+1],          memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],
489              sizeof(void *) * (MAX_DEVICES - i - 1));              sizeof(void *) * (MAX_DEVICES - i - 1));
490  #ifdef BINTRANS          memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low
         memmove(&mem->dev_bintrans_write_low[i], &mem->dev_bintrans_write_low  
491              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));
492          memmove(&mem->dev_bintrans_write_high[i], &mem->dev_bintrans_write_high          memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high
493              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));
 #endif  
494  }  }
495    
496    
# Line 501  unsigned char *memory_paddr_to_hostaddr( Line 520  unsigned char *memory_paddr_to_hostaddr(
520          table = mem->pagetable;          table = mem->pagetable;
521          entry = (paddr >> shrcount) & mask;          entry = (paddr >> shrcount) & mask;
522    
523          /*  printf("   entry = %x\n", entry);  */          /*  printf("memory_paddr_to_hostaddr(): p=%16llx w=%i => entry=0x%x\n",
524                (long long)paddr, writeflag, entry);  */
525    
526          if (table[entry] == NULL) {          if (table[entry] == NULL) {
527                  size_t alloclen;                  size_t alloclen;

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

  ViewVC Help
Powered by ViewVC 1.1.26