kvm: qemu: report paravirt features on cpuid
[kvm-userspace.git] / qemu / target-cris / mmu.c
blob5fa5215bc28444e2ece3389e6e746a038a22583b
1 /*
2 * CRIS mmu emulation.
4 * Copyright (c) 2007 AXIS Communications AB
5 * Written by Edgar E. Iglesias.
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, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #ifndef CONFIG_USER_ONLY
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
28 #include "config.h"
29 #include "cpu.h"
30 #include "mmu.h"
31 #include "exec-all.h"
34 static int cris_mmu_enabled(uint32_t rw_gc_cfg)
36 return (rw_gc_cfg & 12) != 0;
39 static int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg)
41 return (1 << seg) & rw_mm_cfg;
44 static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
46 uint32_t base;
47 int i;
49 if (seg < 8)
50 base = env->sregs[SFR_RW_MM_KBASE_LO];
51 else
52 base = env->sregs[SFR_RW_MM_KBASE_HI];
54 i = seg & 7;
55 base >>= i * 4;
56 base &= 15;
58 base <<= 28;
59 return base;
61 /* Used by the tlb decoder. */
62 #define EXTRACT_FIELD(src, start, end) \
63 (((src) >> start) & ((1 << (end - start + 1)) - 1))
65 static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
66 CPUState *env, uint32_t vaddr,
67 int rw, int usermode)
69 unsigned int vpage;
70 unsigned int idx;
71 uint32_t lo, hi;
72 uint32_t vpn, pfn = 0, pid, fg, fv, fk, fw, fx;
73 int i, match = 0;
75 vpage = vaddr >> 13;
76 idx = vpage & 31;
77 vpage >>= 4;
79 /* We know the index which to check on each set.
80 Scan both I and D. */
81 for (i = 0; i < 4; i++)
83 lo = env->tlbsets[0][i][idx].lo;
84 hi = env->tlbsets[0][i][idx].hi;
86 vpn = EXTRACT_FIELD(hi, 13, 31);
87 pid = EXTRACT_FIELD(hi, 0, 7);
89 if (vpn == vpage
90 && pid == env->pregs[PR_PID]) {
91 match = 1;
92 break;
96 if (match) {
97 pfn = EXTRACT_FIELD(lo, 13, 31);
98 fg = EXTRACT_FIELD(lo, 4, 4);
99 fv = EXTRACT_FIELD(lo, 3, 3);
100 fk = EXTRACT_FIELD(lo, 2, 2);
101 fw = EXTRACT_FIELD(lo, 1, 1);
102 fx = EXTRACT_FIELD(lo, 0, 0);
104 printf ("%s match=%d vaddr=%x vpage=%x vpn=%x pfn=%x pid=%x %x\n",
105 __func__, match,
106 vaddr, vpage,
107 vpn, pfn, pid, env->pregs[PR_PID]);
108 res->pfn = pfn;
109 return !match;
112 int cris_mmu_translate(struct cris_mmu_result_t *res,
113 CPUState *env, uint32_t vaddr,
114 int rw, int mmu_idx)
116 uint32_t phy = vaddr;
117 int seg;
118 int miss = 0;
119 int is_user = mmu_idx == MMU_USER_IDX;
121 if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
122 res->phy = vaddr;
123 return 0;
126 seg = vaddr >> 28;
127 if (cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG]))
129 uint32_t base;
131 miss = 0;
132 base = cris_mmu_translate_seg(env, seg);
133 phy = base | (0x0fffffff & vaddr);
134 res->phy = phy;
136 else
138 miss = cris_mmu_translate_page(res, env, vaddr, rw, is_user);
139 if (!miss) {
140 phy &= 8191;
141 phy |= (res->pfn << 13);
142 res->phy = phy;
145 // printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy);
146 return miss;
148 #endif