--- np2/i386c/ia32/paging.c 2004/01/23 16:17:51 1.5 +++ np2/i386c/ia32/paging.c 2004/02/20 16:09:04 1.12 @@ -1,4 +1,4 @@ -/* $Id: paging.c,v 1.5 2004/01/23 16:17:51 monaka Exp $ */ +/* $Id: paging.c,v 1.12 2004/02/20 16:09:04 monaka Exp $ */ /* * Copyright (c) 2003 NONAKA Kimihiro @@ -112,9 +112,9 @@ * +-----+-----------+-----+-----+---+ */ #if !defined(USE_PAGE_ACCESS_TABLE) -static const DWORD page_access = 0xd0cdd0ff; +#define page_access 0xd0ddd0ff #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: w */ 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: r */ @@ -143,7 +143,7 @@ static const BYTE page_access_bit[32] = 1, /* CR0: p, CPL: s, PTE: u, PTE: r, ope: r */ 0, /* CR0: p, CPL: s, PTE: u, PTE: r, ope: w */ 1, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: r */ - 0, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: w */ + 1, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: w */ 0, /* CR0: p, CPL: u, PTE: s, PTE: r, ope: r */ 0, /* CR0: p, CPL: u, PTE: s, PTE: r, ope: w */ @@ -184,180 +184,167 @@ static const BYTE page_access_bit[32] = * +- 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) -static BOOL tlb_lookup(DWORD vaddr, int crw, DWORD* paddr); -static void tlb_update(DWORD paddr, DWORD entry, int crw); +static BOOL tlb_lookup(UINT32 vaddr, int crw, UINT32 *paddr); +static void tlb_update(UINT32 paddr, UINT entry, int crw); #endif -DWORD MEMCALL -cpu_linear_memory_read(DWORD laddr, DWORD length, int code) +UINT32 MEMCALL +cpu_linear_memory_read(UINT32 laddr, UINT length, int crw, int user_mode) { - DWORD paddr; - DWORD remain; /* page remain */ - DWORD r; - DWORD shift = 0; - DWORD value = 0; - int crw; - int pl; - - crw = CPU_PAGING_PAGE_READ; - crw |= code ? CPU_PAGING_PAGE_CODE : CPU_PAGING_PAGE_DATA; - pl = (CPU_STAT_CPL == 3); + UINT32 value = 0; + UINT32 paddr; + UINT remain; /* page remain */ + UINT r; + int shift = 0; /* XXX: 4MB pages... */ remain = 0x1000 - (laddr & 0x00000fff); for (;;) { - paddr = paging(laddr, crw, pl); + paddr = paging(laddr, crw, user_mode); r = (remain > length) ? length : remain; switch (r) { - case 1: - value |= (DWORD)cpu_memoryread(paddr) << shift; - shift += 8; + case 4: + value = cpu_memoryread_d(paddr); break; + case 3: + value += (UINT32)cpu_memoryread(paddr) << shift; + shift += 8; + paddr++; + /*FALLTHROUGH*/ case 2: - value |= (DWORD)cpu_memoryread_w(paddr) << shift; + value += (UINT32)cpu_memoryread_w(paddr) << shift; shift += 16; break; - case 3: - value |= (DWORD)cpu_memoryread_w(paddr) << shift; - shift += 16; - value |= (DWORD)cpu_memoryread(paddr + 2) << shift; + case 1: + value += (UINT32)cpu_memoryread(paddr) << shift; shift += 8; break; - case 4: - value = cpu_memoryread_d(paddr); - break; - default: ia32_panic("cpu_linear_memory_read(): out of range (r = %d)\n", r); break; } - if (length == r) + length -= r; + if (length == 0) break; laddr += r; - length -= r; remain -= r; - if (remain <= 0) + if (remain <= 0) { + /* next page */ remain += 0x1000; + } } return value; } void MEMCALL -cpu_linear_memory_write(DWORD laddr, DWORD length, DWORD value) +cpu_linear_memory_write(UINT32 laddr, UINT32 value, UINT length, int user_mode) { - DWORD paddr; - DWORD remain; /* page remain */ - DWORD r; - int crw; - int pl; - - crw = CPU_PAGING_PAGE_WRITE; - crw |= CPU_PAGING_PAGE_DATA; - pl = (CPU_STAT_CPL == 3); + UINT32 paddr; + UINT remain; /* page remain */ + UINT r; + int crw = (CPU_PAGE_WRITE|CPU_PAGE_DATA); /* XXX: 4MB pages... */ remain = 0x1000 - (laddr & 0x00000fff); for (;;) { - paddr = paging(laddr, crw, pl); + paddr = paging(laddr, crw, user_mode); r = (remain > length) ? length : remain; switch (r) { - case 1: - cpu_memorywrite(paddr, value & 0xff); - value >>= 8; + case 4: + cpu_memorywrite_d(paddr, value); break; + case 3: + cpu_memorywrite(paddr, value & 0xff); + value >>= 8; + paddr++; + /*FALLTHROUGH*/ case 2: cpu_memorywrite_w(paddr, value & 0xffff); value >>= 16; break; - case 3: - cpu_memorywrite_w(paddr, value & 0xffff); - value >>= 16; + case 1: cpu_memorywrite(paddr, value & 0xff); value >>= 8; break; - case 4: - cpu_memorywrite_d(paddr, value); - break; - default: ia32_panic("cpu_linear_memory_write(): out of range (r = %d)\n", r); break; } - if (length == r) + length -= r; + if (length == 0) break; laddr += r; - length -= r; remain -= r; - if (remain <= 0) + if (remain <= 0) { + /* next page */ remain += 0x1000; + } } } void MEMCALL -paging_check(DWORD laddr, DWORD length, int rw) +paging_check(UINT32 laddr, UINT length, int crw, int user_mode) { - DWORD paddr; - DWORD remain; /* page remain */ - DWORD r; - int crw; - int pl; - - crw = rw; - pl = (CPU_STAT_CPL == 3); + UINT32 paddr; + UINT remain; /* page remain */ + UINT r; /* XXX: 4MB pages... */ remain = 0x1000 - (laddr & 0x00000fff); for (;;) { - paddr = paging(laddr, crw, pl); + paddr = paging(laddr, crw, user_mode); r = (remain > length) ? length : remain; - if (length == r) + + length -= r; + if (length == 0) break; laddr += r; - length -= r; remain -= r; - if (remain <= 0) + if (remain <= 0) { + /* next page */ remain += 0x1000; + } } } -static DWORD -paging(DWORD laddr, int crw, int user_mode) +static UINT32 +paging(UINT32 laddr, int crw, int user_mode) { - DWORD paddr; /* physical address */ - DWORD pde_addr; /* page directory entry address */ - DWORD pde; /* page directory entry */ - DWORD pte_addr; /* page table entry address */ - DWORD pte; /* page table entry */ - DWORD bit; - DWORD err = 0; + UINT32 paddr; /* physical address */ + UINT32 pde_addr; /* page directory entry address */ + UINT32 pde; /* page directory entry */ + UINT32 pte_addr; /* page table entry address */ + UINT32 pte; /* page table entry */ + UINT bit; + UINT err; #if defined(IA32_SUPPORT_TLB) if (tlb_lookup(laddr, crw, &paddr)) return paddr; #endif /* IA32_SUPPORT_TLB */ - pde_addr = (CPU_CR3 & CPU_CR3_PD_MASK) | ((laddr >> 20) & 0xffc); + pde_addr = CPU_STAT_PDE_BASE + ((laddr >> 20) & 0xffc); pde = cpu_memoryread_d(pde_addr); 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: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); err = 0; @@ -368,6 +355,7 @@ paging(DWORD laddr, int crw, int user_mo cpu_memorywrite_d(pde_addr, pde); } +#if CPU_FAMILY >= 5 /* no support PAE */ __ASSERT(!(CPU_CR4 & CPU_CR4_PAE)); @@ -379,13 +367,15 @@ paging(DWORD laddr, int crw, int user_mo pte_addr = 0; /* compiler happy */ /* make physical address */ - paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) | (laddr & 0x003fffff); - } else { + paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) + (laddr & 0x003fffff); + } else +#endif /* CPU_FAMILY >= 5 */ + { /* 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); 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: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); err = 0; @@ -397,13 +387,13 @@ paging(DWORD laddr, int crw, int user_mo } /* make physical address */ - paddr = (pte & CPU_PTE_BASEADDR_MASK) | (laddr & 0x00000fff); + paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & 0x00000fff); } - bit = crw & CPU_PAGING_PAGE_WRITE; + bit = crw & CPU_PAGE_WRITE; bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); bit |= (user_mode << 3); - bit |= (CPU_CR0 & CPU_CR0_WP) >> 12; + bit |= CPU_STAT_WP; #if !defined(USE_PAGE_ACCESS_TABLE) if (!(page_access & (1 << bit))) @@ -419,7 +409,7 @@ paging(DWORD laddr, int crw, int user_mo goto pf_exception; } - if ((crw & CPU_PAGING_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { + if ((crw & CPU_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { pte |= CPU_PTE_DIRTY; cpu_memorywrite_d(pte_addr, pte); } @@ -432,7 +422,7 @@ paging(DWORD laddr, int crw, int user_mo pf_exception: CPU_CR2 = laddr; - err |= ((crw & CPU_PAGING_PAGE_WRITE) << 1) | (user_mode << 2); + err |= ((crw & CPU_PAGE_WRITE) << 1) | (user_mode << 2); EXCEPTION(PF_EXCEPTION, err); return 0; /* compiler happy */ } @@ -442,19 +432,19 @@ pf_exception: * TLB */ typedef struct { - BYTE valid; /* TLB entry is valid */ - BYTE global; /* this TLB entry is global */ - BYTE score; - BYTE pad; + UINT8 valid; /* TLB entry is valid */ + UINT8 global; /* this TLB entry is global */ + UINT8 score; + UINT8 pad; - DWORD tag; - DWORD mask; /* 4K or 2M or 4M */ + UINT32 tag; + UINT32 mask; /* 4K or 2M or 4M */ - DWORD paddr; /* physical addr */ + UINT32 paddr; /* physical addr */ } TLB_ENTRY_T; typedef struct { - BYTE kind; + UINT8 kind; #define TLB_KIND_INSTRUCTION (1 << 1) #define TLB_KIND_DATA (1 << 2) #define TLB_KIND_COMBINE (TLB_KIND_INSTRUCTION|TLB_KIND_DATA) @@ -462,14 +452,14 @@ typedef struct { #define TLB_KIND_LARGE (1 << 4) #define TLB_KIND_BOTH (TLB_KIND_SMALL|TLB_KIND_LARGE) - BYTE way; /* n-way associative */ - BYTE idx; /* number of TLB index */ - BYTE bpad; + UINT8 way; /* n-way associative */ + UINT8 idx; /* number of TLB index */ + UINT8 bpad; - WORD num; /* number of TLB entry */ - WORD wpad; + UINT16 num; /* number of TLB entry */ + 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; static int ntlb; @@ -477,13 +467,13 @@ static TLB_T tlb[4]; /* i TLB, i (lp) TL #if defined(IA32_PROFILE_TLB) /* profiling */ -static DWORD tlb_hits; -static DWORD tlb_misses; -static DWORD tlb_lookups; -static DWORD tlb_updates; -static DWORD tlb_flushes; -static DWORD tlb_global_flushes; -static DWORD tlb_entry_flushes; +static UINT64 tlb_hits; +static UINT64 tlb_misses; +static UINT64 tlb_lookups; +static UINT64 tlb_updates; +static UINT64 tlb_flushes; +static UINT64 tlb_global_flushes; +static UINT64 tlb_entry_flushes; #define PROFILE_INC(v) (v)++; #else /* !IA32_PROFILE_TLB */ @@ -491,7 +481,7 @@ static DWORD tlb_entry_flushes; #endif /* IA32_PROFILE_TLB */ void -tlb_init() +tlb_init(void) { int i; @@ -512,17 +502,18 @@ tlb_init() tlb_entry_flushes = 0; #endif /* IA32_PROFILE_TLB */ - /* XXX プロセッサ種別にしたがって TLB 構成を構築する */ - +#if CPU_FAMILY == 4 /* とりあえず i486 形式で… */ /* combine (I/D) TLB: 4KB Pages, 4-way set associative 32 entries */ ntlb = 1; tlb[0].kind = TLB_KIND_COMBINE | TLB_KIND_SMALL; tlb[0].num = 32; tlb[0].way = 4; - tlb[0].idx = tlb[0].num / tlb[0].way; +#endif for (i = 0; i < ntlb; i++) { + tlb[i].idx = tlb[i].num / tlb[i].way; + tlb[i].entry = (TLB_ENTRY_T*)calloc(sizeof(TLB_ENTRY_T), tlb[i].num); if (tlb[i].entry == 0) { ia32_panic("tlb_init(): can't alloc TLB entry\n"); @@ -533,7 +524,7 @@ tlb_init() void tlb_flush(BOOL allflush) { - TLB_ENTRY_T* ep; + TLB_ENTRY_T *ep; int i, j; if (allflush) { @@ -554,9 +545,9 @@ tlb_flush(BOOL allflush) } void -tlb_flush_page(DWORD vaddr) +tlb_flush_page(UINT32 vaddr) { - TLB_ENTRY_T* ep; + TLB_ENTRY_T *ep; int idx; int i; @@ -587,15 +578,15 @@ tlb_flush_page(DWORD vaddr) } 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 i; PROFILE_INC(tlb_lookups); - crw &= CPU_PAGING_PAGE_CODE | CPU_PAGING_PAGE_DATA; + crw &= CPU_PAGE_CODE | CPU_PAGE_DATA; for (i = 0; i < ntlb; i++) { if (tlb[i].kind & crw) { if (tlb[i].idx == 1) { @@ -614,7 +605,7 @@ tlb_lookup(DWORD laddr, int crw, DWORD* for (i = 0; i < tlb[i].way; i++) { if (ep->valid) { if ((laddr & ep->mask) == ep->tag) { - if (ep->score != (BYTE)~0) + if (ep->score != (UINT8)~0) ep->score++; *paddr = ep->paddr; PROFILE_INC(tlb_hits); @@ -629,17 +620,17 @@ tlb_lookup(DWORD laddr, int crw, DWORD* } 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 i, j; int min_way; - WORD min_score = ~0; + UINT16 min_score = ~0; PROFILE_INC(tlb_updates); - crw &= CPU_PAGING_PAGE_CODE | CPU_PAGING_PAGE_DATA; + crw &= CPU_PAGE_CODE | CPU_PAGE_DATA; for (i = 0; i < ntlb; i++) { if (tlb[i].kind & crw) { if (tlb[i].idx == 1) { @@ -686,25 +677,4 @@ tlb_update(DWORD paddr, DWORD entry, int } __ASSERT(i != ntlb); } -#else /* !IA32_SUPPORT_TLB */ -void -tlb_init() -{ - - /* nothing to do */ -} - -void -tlb_flush(BOOL allflush) -{ - - (void)allflush; -} - -void -tlb_flush_page(DWORD laddr) -{ - - (void)laddr; -} #endif /* IA32_SUPPORT_TLB */