--- np2/i386c/ia32/paging.c 2003/12/11 15:06:50 1.2 +++ np2/i386c/ia32/paging.c 2004/01/26 15:22:16 1.6 @@ -1,4 +1,4 @@ -/* $Id: paging.c,v 1.2 2003/12/11 15:06:50 monaka Exp $ */ +/* $Id: paging.c,v 1.6 2004/01/26 15:22:16 monaka Exp $ */ /* * Copyright (c) 2003 NONAKA Kimihiro @@ -32,93 +32,6 @@ #include "ia32.mcr" /* - * ページ・ディレクトリ・エントリ (4K バイトページ使用時) - * - * 31 12 11 9 8 7 6 5 4 3 2 1 0 - * +----------------------------------------+------+-+--+-+-+---+---+---+---+-+ - * | ページ・テーブルのベース・アドレス |使用可|G|PS|0|A|PCD|PWT|U/S|R/W|P| - * +----------------------------------------+------+-+--+-+-+---+---+---+---+-+ - * | | | | | | | | | | - * 9-11: システム・プログラマが使用可能 --------+ | | | | | | | | | - * 8: グローバル・ページ(無視される) ------------+ | | | | | | | | - * 7: ページ・サイズ (0 = 4k バイトページ) ---------+ | | | | | | | - * 6: 予約 (0) ---------------------------------------+ | | | | | | - * 5: アクセス -----------------------------------------+ | | | | | - * 4: キャッシュ無効 --------------------------------------+ | | | | - * 3: ライトスルー --------------------------------------------+ | | | - * 2: ユーザ/スーパバイザ (0 = スーパバイザ) ---------------------+ | | - * 1: 読み取り/書き込み (0 = 読み取りのみ) ---------------------------+ | - * 0: ページ存在 ---------------------------------------------------------+ - */ -#define CPU_PDE_BASEADDR_MASK 0xfffff000 -#define CPU_PDE_PAGE_SIZE (1 << 7) -#define CPU_PDE_ACCESS (1 << 5) -#define CPU_PDE_CACHE_DISABLE (1 << 4) -#define CPU_PDE_WRITE_THROUGH (1 << 3) -#define CPU_PDE_USER_MODE (1 << 2) -#define CPU_PDE_WRITABLE (1 << 1) -#define CPU_PDE_PRESENT (1 << 0) - -/* - * ページ・ディレクトリ・エントリ (4M バイトページ使用時) - * - * 31 22 21 12 11 9 8 7 6 5 4 3 2 1 0 - * +----------------------------+-----------+------+-+--+-+-+---+---+---+---+-+ - * |ページテーブルの物理アドレス| 予約済み |使用可|G|PS|D|A|PCD|PWT|U/S|R/W|P| - * +----------------------------+-----------+------+-+--+-+-+---+---+---+---+-+ - * | | | | | | | | | | - * 9-11: システム・プログラマが使用可能 --------+ | | | | | | | | | - * 8: グローバル・ページ ------------------------+ | | | | | | | | - * 7: ページ・サイズ (1 = 4M バイトページ) ---------+ | | | | | | | - * 6: ダーティ ---------------------------------------+ | | | | | | - * 5: アクセス -----------------------------------------+ | | | | | - * 4: キャッシュ無効 --------------------------------------+ | | | | - * 3: ライトスルー --------------------------------------------+ | | | - * 2: ユーザ/スーパバイザ (0 = スーパバイザ) ---------------------+ | | - * 1: 読み取り/書き込み (0 = 読み取りのみ) ---------------------------+ | - * 0: ページ存在 ---------------------------------------------------------+ - */ -#define CPU_PDE_4M_BASEADDR_MASK 0xffc00000 -#define CPU_PDE_4M_GLOBAL_PAGE (1 << 8) -#define CPU_PDE_4M_PAGE_SIZE (1 << 7) -#define CPU_PDE_4M_DIRTY (1 << 6) -#define CPU_PDE_4M_ACCESS (1 << 5) -#define CPU_PDE_4M_CACHE_DISABLE (1 << 4) -#define CPU_PDE_4M_WRITE_THROUGH (1 << 3) -#define CPU_PDE_4M_USER_MODE (1 << 2) -#define CPU_PDE_4M_WRITABLE (1 << 1) -#define CPU_PDE_4M_PRESENT (1 << 0) - -/* - * ページ・テーブル・エントリ (4k バイト・ページ) - * - * 31 12 11 9 8 7 6 5 4 3 2 1 0 - * +----------------------------------------+------+-+-+-+-+---+---+---+---+-+ - * | ページのベース・アドレス |使用可|G|0|D|A|PCD|PWT|U/S|R/W|P| - * +----------------------------------------+------+-+-+-+-+---+---+---+---+-+ - * | | | | | | | | | | - * 9-11: システム・プログラマが使用可能 -------+ | | | | | | | | | - * 8: グローバル・ページ -----------------------+ | | | | | | | | - * 7: 予約 (0) -----------------------------------+ | | | | | | | - * 6: ダーティ -------------------------------------+ | | | | | | - * 5: アクセス ---------------------------------------+ | | | | | - * 4: キャッシュ無効 ------------------------------------+ | | | | - * 3: ライトスルー ------------------------------------------+ | | | - * 2: ユーザ/スーパバイザ (0 = スーパバイザ) -------------------+ | | - * 1: 読み取り/書き込み (0 = 読み取りのみ) -------------------------+ | - * 0: ページ存在 -------------------------------------------------------+ - */ -#define CPU_PTE_BASEADDR_MASK 0xfffff000 -#define CPU_PTE_GLOBAL_PAGE (1 << 8) -#define CPU_PTE_DIRTY (1 << 6) -#define CPU_PTE_ACCESS (1 << 5) -#define CPU_PTE_CACHE_DISABLE (1 << 4) -#define CPU_PTE_WRITE_THROUGH (1 << 3) -#define CPU_PTE_USER_MODE (1 << 2) -#define CPU_PTE_WRITABLE (1 << 1) -#define CPU_PTE_PRESENT (1 << 0) - -/* * ページフォルト例外 * * 4-31: 予約済み @@ -284,6 +197,7 @@ cpu_linear_memory_read(DWORD laddr, DWOR DWORD paddr; DWORD remain; /* page remain */ DWORD r; + DWORD shift = 0; DWORD value = 0; int crw; int pl; @@ -300,17 +214,20 @@ cpu_linear_memory_read(DWORD laddr, DWOR r = (remain > length) ? length : remain; switch (r) { case 1: - value = (value << 8) | cpu_memoryread(paddr); + value |= (DWORD)cpu_memoryread(paddr) << shift; + shift += 8; break; case 2: - value = (value << 16) | cpu_memoryread_w(paddr); + value |= (DWORD)cpu_memoryread_w(paddr) << shift; + shift += 16; break; case 3: - value <<= 24; - value |= cpu_memoryread_w(paddr) << 8; - value |= cpu_memoryread(paddr + 2); + value |= (DWORD)cpu_memoryread_w(paddr) << shift; + shift += 16; + value |= (DWORD)cpu_memoryread(paddr + 2) << shift; + shift += 8; break; case 4: @@ -318,16 +235,18 @@ cpu_linear_memory_read(DWORD laddr, DWOR break; default: - ia32_panic("cpu_linear_memory_read(): out of range\n"); + ia32_panic("cpu_linear_memory_read(): out of range (r = %d)\n", r); break; } if (length == r) break; + laddr += r; length -= r; remain -= r; - laddr += r; + if (remain <= 0) + remain += 0x1000; } return value; @@ -339,31 +258,35 @@ cpu_linear_memory_write(DWORD laddr, DWO 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); /* XXX: 4MB pages... */ remain = 0x1000 - (laddr & 0x00000fff); for (;;) { - paddr = paging(laddr, CPU_PAGING_PAGE_WRITE|CPU_PAGING_PAGE_DATA, pl); + paddr = paging(laddr, crw, pl); r = (remain > length) ? length : remain; switch (r) { case 1: - cpu_memorywrite(paddr, value); + cpu_memorywrite(paddr, value & 0xff); value >>= 8; break; case 2: - cpu_memorywrite_w(paddr, value); + cpu_memorywrite_w(paddr, value & 0xffff); value >>= 16; break; case 3: - cpu_memorywrite_w(paddr, value); - cpu_memorywrite(paddr, value >> 16); - value >>= 24; + cpu_memorywrite_w(paddr, value & 0xffff); + value >>= 16; + cpu_memorywrite(paddr + 2, value & 0xff); + value >>= 8; break; case 4: @@ -371,35 +294,48 @@ cpu_linear_memory_write(DWORD laddr, DWO break; default: - ia32_panic("cpu_linear_memory_write(): out of range\n"); + ia32_panic("cpu_linear_memory_write(): out of range (r = %d)\n", r); break; } if (length == r) break; + laddr += r; length -= r; remain -= r; - laddr += r; + if (remain <= 0) + remain += 0x1000; } } void MEMCALL paging_check(DWORD laddr, DWORD length, int rw) { - DWORD addr; - int n; + DWORD paddr; + DWORD remain; /* page remain */ + DWORD r; + int crw; int pl; + crw = rw; pl = (CPU_STAT_CPL == 3); /* XXX: 4MB pages... */ - n = ((laddr & 0xfff) + length) / 0x1000; - addr = (laddr & ~0xfff); - do { - (void)paging(addr, rw, pl); - addr += 0x1000; - } while (--n > 0); + remain = 0x1000 - (laddr & 0x00000fff); + for (;;) { + paddr = paging(laddr, crw, pl); + + r = (remain > length) ? length : remain; + if (length == r) + break; + + laddr += r; + length -= r; + remain -= r; + if (remain <= 0) + remain += 0x1000; + } } static DWORD @@ -411,7 +347,7 @@ paging(DWORD laddr, int crw, int user_mo DWORD pte_addr; /* page table entry address */ DWORD pte; /* page table entry */ DWORD bit; - DWORD err = 0; + DWORD err; #if defined(IA32_SUPPORT_TLB) if (tlb_lookup(laddr, crw, &paddr)) @@ -421,6 +357,9 @@ paging(DWORD laddr, int crw, int user_mo pde_addr = (CPU_CR3 & CPU_CR3_PD_MASK) | ((laddr >> 20) & 0xffc); pde = cpu_memoryread_d(pde_addr); if (!(pde & CPU_PDE_PRESENT)) { + VERBOSE(("paging: PDE 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; goto pf_exception; } @@ -446,6 +385,9 @@ paging(DWORD laddr, int crw, int user_mo 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: 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; goto pf_exception; } @@ -458,7 +400,7 @@ paging(DWORD laddr, int crw, int user_mo paddr = (pte & CPU_PTE_BASEADDR_MASK) | (laddr & 0x00000fff); } - bit = crw & 1; + bit = crw & CPU_PAGING_PAGE_WRITE; bit |= (pde & pte & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE)); bit |= (user_mode << 3); bit |= (CPU_CR0 & CPU_CR0_WP) >> 12; @@ -469,11 +411,15 @@ paging(DWORD laddr, int crw, int user_mo if (!(page_access_bit[bit])) #endif { + VERBOSE(("paging: page access violation.")); + 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: paddr = 0x%08x, bit = 0x%08x", paddr, bit)); err = 1; goto pf_exception; } - if ((crw & 1) && !(pte & CPU_PTE_DIRTY)) { + if ((crw & CPU_PAGING_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { pte |= CPU_PTE_DIRTY; cpu_memorywrite_d(pte_addr, pte); } @@ -486,7 +432,7 @@ paging(DWORD laddr, int crw, int user_mo pf_exception: CPU_CR2 = laddr; - err |= ((crw & 1) << 1) | (user_mode << 2); + err |= ((crw & CPU_PAGING_PAGE_WRITE) << 1) | (user_mode << 2); EXCEPTION(PF_EXCEPTION, err); return 0; /* compiler happy */ } @@ -641,7 +587,7 @@ tlb_flush_page(DWORD vaddr) } static BOOL -tlb_lookup(DWORD vaddr, int crw, DWORD* paddr) +tlb_lookup(DWORD laddr, int crw, DWORD* paddr) { TLB_ENTRY_T* ep; int idx; @@ -657,9 +603,9 @@ tlb_lookup(DWORD vaddr, int crw, DWORD* idx = 0; } else { if (tlb[i].kind & TLB_KIND_SMALL) { - idx = (vaddr >> 12) & (tlb[i].idx - 1); + idx = (laddr >> 12) & (tlb[i].idx - 1); } else { - idx = (vaddr >> 22) & (tlb[i].idx - 1); + idx = (laddr >> 22) & (tlb[i].idx - 1); } } @@ -667,7 +613,7 @@ tlb_lookup(DWORD vaddr, int crw, DWORD* ep = &tlb[i].entry[idx * tlb[i].way]; for (i = 0; i < tlb[i].way; i++) { if (ep->valid) { - if ((vaddr & ep->mask) == ep->tag) { + if ((laddr & ep->mask) == ep->tag) { if (ep->score != (BYTE)~0) ep->score++; *paddr = ep->paddr; @@ -756,9 +702,9 @@ tlb_flush(BOOL allflush) } void -tlb_flush_page(DWORD vaddr) +tlb_flush_page(DWORD laddr) { - (void)vaddr; + (void)laddr; } #endif /* IA32_SUPPORT_TLB */