/[gxemul]/trunk/src/memory_rw.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_rw.c

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

revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 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_rw.c,v 1.75 2005/10/27 14:01:12 debug Exp $   *  $Id: memory_rw.c,v 1.82 2005/12/31 15:48:32 debug Exp $
29   *   *
30   *  Generic memory_rw(), with special hacks for specific CPU families.   *  Generic memory_rw(), with special hacks for specific CPU families.
31   *   *
# Line 48  Line 48 
48   *                      a placeholder for data when reading from memory   *                      a placeholder for data when reading from memory
49   *      len             the length of the 'data' buffer   *      len             the length of the 'data' buffer
50   *      writeflag       set to MEM_READ or MEM_WRITE   *      writeflag       set to MEM_READ or MEM_WRITE
51   *      cache_flags     CACHE_{NONE,DATA,INSTRUCTION} | other flags   *      misc_flags      CACHE_{NONE,DATA,INSTRUCTION} | other flags
52   *   *
53   *  If the address indicates access to a memory mapped device, that device'   *  If the address indicates access to a memory mapped device, that device'
54   *  read/write access function is called.   *  read/write access function is called.
# Line 66  Line 66 
66   *  (MEMORY_ACCESS_FAILED is 0.)   *  (MEMORY_ACCESS_FAILED is 0.)
67   */   */
68  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,
69          unsigned char *data, size_t len, int writeflag, int cache_flags)          unsigned char *data, size_t len, int writeflag, int misc_flags)
70  {  {
71  #ifdef MEM_ALPHA  #ifdef MEM_ALPHA
72          const int offset_mask = 0x1fff;          const int offset_mask = 0x1fff;
# Line 83  int MEMORY_RW(struct cpu *cpu, struct me Line 83  int MEMORY_RW(struct cpu *cpu, struct me
83  #ifdef MEM_MIPS  #ifdef MEM_MIPS
84          int bintrans_cached = cpu->machine->bintrans_enable;          int bintrans_cached = cpu->machine->bintrans_enable;
85  #endif  #endif
86          int bintrans_device_danger = 0;          int dyntrans_device_danger = 0;
87    
88          no_exceptions = cache_flags & NO_EXCEPTIONS;          no_exceptions = misc_flags & NO_EXCEPTIONS;
89          cache = cache_flags & CACHE_FLAGS_MASK;          cache = misc_flags & CACHE_FLAGS_MASK;
90    
91  #ifdef MEM_X86  #ifdef MEM_X86
92          /*  Real-mode wrap-around:  */          /*  Real-mode wrap-around:  */
93          if (REAL_MODE && !(cache_flags & PHYSICAL)) {          if (REAL_MODE && !(misc_flags & PHYSICAL)) {
94                  if ((vaddr & 0xffff) + len > 0x10000) {                  if ((vaddr & 0xffff) + len > 0x10000) {
95                          /*  Do one byte at a time:  */                          /*  Do one byte at a time:  */
96                          int res = 0, i;                          int res = 0;
97                            size_t i;
98                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
99                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
100                                      writeflag, cache_flags);                                      writeflag, misc_flags);
101                          return res;                          return res;
102                  }                  }
103          }          }
104    
105          /*  Crossing a page boundary? Then do one byte at a time:  */          /*  Crossing a page boundary? Then do one byte at a time:  */
106          if ((vaddr & 0xfff) + len > 0x1000 && !(cache_flags & PHYSICAL)          if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL)
107              && cpu->cd.x86.cr[0] & X86_CR0_PG) {              && cpu->cd.x86.cr[0] & X86_CR0_PG) {
108                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!
109                      Then do a write of all the new bytes. This is to make sure                      Then do a write of all the new bytes. This is to make sure
110                      than both pages around the boundary are writable so we don't                      than both pages around the boundary are writable so we don't
111                      do a partial write.  */                      do a partial write.  */
112                  int res = 0, i;                  int res = 0;
113                    size_t i;
114                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
115                          unsigned char tmp;                          unsigned char tmp;
116                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
117                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
118                                      MEM_READ, cache_flags);                                      MEM_READ, misc_flags);
119                                  if (!res)                                  if (!res)
120                                          return 0;                                          return 0;
121                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
122                                      MEM_WRITE, cache_flags);                                      MEM_WRITE, misc_flags);
123                                  if (!res)                                  if (!res)
124                                          return 0;                                          return 0;
125                          }                          }
126                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
127                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
128                                      MEM_WRITE, cache_flags);                                      MEM_WRITE, misc_flags);
129                                  if (!res)                                  if (!res)
130                                          return 0;                                          return 0;
131                          }                          }
# Line 131  int MEMORY_RW(struct cpu *cpu, struct me Line 133  int MEMORY_RW(struct cpu *cpu, struct me
133                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
134                                  /*  Do one byte at a time:  */                                  /*  Do one byte at a time:  */
135                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
136                                      writeflag, cache_flags);                                      writeflag, misc_flags);
137                                  if (!res) {                                  if (!res) {
138                                          if (cache == CACHE_INSTRUCTION) {                                          if (cache == CACHE_INSTRUCTION) {
139                                                  fatal("FAILED instruction "                                                  fatal("FAILED instruction "
# Line 184  int MEMORY_RW(struct cpu *cpu, struct me Line 186  int MEMORY_RW(struct cpu *cpu, struct me
186          }          }
187  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
188    
189          if (cache_flags & PHYSICAL || cpu->translate_address == NULL) {          if (misc_flags & PHYSICAL || cpu->translate_address == NULL) {
190                  paddr = vaddr;                  paddr = vaddr;
   
191  #ifdef MEM_ALPHA  #ifdef MEM_ALPHA
192                  /*  paddr &= 0x1fffffff;  For testalpha  */                  /*  paddr &= 0x1fffffff;  For testalpha  */
193                  paddr &= 0x000003ffffffffffULL;                  paddr &= 0x000003ffffffffffULL;
194  #endif  #endif
   
 #ifdef MEM_IA64  
                 /*  For testia64  */  
                 paddr &= 0x3fffffff;  
 #endif  
   
 #ifdef MEM_PPC  
                 if (cpu->cd.ppc.bits == 32)  
                         paddr &= 0xffffffff;  
 #endif  
   
 #ifdef MEM_SH  
                 paddr &= 0xffffffff;  
 #endif  
195          } else {          } else {
196                  ok = cpu->translate_address(cpu, vaddr, &paddr,                  ok = cpu->translate_address(cpu, vaddr, &paddr,
197                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
198                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)
199  #ifdef MEM_X86  #ifdef MEM_X86
200                      + (cache_flags & NO_SEGMENTATION)                      + (misc_flags & NO_SEGMENTATION)
201  #endif  #endif
202  #ifdef MEM_ARM  #ifdef MEM_ARM
203                      + (cache_flags & MEMORY_USER_ACCESS)                      + (misc_flags & MEMORY_USER_ACCESS)
204  #endif  #endif
205                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));
206                  /*  If the translation caused an exception, or was invalid in                  /*  If the translation caused an exception, or was invalid in
# Line 226  int MEMORY_RW(struct cpu *cpu, struct me Line 213  int MEMORY_RW(struct cpu *cpu, struct me
213    
214  #ifdef MEM_X86  #ifdef MEM_X86
215          /*  DOS debugging :-)  */          /*  DOS debugging :-)  */
216          if (!quiet_mode && !(cache_flags & PHYSICAL)) {          if (!quiet_mode && !(misc_flags & PHYSICAL)) {
217                  if (paddr >= 0x400 && paddr <= 0x4ff)                  if (paddr >= 0x400 && paddr <= 0x4ff)
218                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==
219                              MEM_WRITE? "writing to" : "reading from",                              MEM_WRITE? "writing to" : "reading from",
# Line 282  have_paddr: Line 269  have_paddr:
269          /*          /*
270           *  Memory mapped device?           *  Memory mapped device?
271           *           *
272           *  TODO: this is utterly slow.           *  TODO: if paddr < base, but len enough, then the device should
273           *  TODO2: if paddr<base, but len enough, then we should write           *  still be written to!
          *  to a device to  
274           */           */
275          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {
276                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
277                  int i, start, res;                  int i, start, end, res;
278    
279                  /*                  /*
280                   *  Really really slow, but unfortunately necessary. This is                   *  Really really slow, but unfortunately necessary. This is
# Line 298  have_paddr: Line 284  have_paddr:
284                   *      b) offsets 0x124..0x777 are a device                   *      b) offsets 0x124..0x777 are a device
285                   *                   *
286                   *      1) a read is done from offset 0x100. the page is                   *      1) a read is done from offset 0x100. the page is
287                   *         added to the bintrans system as a "RAM" page                   *         added to the dyntrans system as a "RAM" page
288                   *      2) a bintranslated read is done from offset 0x200,                   *      2) a dyntranslated read is done from offset 0x200,
289                   *         which should access the device, but since the                   *         which should access the device, but since the
290                   *         entire page is added, it will access non-existant                   *         entire page is added, it will access non-existant
291                   *         RAM instead, without warning.                   *         RAM instead, without warning.
292                   *                   *
293                   *  Setting bintrans_device_danger = 1 on accesses which are                   *  Setting dyntrans_device_danger = 1 on accesses which are
294                   *  on _any_ offset on pages that are device mapped avoids                   *  on _any_ offset on pages that are device mapped avoids
295                   *  this problem, but it is probably not very fast.                   *  this problem, but it is probably not very fast.
296                     *
297                     *  TODO: Convert this into a quick (multi-level, 64-bit)
298                     *  address space lookup, to find dangerous pages.
299                   */                   */
300    #if 1
301                  for (i=0; i<mem->n_mmapped_devices; i++)                  for (i=0; i<mem->n_mmapped_devices; i++)
302                          if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&                          if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&
303                              paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) {                              paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) {
304                                  bintrans_device_danger = 1;                                  dyntrans_device_danger = 1;
305                                  break;                                  break;
306                          }                          }
307    #endif
308    
309                  i = start = mem->last_accessed_device;                  start = 0; end = mem->n_mmapped_devices - 1;
310                    i = mem->last_accessed_device;
311    
312                  /*  Scan through all devices:  */                  /*  Scan through all devices:  */
313                  do {                  do {
# Line 329  have_paddr: Line 321  have_paddr:
321                                          len = mem->dev_length[i] - paddr;                                          len = mem->dev_length[i] - paddr;
322    
323                                  if (cpu->update_translation_table != NULL &&                                  if (cpu->update_translation_table != NULL &&
324                                      mem->dev_flags[i] & MEM_DYNTRANS_OK) {                                      !(ok & MEMORY_NOT_FULL_PAGE) &&
325                                        mem->dev_flags[i] & DM_DYNTRANS_OK) {
326                                          int wf = writeflag == MEM_WRITE? 1 : 0;                                          int wf = writeflag == MEM_WRITE? 1 : 0;
327                                          unsigned char *host_addr;                                          unsigned char *host_addr;
328    
329                                          if (!(mem->dev_flags[i] &                                          if (!(mem->dev_flags[i] &
330                                              MEM_DYNTRANS_WRITE_OK))                                              DM_DYNTRANS_WRITE_OK))
331                                                  wf = 0;                                                  wf = 0;
332    
333                                          if (writeflag && wf) {                                          if (writeflag && wf) {
# Line 353  have_paddr: Line 346  have_paddr:
346                                          }                                          }
347    
348                                          if (mem->dev_flags[i] &                                          if (mem->dev_flags[i] &
349                                              MEM_EMULATED_RAM) {                                              DM_EMULATED_RAM) {
350                                                  /*  MEM_WRITE to force the page                                                  /*  MEM_WRITE to force the page
351                                                      to be allocated, if it                                                      to be allocated, if it
352                                                      wasn't already  */                                                      wasn't already  */
# Line 378  have_paddr: Line 371  have_paddr:
371    
372                                  res = 0;                                  res = 0;
373                                  if (!no_exceptions || (mem->dev_flags[i] &                                  if (!no_exceptions || (mem->dev_flags[i] &
374                                      MEM_READING_HAS_NO_SIDE_EFFECTS))                                      DM_READS_HAVE_NO_SIDE_EFFECTS))
375                                          res = mem->dev_f[i](cpu, mem, paddr,                                          res = mem->dev_f[i](cpu, mem, paddr,
376                                              data, len, writeflag,                                              data, len, writeflag,
377                                              mem->dev_extra[i]);                                              mem->dev_extra[i]);
# Line 414  have_paddr: Line 407  have_paddr:
407                                  goto do_return_ok;                                  goto do_return_ok;
408                          }                          }
409    
410                          i ++;                          if (paddr < mem->dev_baseaddr[i])
411                          if (i == mem->n_mmapped_devices)                                  end = i - 1;
412                                  i = 0;                          if (paddr >= mem->dev_endaddr[i])
413                  } while (i != start);                                  start = i + 1;
414                            i = (start + end) >> 1;
415                    } while (start <= end);
416          }          }
417    
418    
# Line 429  have_paddr: Line 424  have_paddr:
424          switch (cpu->cd.mips.cpu_type.mmu_model) {          switch (cpu->cd.mips.cpu_type.mmu_model) {
425          case MMU3K:          case MMU3K:
426                  /*  if not uncached addess  (TODO: generalize this)  */                  /*  if not uncached addess  (TODO: generalize this)  */
427                  if (!(cache_flags & PHYSICAL) && cache != CACHE_NONE &&                  if (!(misc_flags & PHYSICAL) && cache != CACHE_NONE &&
428                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&
429                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {
430                          if (memory_cache_R3000(cpu, cache, paddr,                          if (memory_cache_R3000(cpu, cache, paddr,
# Line 461  have_paddr: Line 456  have_paddr:
456                  {                  {
457                          if (paddr >= mem->physical_max) {                          if (paddr >= mem->physical_max) {
458                                  char *symbol;                                  char *symbol;
                                 uint64_t old_pc;  
459                                  uint64_t offset;                                  uint64_t offset;
   
460  #ifdef MEM_MIPS  #ifdef MEM_MIPS
461                                  old_pc = cpu->cd.mips.pc_last;                                  uint64_t old_pc = cpu->cd.mips.pc_last;
462  #else  #else
463                                  /*  Default instruction size on most                                  uint64_t old_pc = cpu->pc;
                                     RISC archs is 32 bits:  */  
                                 old_pc = cpu->pc - sizeof(uint32_t);  
464  #endif  #endif
465    
466                                  /*  This allows for example OS kernels to probe                                  /*  This allows for example OS kernels to probe
# Line 587  have_paddr: Line 578  have_paddr:
578    
579          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);
580    
581          if (cpu->update_translation_table != NULL && !bintrans_device_danger          if (cpu->update_translation_table != NULL && !dyntrans_device_danger
582  #ifndef MEM_MIPS  #ifndef MEM_MIPS
583  /*          && !(cache_flags & MEMORY_USER_ACCESS)  */  /*          && !(misc_flags & MEMORY_USER_ACCESS)  */
584  #ifndef MEM_USERLAND  #ifndef MEM_USERLAND
585              && !(ok & MEMORY_NOT_FULL_PAGE)              && !(ok & MEMORY_NOT_FULL_PAGE)
586  #endif  #endif
# Line 597  have_paddr: Line 588  have_paddr:
588              && !no_exceptions)              && !no_exceptions)
589                  cpu->update_translation_table(cpu, vaddr & ~offset_mask,                  cpu->update_translation_table(cpu, vaddr & ~offset_mask,
590                      memblock + (offset & ~offset_mask),                      memblock + (offset & ~offset_mask),
591                      (cache_flags & MEMORY_USER_ACCESS) |                      (misc_flags & MEMORY_USER_ACCESS) |
592  #ifndef MEM_MIPS  #ifndef MEM_MIPS
593                      (cache == CACHE_INSTRUCTION? TLB_CODE : 0) |                      (cache == CACHE_INSTRUCTION? TLB_CODE : 0) |
594  #endif  #endif
595  #if 0  #if !defined(MEM_MIPS) && !defined(MEM_USERLAND)
596                      (cache == CACHE_INSTRUCTION?                      (cache == CACHE_INSTRUCTION?
597                          (writeflag == MEM_WRITE? 1 : 0)                          (writeflag == MEM_WRITE? 1 : 0) : ok - 1),
                         : ok - 1),  
598  #else  #else
599                      (writeflag == MEM_WRITE? 1 : 0),                      (writeflag == MEM_WRITE? 1 : 0),
600  #endif  #endif
601                      paddr & ~offset_mask);                      paddr & ~offset_mask);
602    
603          /*  Invalidate code translations for the page we are writing to.  */          /*  Invalidate code translations for the page we are writing to.  */
604          if (writeflag == MEM_WRITE &&          if (writeflag == MEM_WRITE && cpu->invalidate_code_translation != NULL)
             cpu->invalidate_code_translation != NULL)  
605                  cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);                  cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);
606    
607          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {

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

  ViewVC Help
Powered by ViewVC 1.1.26