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

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

revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory_mips_v2p.c,v 1.9 2006/08/12 11:43:13 debug Exp $   *  $Id: memory_mips_v2p.c,v 1.14 2006/10/14 23:47:37 debug Exp $
29   */   */
30    
31    
32  /*  /*
33   *  translate_v2p():   *  translate_v2p():
34   *   *
35   *  Don't call this function is userland_emul is non-NULL, or cpu is NULL.   *  Translate a virtual MIPS address to a physical address, by looking up the
36     *  address in the TLB. On failure, an exception is generated (except for the
37     *  case when FLAG_NOEXCEPTIONS is used).
38   *   *
39   *  TODO:  vpn2 is a bad name for R2K/R3K, as it is the actual framenumber.   *  Note: This function is long and hairy, it is included several times with
40     *        various defines set, to produce more or less optimized versions of
41     *        the function for different emulated CPU types.
42     *
43     *  V2P_MMU3K       Defined for R2000/R3000 emulation. If it is not defined,
44     *                  R4000+/MIPS32/MIPS64 is presumed.
45     *  V2P_MMU10K      This enables the use of 44 userspace bits, instead of 40.
46     *  V2P_MMU4100     VR41xx processors support 1 KB pages, so their page mask
47     *                  is slightly different. (The emulator only supports 4 KB
48     *                  pages, though.)
49     *  V2P_MMU8K       Not yet. (TODO.)
50     *
51     *
52     *  Note:  Unfortunately, the variable name vpn2 is poorly choosen for R2K/R3K,
53     *         since it actual contains the vpn.
54   *   *
55   *  Return values:   *  Return values:
56   *      0  Failure   *      0  Failure
# Line 55  int TRANSLATE_ADDRESS(struct cpu *cpu, u Line 71  int TRANSLATE_ADDRESS(struct cpu *cpu, u
71          const int x_64 = 0;          const int x_64 = 0;
72          const int n_tlbs = 64;          const int n_tlbs = 64;
73          const int pmask = 0xfff;          const int pmask = 0xfff;
74            uint64_t xuseg_top;             /*  Well, useg actually.  */
75  #else  #else
76  #ifdef V2P_MMU10K  #ifdef V2P_MMU10K
77          const uint64_t vpn2_mask = ENTRYHI_VPN2_MASK_R10K;          const uint64_t vpn2_mask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K;
78            uint64_t xuseg_top = ENTRYHI_VPN2_MASK_R10K | 0x1fffULL;
79  #else  #else
80  #ifdef V2P_MMU4100  #ifdef V2P_MMU4100
81  /* This is ugly  */          const uint64_t vpn2_mask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
         const uint64_t vpn2_mask = ENTRYHI_VPN2_MASK | 0x1800;  
82  #else  #else
83          const uint64_t vpn2_mask = ENTRYHI_VPN2_MASK;          const uint64_t vpn2_mask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK;
84  #endif  #endif
85            uint64_t xuseg_top = ENTRYHI_VPN2_MASK | 0x1fffULL;
86  #endif  #endif
87          int x_64;       /*  non-zero for 64-bit address space accesses  */          int x_64;       /*  non-zero for 64-bit address space accesses  */
88          int pageshift, n_tlbs;          int pageshift, n_tlbs;
# Line 89  int TRANSLATE_ADDRESS(struct cpu *cpu, u Line 107  int TRANSLATE_ADDRESS(struct cpu *cpu, u
107          status = cp0->reg[COP0_STATUS];          status = cp0->reg[COP0_STATUS];
108    
109          /*          /*
110           *  R4000 Address Translation:           *  MIPS R4000+ and MIPS64 Address Translation:
111           *           *
112           *  An address may be in one of the kernel segments, that           *  An address may be in one of the kernel segments, that are directly
113           *  are directly mapped, or the address can go through the           *  mapped to physical addresses, or the address needs to be looked up
114           *  TLBs to be turned into a physical address.           *  in the TLB entries.
115           *           *
116           *  KSU: EXL: ERL: X:  Name:   Range:           *  KSU: EXL: ERL: X:  Name:   Range:
117           *  ---- ---- ---- --  -----   ------           *  ---- ---- ---- --  -----   ------
# Line 114  int TRANSLATE_ADDRESS(struct cpu *cpu, u Line 132  int TRANSLATE_ADDRESS(struct cpu *cpu, u
132           *                                        unmapped, cached           *                                        unmapped, cached
133           *   00   x    x    0  kseg1   0xa0000000 - 0xbfffffff (0.5GB)           *   00   x    x    0  kseg1   0xa0000000 - 0xbfffffff (0.5GB)
134           *                                        unmapped, uncached           *                                        unmapped, uncached
135           *   00   x    x    0  ksseg   0xc0000000 - 0xdfffffff (0.5GB)           *   00   x    x    0  ksseg   0xc0000000 - 0xdfffffff (0.5GB) (via TLB)
136           *                                        (via TLB)           *   00   x    x    0  kseg3   0xe0000000 - 0xffffffff (0.5GB) (via TLB)
          *   00   x    x    0  kseg3   0xe0000000 - 0xffffffff (0.5GB)  
          *                                        (via TLB)  
137           *   00   x    x    1  xksuseg 0 - 0xffffffffff (1TB) (via TLB) (*)           *   00   x    x    1  xksuseg 0 - 0xffffffffff (1TB) (via TLB) (*)
138           *   00   x    x    1  xksseg  0x4000000000000000 - 0x400000ffffffffff           *   00   x    x    1  xksseg  0x4000000000000000 - 0x400000ffffffffff
139           *                                        (1TB)  (via TLB)           *                                        (1TB)  (via TLB)
140           *   00   x    x    1  xkphys  0x8000000000000000 - 0xbfffffffffffffff           *   00   x    x    1  xkphys  0x8000000000000000 - 0xbfffffffffffffff
          *                                        todo  
141           *   00   x    x    1  xkseg   0xc000000000000000 - 0xc00000ff7fffffff           *   00   x    x    1  xkseg   0xc000000000000000 - 0xc00000ff7fffffff
          *                                        todo  
142           *   00   x    x    1  ckseg0  0xffffffff80000000 - 0xffffffff9fffffff           *   00   x    x    1  ckseg0  0xffffffff80000000 - 0xffffffff9fffffff
          *                                        like kseg0  
143           *   00   x    x    1  ckseg1  0xffffffffa0000000 - 0xffffffffbfffffff           *   00   x    x    1  ckseg1  0xffffffffa0000000 - 0xffffffffbfffffff
          *                                        like kseg1  
144           *   00   x    x    1  cksseg  0xffffffffc0000000 - 0xffffffffdfffffff           *   00   x    x    1  cksseg  0xffffffffc0000000 - 0xffffffffdfffffff
          *                                        like ksseg  
145           *   00   x    x    1  ckseg3  0xffffffffe0000000 - 0xffffffffffffffff           *   00   x    x    1  ckseg3  0xffffffffe0000000 - 0xffffffffffffffff
146           *                                        like kseg2           *                                        like 0x80000000 - 0xffffffff
147           *           *
148           *  (*) = if ERL=1 then kuseg is not via TLB, but unmapped,           *  (*) = if ERL=1 then kuseg is not via TLB, but unmapped,
149           *  uncached physical memory.           *  uncached physical memory.
# Line 154  int TRANSLATE_ADDRESS(struct cpu *cpu, u Line 165  int TRANSLATE_ADDRESS(struct cpu *cpu, u
165          vaddr_asid = cp0->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK;          vaddr_asid = cp0->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK;
166          vaddr_vpn2 = vaddr & R2K3K_ENTRYHI_VPN_MASK;          vaddr_vpn2 = vaddr & R2K3K_ENTRYHI_VPN_MASK;
167  #else  #else
168          /*          /*  kx,sx,ux = 0 for 32-bit addressing, 1 for 64-bit addressing.  */
          *  R4000 and others:  
          *  
          *  kx,sx,ux = 0 for 32-bit addressing,  
          *  1 for 64-bit addressing.  
          */  
         n_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;  
   
169          ksu = (status & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT;          ksu = (status & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT;
170          if (status & (STATUS_EXL | STATUS_ERL))          if (status & (STATUS_EXL | STATUS_ERL))
171                  ksu = KSU_KERNEL;                  ksu = KSU_KERNEL;
172    
173          /*  Assume KSU_USER.  */          switch (ksu) {
174          x_64 = status & STATUS_UX;          case KSU_USER:
175                    x_64 = status & STATUS_UX;
176          if (ksu == KSU_KERNEL)                  break;
177            case KSU_KERNEL:
178                  x_64 = status & STATUS_KX;                  x_64 = status & STATUS_KX;
179          else if (ksu == KSU_SUPERVISOR)                  break;
180            case KSU_SUPERVISOR:
181                  x_64 = status & STATUS_SX;                  x_64 = status & STATUS_SX;
182                    /*  FALLTHROUGH, since supervisor address spaces are not
183                        really implemented yet.  */
184            default:fatal("memory_mips_v2p.c: ksu=%i not yet implemented yet\n",
185                        ksu);
186                    exit(1);
187            }
188    
189            n_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;
190    
191          /*  This suppresses a compiler warning:  */          /*  Having this here suppresses a compiler warning:  */
192          pageshift = 12;          pageshift = 12;
193    
194            /*  KUSEG: 0x00000000 - 0x7fffffff if ERL = 1 and KSU = kernel:  */
195            if (ksu == KSU_KERNEL && (status & STATUS_ERL) &&
196                vaddr <= 0x7fffffff) {
197                    *return_paddr = vaddr & 0x7fffffff;
198                    return 2;
199            }
200    
201          /*          /*
202           *  Physical addressing on R10000 etc:           *  XKPHYS: 0x8000000000000000 - 0xbfffffffffffffff
203           *           *
204           *  TODO: Probably only accessible in kernel mode.           *  TODO: Is the correct error generated if accessing XKPHYS from
205             *        usermode?
206           *           *
207           *  0x9000000080000000 = disable L2 cache (?)           *  TODO: Magic on SGI machines... Cache control, NUMA, etc.:
208           *  TODO:  Make this correct.           *        0x9000000080000000   = disable L2 cache (?)
209             *        0x90000000a0000000   = something on IP30?
210             *        0x92.... and 0x96... = NUMA on IP27
211           */           */
212          if ((vaddr >> 62) == 0x2) {          if (ksu == KSU_KERNEL && (vaddr & ENTRYHI_R_MASK) == ENTRYHI_R_XKPHYS) {
                 /*  
                  *  On IP30, addresses such as 0x900000001f600050 are used,  
                  *  but also things like 0x90000000a0000000.  (TODO)  
                  *  
                  *  On IP27 (and probably others), addresses such as  
                  *  0x92... and 0x96... have to do with NUMA stuff.  
                  */  
213                  *return_paddr = vaddr & (((uint64_t)1 << 44) - 1);                  *return_paddr = vaddr & (((uint64_t)1 << 44) - 1);
214                  return 2;                  return 2;
215          }          }
# Line 202  int TRANSLATE_ADDRESS(struct cpu *cpu, u Line 219  int TRANSLATE_ADDRESS(struct cpu *cpu, u
219          /*  vpn2 depends on pagemask, which is not fixed on R4000  */          /*  vpn2 depends on pagemask, which is not fixed on R4000  */
220  #endif  #endif
221    
222            /*  If 32-bit, truncate address and sign extend:  */
223            if (x_64 == 0) {
224                    vaddr = (int32_t) vaddr;
225                    xuseg_top = 0x7fffffff;
226                    /*  (Actually useg for R2000/R3000)  */
227            }
228    
229          if (vaddr <= 0x7fffffff)          if (vaddr <= xuseg_top) {
230                  use_tlb = 1;                  use_tlb = 1;
231          else {          } else {
 #if 1  
 /*  TODO: This should be removed, but it seems that other  
 bugs are triggered.  */  
                 /*  Sign-extend vaddr, if necessary:  */  
                 if ((vaddr >> 32) == 0 && vaddr & (uint32_t)0x80000000ULL)  
                         vaddr |= 0xffffffff00000000ULL;  
 #endif  
232                  if (ksu == KSU_KERNEL) {                  if (ksu == KSU_KERNEL) {
233                          /*  kseg0, kseg1:  */                          /*  kseg0, kseg1:  */
234                          if (vaddr >= (uint64_t)0xffffffff80000000ULL &&                          if (vaddr >= (uint64_t)0xffffffff80000000ULL &&
# Line 221  bugs are triggered.  */ Line 237  bugs are triggered.  */
237                                  return 2;                                  return 2;
238                          }                          }
239    
                         /*  TODO: supervisor stuff  */  
   
240                          /*  other segments:  */                          /*  other segments:  */
241                          use_tlb = 1;                          use_tlb = 1;
242                  } else                  } else {
243                          use_tlb = 0;                          use_tlb = 0;
244                    }
245          }          }
246    
247          if (use_tlb) {          if (use_tlb) {
# Line 237  bugs are triggered.  */ Line 252  bugs are triggered.  */
252                  int g_bit, v_bit, d_bit;                  int g_bit, v_bit, d_bit;
253                  uint64_t cached_hi, cached_lo0;                  uint64_t cached_hi, cached_lo0;
254                  uint64_t entry_vpn2 = 0, entry_asid, pfn;                  uint64_t entry_vpn2 = 0, entry_asid, pfn;
255                    int i_end;
256    
257                    i = cpu->cd.mips.last_written_tlb_index;
258                    i_end = i == 0? n_tlbs-1 : i - 1;
259    
260                  for (i=0; i<n_tlbs; i++) {                  /*  Scan all TLB entries:  */
261                    for (;;) {
262  #ifdef V2P_MMU3K  #ifdef V2P_MMU3K
263                          /*  R3000 or similar:  */                          /*  R3000 or similar:  */
264                          cached_hi = cp0->tlbs[i].hi;                          cached_hi = cp0->tlbs[i].hi;
# Line 381  bugs are triggered.  */ Line 401  bugs are triggered.  */
401                                          goto exception;                                          goto exception;
402                                  }                                  }
403                          }                          }
404    
405                            if (i == i_end)
406                                    break;
407    
408                            /*  Go to the next TLB entry:  */
409                            i ++;
410                            if (i == n_tlbs)
411                                    i = 0;
412                  }                  }
413          }          }
414    

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

  ViewVC Help
Powered by ViewVC 1.1.26