Loading target-alpha/cpu.h +13 −0 Original line number Diff line number Diff line Loading @@ -320,6 +320,19 @@ enum { #define CPU_INTERRUPT_SMP CPU_INTERRUPT_TGT_EXT_1 #define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2 /* OSF/1 Page table bits. */ enum { PTE_VALID = 0x0001, PTE_FOR = 0x0002, /* used for page protection (fault on read) */ PTE_FOW = 0x0004, /* used for page protection (fault on write) */ PTE_FOE = 0x0008, /* used for page protection (fault on exec) */ PTE_ASM = 0x0010, PTE_KRE = 0x0100, PTE_URE = 0x0200, PTE_KWE = 0x1000, PTE_UWE = 0x2000 }; /* Hardware interrupt (entInt) constants. */ enum { INT_K_IP, Loading target-alpha/helper.c +125 −4 Original line number Diff line number Diff line Loading @@ -200,14 +200,135 @@ void swap_shadow_regs(CPUState *env) env->shadow[7] = i7; } /* Returns the OSF/1 entMM failure indication, or -1 on success. */ static int get_physical_address(CPUState *env, target_ulong addr, int prot_need, int mmu_idx, target_ulong *pphys, int *pprot) { target_long saddr = addr; target_ulong phys = 0; target_ulong L1pte, L2pte, L3pte; target_ulong pt, index; int prot = 0; int ret = MM_K_ACV; /* Ensure that the virtual address is properly sign-extended from the last implemented virtual address bit. */ if (saddr >> TARGET_VIRT_ADDR_SPACE_BITS != saddr >> 63) { goto exit; } /* Translate the superpage. */ /* ??? When we do more than emulate Unix PALcode, we'll need to determine which superpage is actually active. */ if (saddr < 0 && (saddr >> (TARGET_VIRT_ADDR_SPACE_BITS - 2) & 3) == 2) { /* User-space cannot access kseg addresses. */ if (mmu_idx != MMU_KERNEL_IDX) { goto exit; } phys = saddr & ((1ull << 40) - 1); prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ret = -1; goto exit; } /* Interpret the page table exactly like PALcode does. */ pt = env->ptbr; /* L1 page table read. */ index = (addr >> (TARGET_PAGE_BITS + 20)) & 0x3ff; L1pte = ldq_phys(pt + index*8); if (unlikely((L1pte & PTE_VALID) == 0)) { ret = MM_K_TNV; goto exit; } if (unlikely((L1pte & PTE_KRE) == 0)) { goto exit; } pt = L1pte >> 32 << TARGET_PAGE_BITS; /* L2 page table read. */ index = (addr >> (TARGET_PAGE_BITS + 10)) & 0x3ff; L2pte = ldq_phys(pt + index*8); if (unlikely((L2pte & PTE_VALID) == 0)) { ret = MM_K_TNV; goto exit; } if (unlikely((L2pte & PTE_KRE) == 0)) { goto exit; } pt = L2pte >> 32 << TARGET_PAGE_BITS; /* L3 page table read. */ index = (addr >> TARGET_PAGE_BITS) & 0x3ff; L3pte = ldq_phys(pt + index*8); phys = L3pte >> 32 << TARGET_PAGE_BITS; if (unlikely((L3pte & PTE_VALID) == 0)) { ret = MM_K_TNV; goto exit; } #if PAGE_READ != 1 || PAGE_WRITE != 2 || PAGE_EXEC != 4 # error page bits out of date #endif /* Check access violations. */ if (L3pte & (PTE_KRE << mmu_idx)) { prot |= PAGE_READ | PAGE_EXEC; } if (L3pte & (PTE_KWE << mmu_idx)) { prot |= PAGE_WRITE; } if (unlikely((prot & prot_need) == 0 && prot_need)) { goto exit; } /* Check fault-on-operation violations. */ prot &= ~(L3pte >> 1); ret = -1; if (unlikely((prot & prot_need) == 0)) { ret = (prot_need & PAGE_EXEC ? MM_K_FOE : prot_need & PAGE_WRITE ? MM_K_FOW : prot_need & PAGE_READ ? MM_K_FOR : -1); } exit: *pphys = phys; *pprot = prot; return ret; } target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { return -1; target_ulong phys; int prot, fail; fail = get_physical_address(env, addr, 0, 0, &phys, &prot); return (fail >= 0 ? -1 : phys); } int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw, int mmu_idx, int is_softmmu) { target_ulong phys; int prot, fail; fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot); if (unlikely(fail >= 0)) { env->exception_index = EXCP_MMFAULT; env->trap_arg0 = addr; env->trap_arg1 = fail; env->trap_arg2 = (rw == 2 ? -1 : rw); return 1; } tlb_set_page(env, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); return 0; } #endif /* USER_ONLY */ Loading Loading
target-alpha/cpu.h +13 −0 Original line number Diff line number Diff line Loading @@ -320,6 +320,19 @@ enum { #define CPU_INTERRUPT_SMP CPU_INTERRUPT_TGT_EXT_1 #define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2 /* OSF/1 Page table bits. */ enum { PTE_VALID = 0x0001, PTE_FOR = 0x0002, /* used for page protection (fault on read) */ PTE_FOW = 0x0004, /* used for page protection (fault on write) */ PTE_FOE = 0x0008, /* used for page protection (fault on exec) */ PTE_ASM = 0x0010, PTE_KRE = 0x0100, PTE_URE = 0x0200, PTE_KWE = 0x1000, PTE_UWE = 0x2000 }; /* Hardware interrupt (entInt) constants. */ enum { INT_K_IP, Loading
target-alpha/helper.c +125 −4 Original line number Diff line number Diff line Loading @@ -200,14 +200,135 @@ void swap_shadow_regs(CPUState *env) env->shadow[7] = i7; } /* Returns the OSF/1 entMM failure indication, or -1 on success. */ static int get_physical_address(CPUState *env, target_ulong addr, int prot_need, int mmu_idx, target_ulong *pphys, int *pprot) { target_long saddr = addr; target_ulong phys = 0; target_ulong L1pte, L2pte, L3pte; target_ulong pt, index; int prot = 0; int ret = MM_K_ACV; /* Ensure that the virtual address is properly sign-extended from the last implemented virtual address bit. */ if (saddr >> TARGET_VIRT_ADDR_SPACE_BITS != saddr >> 63) { goto exit; } /* Translate the superpage. */ /* ??? When we do more than emulate Unix PALcode, we'll need to determine which superpage is actually active. */ if (saddr < 0 && (saddr >> (TARGET_VIRT_ADDR_SPACE_BITS - 2) & 3) == 2) { /* User-space cannot access kseg addresses. */ if (mmu_idx != MMU_KERNEL_IDX) { goto exit; } phys = saddr & ((1ull << 40) - 1); prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ret = -1; goto exit; } /* Interpret the page table exactly like PALcode does. */ pt = env->ptbr; /* L1 page table read. */ index = (addr >> (TARGET_PAGE_BITS + 20)) & 0x3ff; L1pte = ldq_phys(pt + index*8); if (unlikely((L1pte & PTE_VALID) == 0)) { ret = MM_K_TNV; goto exit; } if (unlikely((L1pte & PTE_KRE) == 0)) { goto exit; } pt = L1pte >> 32 << TARGET_PAGE_BITS; /* L2 page table read. */ index = (addr >> (TARGET_PAGE_BITS + 10)) & 0x3ff; L2pte = ldq_phys(pt + index*8); if (unlikely((L2pte & PTE_VALID) == 0)) { ret = MM_K_TNV; goto exit; } if (unlikely((L2pte & PTE_KRE) == 0)) { goto exit; } pt = L2pte >> 32 << TARGET_PAGE_BITS; /* L3 page table read. */ index = (addr >> TARGET_PAGE_BITS) & 0x3ff; L3pte = ldq_phys(pt + index*8); phys = L3pte >> 32 << TARGET_PAGE_BITS; if (unlikely((L3pte & PTE_VALID) == 0)) { ret = MM_K_TNV; goto exit; } #if PAGE_READ != 1 || PAGE_WRITE != 2 || PAGE_EXEC != 4 # error page bits out of date #endif /* Check access violations. */ if (L3pte & (PTE_KRE << mmu_idx)) { prot |= PAGE_READ | PAGE_EXEC; } if (L3pte & (PTE_KWE << mmu_idx)) { prot |= PAGE_WRITE; } if (unlikely((prot & prot_need) == 0 && prot_need)) { goto exit; } /* Check fault-on-operation violations. */ prot &= ~(L3pte >> 1); ret = -1; if (unlikely((prot & prot_need) == 0)) { ret = (prot_need & PAGE_EXEC ? MM_K_FOE : prot_need & PAGE_WRITE ? MM_K_FOW : prot_need & PAGE_READ ? MM_K_FOR : -1); } exit: *pphys = phys; *pprot = prot; return ret; } target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { return -1; target_ulong phys; int prot, fail; fail = get_physical_address(env, addr, 0, 0, &phys, &prot); return (fail >= 0 ? -1 : phys); } int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw, int mmu_idx, int is_softmmu) { target_ulong phys; int prot, fail; fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot); if (unlikely(fail >= 0)) { env->exception_index = EXCP_MMFAULT; env->trap_arg0 = addr; env->trap_arg1 = fail; env->trap_arg2 = (rw == 2 ? -1 : rw); return 1; } tlb_set_page(env, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); return 0; } #endif /* USER_ONLY */ Loading