]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * PowerPC MMU, TLB and BAT emulation helpers for QEMU. | |
3 | * | |
4 | * Copyright (c) 2003-2007 Jocelyn Mayer | |
5 | * Copyright (c) 2013 David Gibson, IBM Corporation | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
20 | ||
21 | #include "cpu.h" | |
22 | #include "helper.h" | |
23 | #include "sysemu/kvm.h" | |
24 | #include "kvm_ppc.h" | |
25 | #include "mmu-hash32.h" | |
26 | ||
27 | //#define DEBUG_MMU | |
28 | ||
29 | #ifdef DEBUG_MMU | |
30 | # define LOG_MMU(...) qemu_log(__VA_ARGS__) | |
31 | # define LOG_MMU_STATE(env) log_cpu_state((env), 0) | |
32 | #else | |
33 | # define LOG_MMU(...) do { } while (0) | |
34 | # define LOG_MMU_STATE(...) do { } while (0) | |
35 | #endif | |
36 | ||
37 | #define PTE_PTEM_MASK 0x7FFFFFBF | |
38 | #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B) | |
39 | ||
40 | static inline int pte_is_valid_hash32(target_ulong pte0) | |
41 | { | |
42 | return pte0 & 0x80000000 ? 1 : 0; | |
43 | } | |
44 | ||
45 | int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0, | |
46 | target_ulong pte1, int h, int rw, int type) | |
47 | { | |
48 | target_ulong ptem, mmask; | |
49 | int access, ret, pteh, ptev, pp; | |
50 | ||
51 | ret = -1; | |
52 | /* Check validity and table match */ | |
53 | ptev = pte_is_valid_hash32(pte0); | |
54 | pteh = (pte0 >> 6) & 1; | |
55 | if (ptev && h == pteh) { | |
56 | /* Check vsid & api */ | |
57 | ptem = pte0 & PTE_PTEM_MASK; | |
58 | mmask = PTE_CHECK_MASK; | |
59 | pp = pte1 & 0x00000003; | |
60 | if (ptem == ctx->ptem) { | |
61 | if (ctx->raddr != (hwaddr)-1ULL) { | |
62 | /* all matches should have equal RPN, WIMG & PP */ | |
63 | if ((ctx->raddr & mmask) != (pte1 & mmask)) { | |
64 | qemu_log("Bad RPN/WIMG/PP\n"); | |
65 | return -3; | |
66 | } | |
67 | } | |
68 | /* Compute access rights */ | |
69 | access = pp_check(ctx->key, pp, ctx->nx); | |
70 | /* Keep the matching PTE informations */ | |
71 | ctx->raddr = pte1; | |
72 | ctx->prot = access; | |
73 | ret = check_prot(ctx->prot, rw, type); | |
74 | if (ret == 0) { | |
75 | /* Access granted */ | |
76 | LOG_MMU("PTE access granted !\n"); | |
77 | } else { | |
78 | /* Access right violation */ | |
79 | LOG_MMU("PTE access rejected\n"); | |
80 | } | |
81 | } | |
82 | } | |
83 | ||
84 | return ret; | |
85 | } |