|
|
| version 1.10, 2004/02/04 13:24:35 | version 1.12, 2004/02/20 16:09:04 |
|---|---|
| Line 114 | Line 114 |
| #if !defined(USE_PAGE_ACCESS_TABLE) | #if !defined(USE_PAGE_ACCESS_TABLE) |
| #define page_access 0xd0ddd0ff | #define page_access 0xd0ddd0ff |
| #else /* USE_PAGE_ACCESS_TABLE */ | #else /* USE_PAGE_ACCESS_TABLE */ |
| static const BYTE page_access_bit[32] = { | static const UINT8 page_access_bit[32] = { |
| 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: r */ | 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: r */ |
| 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: w */ | 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: w */ |
| 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: r */ | 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: r */ |
| Line 184 static const BYTE page_access_bit[32] = | Line 184 static const BYTE page_access_bit[32] = |
| * +- CR3(物理アドレス) | * +- CR3(物理アドレス) |
| */ | */ |
| static DWORD paging(DWORD laddr, int crw, int user_mode); | static UINT32 paging(UINT32 laddr, int crw, int user_mode); |
| #if defined(IA32_SUPPORT_TLB) | #if defined(IA32_SUPPORT_TLB) |
| static BOOL tlb_lookup(DWORD vaddr, int crw, DWORD* paddr); | static BOOL tlb_lookup(UINT32 vaddr, int crw, UINT32 *paddr); |
| static void tlb_update(DWORD paddr, DWORD entry, int crw); | static void tlb_update(UINT32 paddr, UINT entry, int crw); |
| #endif | #endif |
| DWORD MEMCALL | UINT32 MEMCALL |
| cpu_linear_memory_read(DWORD laddr, DWORD length, int crw, int user_mode) | cpu_linear_memory_read(UINT32 laddr, UINT length, int crw, int user_mode) |
| { | { |
| DWORD paddr; | UINT32 value = 0; |
| DWORD remain; /* page remain */ | UINT32 paddr; |
| DWORD r; | UINT remain; /* page remain */ |
| DWORD shift = 0; | UINT r; |
| DWORD value = 0; | int shift = 0; |
| /* XXX: 4MB pages... */ | /* XXX: 4MB pages... */ |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| Line 212 cpu_linear_memory_read(DWORD laddr, DWOR | Line 212 cpu_linear_memory_read(DWORD laddr, DWOR |
| break; | break; |
| case 3: | case 3: |
| value |= (DWORD)cpu_memoryread(paddr) << shift; | value += (UINT32)cpu_memoryread(paddr) << shift; |
| shift += 8; | shift += 8; |
| paddr++; | paddr++; |
| /*FALLTHROUGH*/ | /*FALLTHROUGH*/ |
| case 2: | case 2: |
| value |= (DWORD)cpu_memoryread_w(paddr) << shift; | value += (UINT32)cpu_memoryread_w(paddr) << shift; |
| shift += 16; | shift += 16; |
| break; | break; |
| case 1: | case 1: |
| value |= (DWORD)cpu_memoryread(paddr) << shift; | value += (UINT32)cpu_memoryread(paddr) << shift; |
| shift += 8; | shift += 8; |
| break; | break; |
| Line 247 cpu_linear_memory_read(DWORD laddr, DWOR | Line 247 cpu_linear_memory_read(DWORD laddr, DWOR |
| } | } |
| void MEMCALL | void MEMCALL |
| cpu_linear_memory_write(DWORD laddr, DWORD value, DWORD length, int user_mode) | cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, int user_mode) |
| { | { |
| DWORD paddr; | UINT32 paddr; |
| DWORD remain; /* page remain */ | UINT remain; /* page remain */ |
| DWORD r; | UINT r; |
| int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); | int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); |
| /* XXX: 4MB pages... */ | /* XXX: 4MB pages... */ |
| Line 299 cpu_linear_memory_write(DWORD laddr, DWO | Line 299 cpu_linear_memory_write(DWORD laddr, DWO |
| } | } |
| void MEMCALL | void MEMCALL |
| paging_check(DWORD laddr, DWORD length, int crw, int user_mode) | paging_check(UINT32 laddr, UINT length, int crw, int user_mode) |
| { | { |
| DWORD paddr; | UINT32 paddr; |
| DWORD remain; /* page remain */ | UINT remain; /* page remain */ |
| DWORD r; | UINT r; |
| /* XXX: 4MB pages... */ | /* XXX: 4MB pages... */ |
| remain = 0x1000 - (laddr & 0x00000fff); | remain = 0x1000 - (laddr & 0x00000fff); |
| Line 325 paging_check(DWORD laddr, DWORD length, | Line 325 paging_check(DWORD laddr, DWORD length, |
| } | } |
| } | } |
| static DWORD | static UINT32 |
| paging(DWORD laddr, int crw, int user_mode) | paging(UINT32 laddr, int crw, int user_mode) |
| { | { |
| DWORD paddr; /* physical address */ | UINT32 paddr; /* physical address */ |
| DWORD pde_addr; /* page directory entry address */ | UINT32 pde_addr; /* page directory entry address */ |
| DWORD pde; /* page directory entry */ | UINT32 pde; /* page directory entry */ |
| DWORD pte_addr; /* page table entry address */ | UINT32 pte_addr; /* page table entry address */ |
| DWORD pte; /* page table entry */ | UINT32 pte; /* page table entry */ |
| DWORD bit; | UINT bit; |
| DWORD err; | UINT err; |
| #if defined(IA32_SUPPORT_TLB) | #if defined(IA32_SUPPORT_TLB) |
| if (tlb_lookup(laddr, crw, &paddr)) | if (tlb_lookup(laddr, crw, &paddr)) |
| return paddr; | return paddr; |
| #endif /* IA32_SUPPORT_TLB */ | #endif /* IA32_SUPPORT_TLB */ |
| pde_addr = CPU_STAT_PDE_BASE | ((laddr >> 20) & 0xffc); | pde_addr = CPU_STAT_PDE_BASE + ((laddr >> 20) & 0xffc); |
| pde = cpu_memoryread_d(pde_addr); | pde = cpu_memoryread_d(pde_addr); |
| if (!(pde & CPU_PDE_PRESENT)) { | if (!(pde & CPU_PDE_PRESENT)) { |
| VERBOSE(("paging: PDE is not present")); | VERBOSE(("paging: PTE page is not present")); |
| VERBOSE(("paging: CPU_CR3 = 0x%08x", CPU_CR3)); | VERBOSE(("paging: CPU_CR3 = 0x%08x", CPU_CR3)); |
| VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); | VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); |
| err = 0; | err = 0; |
| Line 367 paging(DWORD laddr, int crw, int user_mo | Line 367 paging(DWORD laddr, int crw, int user_mo |
| pte_addr = 0; /* compiler happy */ | pte_addr = 0; /* compiler happy */ |
| /* make physical address */ | /* make physical address */ |
| paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) | (laddr & 0x003fffff); | paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) + (laddr & 0x003fffff); |
| } else | } else |
| #endif /* CPU_FAMILY >= 5 */ | #endif /* CPU_FAMILY >= 5 */ |
| { | { |
| /* 4KB page size */ | /* 4KB page size */ |
| pte_addr = (pde & CPU_PDE_BASEADDR_MASK) | ((laddr >> 10) & 0xffc); | pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((laddr >> 10) & 0xffc); |
| pte = cpu_memoryread_d(pte_addr); | pte = cpu_memoryread_d(pte_addr); |
| if (!(pte & CPU_PTE_PRESENT)) { | if (!(pte & CPU_PTE_PRESENT)) { |
| VERBOSE(("paging: PTE is not present")); | VERBOSE(("paging: page is not present")); |
| VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); | VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); |
| VERBOSE(("paging: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); | VERBOSE(("paging: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); |
| err = 0; | err = 0; |
| Line 387 paging(DWORD laddr, int crw, int user_mo | Line 387 paging(DWORD laddr, int crw, int user_mo |
| } | } |
| /* make physical address */ | /* make physical address */ |
| paddr = (pte & CPU_PTE_BASEADDR_MASK) | (laddr & 0x00000fff); | paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & 0x00000fff); |
| } | } |
| bit = crw & CPU_PAGE_WRITE; | bit = crw & CPU_PAGE_WRITE; |
| bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); | bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); |
| bit |= (user_mode << 3); | bit |= (user_mode << 3); |
| bit |= (CPU_CR0 & CPU_CR0_WP) >> 12; | bit |= CPU_STAT_WP; |
| #if !defined(USE_PAGE_ACCESS_TABLE) | #if !defined(USE_PAGE_ACCESS_TABLE) |
| if (!(page_access & (1 << bit))) | if (!(page_access & (1 << bit))) |
| Line 432 pf_exception: | Line 432 pf_exception: |
| * TLB | * TLB |
| */ | */ |
| typedef struct { | typedef struct { |
| BYTE valid; /* TLB entry is valid */ | UINT8 valid; /* TLB entry is valid */ |
| BYTE global; /* this TLB entry is global */ | UINT8 global; /* this TLB entry is global */ |
| BYTE score; | UINT8 score; |
| BYTE pad; | UINT8 pad; |
| DWORD tag; | UINT32 tag; |
| DWORD mask; /* 4K or 2M or 4M */ | UINT32 mask; /* 4K or 2M or 4M */ |
| DWORD paddr; /* physical addr */ | UINT32 paddr; /* physical addr */ |
| } TLB_ENTRY_T; | } TLB_ENTRY_T; |
| typedef struct { | typedef struct { |
| BYTE kind; | UINT8 kind; |
| #define TLB_KIND_INSTRUCTION (1 << 1) | #define TLB_KIND_INSTRUCTION (1 << 1) |
| #define TLB_KIND_DATA (1 << 2) | #define TLB_KIND_DATA (1 << 2) |
| #define TLB_KIND_COMBINE (TLB_KIND_INSTRUCTION|TLB_KIND_DATA) | #define TLB_KIND_COMBINE (TLB_KIND_INSTRUCTION|TLB_KIND_DATA) |
| Line 452 typedef struct { | Line 452 typedef struct { |
| #define TLB_KIND_LARGE (1 << 4) | #define TLB_KIND_LARGE (1 << 4) |
| #define TLB_KIND_BOTH (TLB_KIND_SMALL|TLB_KIND_LARGE) | #define TLB_KIND_BOTH (TLB_KIND_SMALL|TLB_KIND_LARGE) |
| BYTE way; /* n-way associative */ | UINT8 way; /* n-way associative */ |
| BYTE idx; /* number of TLB index */ | UINT8 idx; /* number of TLB index */ |
| BYTE bpad; | UINT8 bpad; |
| WORD num; /* number of TLB entry */ | UINT16 num; /* number of TLB entry */ |
| WORD wpad; | UINT16 wpad; |
| TLB_ENTRY_T* entry; /* entry[assoc][idx] or entry[assoc] if idx == 1*/ | TLB_ENTRY_T *entry; /* entry[assoc][idx] or entry[assoc] if idx == 1*/ |
| } TLB_T; | } TLB_T; |
| static int ntlb; | static int ntlb; |
| Line 467 static TLB_T tlb[4]; /* i TLB, i (lp) TL | Line 467 static TLB_T tlb[4]; /* i TLB, i (lp) TL |
| #if defined(IA32_PROFILE_TLB) | #if defined(IA32_PROFILE_TLB) |
| /* profiling */ | /* profiling */ |
| static DWORD tlb_hits; | static UINT64 tlb_hits; |
| static DWORD tlb_misses; | static UINT64 tlb_misses; |
| static DWORD tlb_lookups; | static UINT64 tlb_lookups; |
| static DWORD tlb_updates; | static UINT64 tlb_updates; |
| static DWORD tlb_flushes; | static UINT64 tlb_flushes; |
| static DWORD tlb_global_flushes; | static UINT64 tlb_global_flushes; |
| static DWORD tlb_entry_flushes; | static UINT64 tlb_entry_flushes; |
| #define PROFILE_INC(v) (v)++; | #define PROFILE_INC(v) (v)++; |
| #else /* !IA32_PROFILE_TLB */ | #else /* !IA32_PROFILE_TLB */ |
| Line 481 static DWORD tlb_entry_flushes; | Line 481 static DWORD tlb_entry_flushes; |
| #endif /* IA32_PROFILE_TLB */ | #endif /* IA32_PROFILE_TLB */ |
| void | void |
| tlb_init() | tlb_init(void) |
| { | { |
| int i; | int i; |
| Line 524 tlb_init() | Line 524 tlb_init() |
| void | void |
| tlb_flush(BOOL allflush) | tlb_flush(BOOL allflush) |
| { | { |
| TLB_ENTRY_T* ep; | TLB_ENTRY_T *ep; |
| int i, j; | int i, j; |
| if (allflush) { | if (allflush) { |
| Line 545 tlb_flush(BOOL allflush) | Line 545 tlb_flush(BOOL allflush) |
| } | } |
| void | void |
| tlb_flush_page(DWORD vaddr) | tlb_flush_page(UINT32 vaddr) |
| { | { |
| TLB_ENTRY_T* ep; | TLB_ENTRY_T *ep; |
| int idx; | int idx; |
| int i; | int i; |
| Line 578 tlb_flush_page(DWORD vaddr) | Line 578 tlb_flush_page(DWORD vaddr) |
| } | } |
| static BOOL | static BOOL |
| tlb_lookup(DWORD laddr, int crw, DWORD* paddr) | tlb_lookup(UINT32 laddr, int crw, UINT32 *paddr) |
| { | { |
| TLB_ENTRY_T* ep; | TLB_ENTRY_T *ep; |
| int idx; | int idx; |
| int i; | int i; |
| Line 605 tlb_lookup(DWORD laddr, int crw, DWORD* | Line 605 tlb_lookup(DWORD laddr, int crw, DWORD* |
| for (i = 0; i < tlb[i].way; i++) { | for (i = 0; i < tlb[i].way; i++) { |
| if (ep->valid) { | if (ep->valid) { |
| if ((laddr & ep->mask) == ep->tag) { | if ((laddr & ep->mask) == ep->tag) { |
| if (ep->score != (BYTE)~0) | if (ep->score != (UINT8)~0) |
| ep->score++; | ep->score++; |
| *paddr = ep->paddr; | *paddr = ep->paddr; |
| PROFILE_INC(tlb_hits); | PROFILE_INC(tlb_hits); |
| Line 620 tlb_lookup(DWORD laddr, int crw, DWORD* | Line 620 tlb_lookup(DWORD laddr, int crw, DWORD* |
| } | } |
| static void | static void |
| tlb_update(DWORD paddr, DWORD entry, int crw) | tlb_update(UINT32 paddr, UINT entry, int crw) |
| { | { |
| TLB_ENTRY_T* ep; | TLB_ENTRY_T *ep; |
| int idx; | int idx; |
| int i, j; | int i, j; |
| int min_way; | int min_way; |
| WORD min_score = ~0; | UINT16 min_score = ~0; |
| PROFILE_INC(tlb_updates); | PROFILE_INC(tlb_updates); |