/* alpha_mmu.c - Alpha memory management simulator Copyright (c) 2003-2006, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. This module contains the routines for ReadB,W,L,Q - read aligned virtual ReadAccL,Q - read aligned virtual, special access check ReadPB,W,L,Q - read aligned physical WriteB,W,L,Q - write aligned virtual WriteAccL,Q - write aligned virtual, special access check WritePB,W,L,Q - write aligned physical The TLB is organized for optimum lookups and is broken up into three fields: tag VA<42:13> for an 8KB page system pte PTE<31:0>, <31:16> are zero; FOE, FOR, FOW stored inverted pfn PFN<31:0> left shifted by page size The inversion of FOE, FOR, FOW means that all checked bits must be one for a reference to proceed. All Alpha implementations provide support for a 43b superpage for Unix, and a 32b superpage for NT: 43b superpage 0xFFFFFC0000000000:0xFFFFFDFFFFFFFFFF 32b superpage 0xFFFFFFFF80000000:0xFFFFFFFFBFFFFFFF */ #include "alpha_defs.h" extern t_uint64 trans_i (t_uint64 va); extern t_uint64 trans_d (t_uint64 va, uint32 acc); extern t_uint64 *M; extern t_uint64 p1; extern uint32 pal_mode, dmapen; extern uint32 cm_eacc, cm_racc, cm_wacc; extern jmp_buf save_env; extern UNIT cpu_unit; /* Read virtual aligned Inputs: va = virtual address Output: returned data, right justified */ t_uint64 ReadB (t_uint64 va) { t_uint64 pa; if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */ else pa = va; return ReadPB (pa); } t_uint64 ReadW (t_uint64 va) { t_uint64 pa; if (va & 1) ABORT1 (va, EXC_ALIGN); /* must be W aligned */ if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */ else pa = va; return ReadPW (pa); } t_uint64 ReadL (t_uint64 va) { t_uint64 pa; if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */ if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */ else pa = va; return ReadPL (pa); } t_uint64 ReadQ (t_uint64 va) { t_uint64 pa; if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */ if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */ else pa = va; return ReadPQ (pa); } /* Read with generalized access controls - used by PALcode */ t_uint64 ReadAccL (t_uint64 va, uint32 acc) { t_uint64 pa; if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */ if (dmapen) pa = trans_d (va, acc); /* mapping on? */ else pa = va; return ReadPL (pa); } t_uint64 ReadAccQ (t_uint64 va, uint32 acc) { t_uint64 pa; if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */ if (dmapen) pa = trans_d (va, acc); /* mapping on? */ else pa = va; return ReadPQ (pa); } /* Read instruction */ uint32 ReadI (t_uint64 va) { t_uint64 pa; if (!pal_mode) pa = trans_i (va); /* mapping on? */ else pa = va; return (uint32) ReadPL (pa); } /* Write virtual aligned Inputs: va = virtual address val = data to be written, right justified in 32b or 64b Output: none */ void WriteB (t_uint64 va, t_uint64 dat) { t_uint64 pa; if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */ else pa = va; WritePB (pa, dat); return; } void WriteW (t_uint64 va, t_uint64 dat) { t_uint64 pa; if (va & 1) ABORT1 (va, EXC_ALIGN); /* must be W aligned */ if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */ else pa = va; WritePW (pa, dat); return; } void WriteL (t_uint64 va, t_uint64 dat) { t_uint64 pa; if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */ if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */ else pa = va; WritePL (pa, dat); return; } void WriteQ (t_uint64 va, t_uint64 dat) { t_uint64 pa; if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */ if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */ else pa = va; WritePQ (pa, dat); return; } /* Write with generalized access controls - used by PALcode */ void WriteAccL (t_uint64 va, t_uint64 dat, uint32 acc) { t_uint64 pa; if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */ if (dmapen) pa = trans_d (va, acc); /* mapping on? */ else pa = va; WritePL (pa, dat); return; } void WriteAccQ (t_uint64 va, t_uint64 dat, uint32 acc) { t_uint64 pa; if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */ if (dmapen) pa = trans_d (va, acc); /* mapping on? */ else pa = va; WritePQ (pa, dat); return; } /* Read and write physical aligned - access point to I/O */ INLINE t_uint64 ReadPB (t_uint64 pa) { t_uint64 val; if (ADDR_IS_MEM (pa)) { uint32 bo = ((uint32) pa) & 07; return (((M[pa >> 3] >> (bo << 3))) & M8); } if (ReadIO (pa, &val, L_BYTE)) return val; return 0; } INLINE t_uint64 ReadPW (t_uint64 pa) { t_uint64 val; if (ADDR_IS_MEM (pa)) { uint32 bo = ((uint32) pa) & 06; return (((M[pa >> 3] >> (bo << 3))) & M16); } if (ReadIO (pa, &val, L_WORD)) return val; return 0; } INLINE t_uint64 ReadPL (t_uint64 pa) { t_uint64 val; if (ADDR_IS_MEM (pa)) { if (pa & 4) return (((M[pa >> 3] >> 32)) & M32); return ((M[pa >> 3]) & M32); } if (ReadIO (pa, &val, L_LONG)) return val; return 0; } INLINE t_uint64 ReadPQ (t_uint64 pa) { t_uint64 val; if (ADDR_IS_MEM (pa)) return M[pa >> 3]; if (ReadIO (pa, &val, L_QUAD)) return val; return 0; } INLINE void WritePB (t_uint64 pa, t_uint64 dat) { dat = dat & M8; if (ADDR_IS_MEM (pa)) { uint32 bo = ((uint32) pa) & 07; M[pa >> 3] = (M[pa >> 3] & ~(((t_uint64) M8) << (bo << 3))) | (dat << (bo << 3)); } else WriteIO (pa, dat, L_BYTE); return; } INLINE void WritePW (t_uint64 pa, t_uint64 dat) { dat = dat & M16; if (ADDR_IS_MEM (pa)) { uint32 bo = ((uint32) pa) & 07; M[pa >> 3] = (M[pa >> 3] & ~(((t_uint64) M16) << (bo << 3))) | (dat << (bo << 3)); } else WriteIO (pa, dat, L_WORD); return; } INLINE void WritePL (t_uint64 pa, t_uint64 dat) { dat = dat & M32; if (ADDR_IS_MEM (pa)) { if (pa & 4) M[pa >> 3] = (M[pa >> 3] & M32) | (dat << 32); else M[pa >> 3] = (M[pa >> 3] & ~((t_uint64) M32)) | dat; } else WriteIO (pa, dat, L_LONG); return; } INLINE void WritePQ (t_uint64 pa, t_uint64 dat) { if (ADDR_IS_MEM (pa)) M[pa >> 3] = dat; else WriteIO (pa, dat, L_QUAD); return; }