/[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 32 by dpavlin, Mon Oct 8 16:20:58 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_rw.c,v 1.97 2006/09/07 11:44:01 debug Exp $   *  $Id: memory_rw.c,v 1.101 2007/02/10 14:04:51 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 81  int MEMORY_RW(struct cpu *cpu, struct me Line 81  int MEMORY_RW(struct cpu *cpu, struct me
81          no_exceptions = misc_flags & NO_EXCEPTIONS;          no_exceptions = misc_flags & NO_EXCEPTIONS;
82          cache = misc_flags & CACHE_FLAGS_MASK;          cache = misc_flags & CACHE_FLAGS_MASK;
83    
 #ifdef MEM_X86  
         /*  Real-mode wrap-around:  */  
         if (REAL_MODE && !(misc_flags & PHYSICAL)) {  
                 if ((vaddr & 0xffff) + len > 0x10000) {  
                         /*  Do one byte at a time:  */  
                         int res = 0;  
                         size_t i;  
                         for (i=0; i<len; i++)  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,  
                                     writeflag, misc_flags);  
                         return res;  
                 }  
         }  
   
         /*  Crossing a page boundary? Then do one byte at a time:  */  
         if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL)  
             && cpu->cd.x86.cr[0] & X86_CR0_PG) {  
                 /*  
                  *  For WRITES: Read ALL BYTES FIRST and write them back!!!  
                  *  Then do a write of all the new bytes. This is to make sure  
                  *  than both pages around the boundary are writable so that  
                  *  there is no "partial write" performed.  
                  */  
                 int res = 0;  
                 size_t i;  
                 if (writeflag == MEM_WRITE) {  
                         unsigned char tmp;  
                         for (i=0; i<len; i++) {  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,  
                                     MEM_READ, misc_flags);  
                                 if (!res)  
                                         return 0;  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,  
                                     MEM_WRITE, misc_flags);  
                                 if (!res)  
                                         return 0;  
                         }  
                         for (i=0; i<len; i++) {  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,  
                                     MEM_WRITE, misc_flags);  
                                 if (!res)  
                                         return 0;  
                         }  
                 } else {  
                         for (i=0; i<len; i++) {  
                                 /*  Do one byte at a time:  */  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,  
                                     writeflag, misc_flags);  
                                 if (!res) {  
                                         if (cache == CACHE_INSTRUCTION) {  
                                                 fatal("FAILED instruction "  
                                                     "fetch across page boundar"  
                                                     "y: todo. vaddr=0x%08x\n",  
                                                     (int)vaddr);  
                                                 cpu->running = 0;  
                                         }  
                                         return 0;  
                                 }  
                         }  
                 }  
                 return res;  
         }  
 #endif  /*  X86  */  
   
84    
85  #ifdef MEM_USERLAND  #ifdef MEM_USERLAND
86  #ifdef MEM_ALPHA  #ifdef MEM_ALPHA
# Line 159  int MEMORY_RW(struct cpu *cpu, struct me Line 95  int MEMORY_RW(struct cpu *cpu, struct me
95                  ok = cpu->translate_v2p(cpu, vaddr, &paddr,                  ok = cpu->translate_v2p(cpu, vaddr, &paddr,
96                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
97                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)
 #ifdef MEM_X86  
                     + (misc_flags & NO_SEGMENTATION)  
 #endif  
98  #ifdef MEM_ARM  #ifdef MEM_ARM
99                      + (misc_flags & MEMORY_USER_ACCESS)                      + (misc_flags & MEMORY_USER_ACCESS)
100  #endif  #endif
# Line 176  int MEMORY_RW(struct cpu *cpu, struct me Line 109  int MEMORY_RW(struct cpu *cpu, struct me
109                          return MEMORY_ACCESS_FAILED;                          return MEMORY_ACCESS_FAILED;
110          }          }
111    
   
 #ifdef MEM_X86  
         /*  DOS debugging :-)  */  
         if (!quiet_mode && !(misc_flags & PHYSICAL)) {  
                 if (paddr >= 0x400 && paddr <= 0x4ff)  
                         debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==  
                             MEM_WRITE? "writing to" : "reading from",  
                             (int)paddr);  
 #if 0  
                 if (paddr >= 0xf0000 && paddr <= 0xfffff)  
                         debug("{ BIOS ACCESS: %s 0x%x }\n",  
                             writeflag == MEM_WRITE? "writing to" :  
                             "reading from", (int)paddr);  
 #endif  
         }  
 #endif  
112  #endif  /*  !MEM_USERLAND  */  #endif  /*  !MEM_USERLAND  */
113    
114    
# Line 206  int MEMORY_RW(struct cpu *cpu, struct me Line 123  int MEMORY_RW(struct cpu *cpu, struct me
123                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
124                  int i, start, end, res;                  int i, start, end, res;
125    
126    #if 0
127    
128    TODO: The correct solution for this is to add RAM devices _around_ the
129    dangerous device. The solution below incurs a slowdown for _everything_,
130    not just the device in question.
131    
132                  /*                  /*
133                   *  Really really slow, but unfortunately necessary. This is                   *  Really really slow, but unfortunately necessary. This is
134                   *  to avoid the folowing scenario:                   *  to avoid the folowing scenario:
# Line 227  int MEMORY_RW(struct cpu *cpu, struct me Line 150  int MEMORY_RW(struct cpu *cpu, struct me
150                   *  TODO: Convert this into a quick (multi-level, 64-bit)                   *  TODO: Convert this into a quick (multi-level, 64-bit)
151                   *  address space lookup, to find dangerous pages.                   *  address space lookup, to find dangerous pages.
152                   */                   */
 #if 1  
153                  for (i=0; i<mem->n_mmapped_devices; i++)                  for (i=0; i<mem->n_mmapped_devices; i++)
154                          if (paddr >= (mem->devices[i].baseaddr & ~offset_mask)&&                          if (paddr >= (mem->devices[i].baseaddr & ~offset_mask)&&
155                              paddr <= ((mem->devices[i].endaddr-1)|offset_mask)){                              paddr <= ((mem->devices[i].endaddr-1)|offset_mask)){
# Line 306  int MEMORY_RW(struct cpu *cpu, struct me Line 228  int MEMORY_RW(struct cpu *cpu, struct me
228                                  if (res == 0)                                  if (res == 0)
229                                          res = -1;                                          res = -1;
230    
 #ifndef MEM_X86  
231                                  /*                                  /*
232                                   *  If accessing the memory mapped device                                   *  If accessing the memory mapped device
233                                   *  failed, then return with a DBE exception.                                   *  failed, then return with a DBE exception.
# Line 322  int MEMORY_RW(struct cpu *cpu, struct me Line 243  int MEMORY_RW(struct cpu *cpu, struct me
243  #endif  #endif
244                                          return MEMORY_ACCESS_FAILED;                                          return MEMORY_ACCESS_FAILED;
245                                  }                                  }
 #endif  
246                                  goto do_return_ok;                                  goto do_return_ok;
247                          }                          }
248    
# Line 373  int MEMORY_RW(struct cpu *cpu, struct me Line 293  int MEMORY_RW(struct cpu *cpu, struct me
293                  } else                  } else
294  #endif /* MIPS */  #endif /* MIPS */
295                  {                  {
296                          if (paddr >= mem->physical_max) {                          if (paddr >= mem->physical_max && !no_exceptions)
297                                  uint64_t offset, old_pc = cpu->pc;                                  memory_warn_about_unimplemented_addr
298                                  char *symbol;                                      (cpu, mem, writeflag, paddr, data, len);
   
                                 /*  This allows for example OS kernels to probe  
                                     memory a few KBs past the end of memory,  
                                     without giving too many warnings.  */  
                                 if (!quiet_mode && !no_exceptions && paddr >=  
                                     mem->physical_max + 0x40000) {  
                                         fatal("[ memory_rw(): writeflag=%i ",  
                                             writeflag);  
                                         if (writeflag) {  
                                                 unsigned int i;  
                                                 debug("data={", writeflag);  
                                                 if (len > 16) {  
                                                         int start2 = len-16;  
                                                         for (i=0; i<16; i++)  
                                                                 debug("%s%02x",  
                                                                     i?",":"",  
                                                                     data[i]);  
                                                         debug(" .. ");  
                                                         if (start2 < 16)  
                                                                 start2 = 16;  
                                                         for (i=start2; i<len;  
                                                             i++)  
                                                                 debug("%s%02x",  
                                                                     i?",":"",  
                                                                     data[i]);  
                                                 } else  
                                                         for (i=0; i<len; i++)  
                                                                 debug("%s%02x",  
                                                                     i?",":"",  
                                                                     data[i]);  
                                                 debug("}");  
                                         }  
   
                                         fatal(" paddr=0x%llx >= physical_max"  
                                             "; pc=", (long long)paddr);  
                                         if (cpu->is_32bit)  
                                                 fatal("0x%08x",(int)old_pc);  
                                         else  
                                                 fatal("0x%016llx",  
                                                     (long long)old_pc);  
                                         symbol = get_symbol_name(  
                                             &cpu->machine->symbol_context,  
                                             old_pc, &offset);  
                                         fatal(" <%s> ]\n",  
                                             symbol? symbol : " no symbol ");  
                                 }  
                         }  
299    
300                          if (writeflag == MEM_READ) {                          if (writeflag == MEM_READ) {
 #ifdef MEM_X86  
                                 /*  Reading non-existant memory on x86:  */  
                                 memset(data, 0xff, len);  
 #else  
301                                  /*  Return all zeroes? (Or 0xff? TODO)  */                                  /*  Return all zeroes? (Or 0xff? TODO)  */
302                                  memset(data, 0, len);                                  memset(data, 0, len);
 #endif  
303    
304  #ifdef MEM_MIPS  #ifdef MEM_MIPS
305                                  /*                                  /*

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

  ViewVC Help
Powered by ViewVC 1.1.26