]>
git.proxmox.com Git - qemu.git/blob - target-ppc/mmu-hash32.c
2 * PowerPC MMU, TLB and BAT emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
5 * Copyright (c) 2013 David Gibson, IBM Corporation
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.
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.
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/>.
23 #include "sysemu/kvm.h"
25 #include "mmu-hash32.h"
30 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
31 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
33 # define LOG_MMU(...) do { } while (0)
34 # define LOG_MMU_STATE(...) do { } while (0)
37 #define PTE_PTEM_MASK 0x7FFFFFBF
38 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
40 static inline int pte_is_valid_hash32(target_ulong pte0
)
42 return pte0
& 0x80000000 ? 1 : 0;
45 static int pte_check_hash32(mmu_ctx_t
*ctx
, target_ulong pte0
,
46 target_ulong pte1
, int h
, int rw
, int type
)
48 target_ulong ptem
, mmask
;
49 int access
, ret
, pteh
, ptev
, pp
;
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");
68 /* Compute access rights */
69 access
= pp_check(ctx
->key
, pp
, ctx
->nx
);
70 /* Keep the matching PTE informations */
73 ret
= check_prot(ctx
->prot
, rw
, type
);
76 LOG_MMU("PTE access granted !\n");
78 /* Access right violation */
79 LOG_MMU("PTE access rejected\n");
87 /* PTE table lookup */
88 int find_pte32(CPUPPCState
*env
, mmu_ctx_t
*ctx
, int h
,
89 int rw
, int type
, int target_page_bits
)
92 target_ulong pte0
, pte1
;
96 ret
= -1; /* No entry found */
97 pteg_off
= get_pteg_offset(env
, ctx
->hash
[h
], HASH_PTE_SIZE_32
);
98 for (i
= 0; i
< 8; i
++) {
99 if (env
->external_htab
) {
100 pte0
= ldl_p(env
->external_htab
+ pteg_off
+ (i
* 8));
101 pte1
= ldl_p(env
->external_htab
+ pteg_off
+ (i
* 8) + 4);
103 pte0
= ldl_phys(env
->htab_base
+ pteg_off
+ (i
* 8));
104 pte1
= ldl_phys(env
->htab_base
+ pteg_off
+ (i
* 8) + 4);
106 r
= pte_check_hash32(ctx
, pte0
, pte1
, h
, rw
, type
);
107 LOG_MMU("Load pte from %08" HWADDR_PRIx
" => " TARGET_FMT_lx
" "
108 TARGET_FMT_lx
" %d %d %d " TARGET_FMT_lx
"\n",
109 pteg_off
+ (i
* 8), pte0
, pte1
, (int)(pte0
>> 31), h
,
110 (int)((pte0
>> 6) & 1), ctx
->ptem
);
113 /* PTE inconsistency */
116 /* Access violation */
126 /* XXX: we should go on looping to check all PTEs consistency
127 * but if we can speed-up the whole thing as the
128 * result would be undefined if PTEs are not consistent.
137 LOG_MMU("found PTE at addr %08" HWADDR_PRIx
" prot=%01x ret=%d\n",
138 ctx
->raddr
, ctx
->prot
, ret
);
139 /* Update page flags */
141 if (pte_update_flags(ctx
, &pte1
, ret
, rw
) == 1) {
142 if (env
->external_htab
) {
143 stl_p(env
->external_htab
+ pteg_off
+ (good
* 8) + 4,
146 stl_phys_notdirty(env
->htab_base
+ pteg_off
+
147 (good
* 8) + 4, pte1
);
152 /* We have a TLB that saves 4K pages, so let's
153 * split a huge page to 4k chunks */
154 if (target_page_bits
!= TARGET_PAGE_BITS
) {
155 ctx
->raddr
|= (ctx
->eaddr
& ((1 << target_page_bits
) - 1))