]> Git Repo - qemu.git/blame - target-openrisc/mmu.c
vfio: Add sysfsdev property for pci & platform
[qemu.git] / target-openrisc / mmu.c
CommitLineData
e67db06e
JL
1/*
2 * OpenRISC MMU.
3 *
4 * Copyright (c) 2011-2012 Jia Liu <[email protected]>
5 * Zhizhou Zhang <[email protected]>
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
ed2decc6 21#include "qemu/osdep.h"
e67db06e
JL
22#include "cpu.h"
23#include "qemu-common.h"
022c62cb 24#include "exec/gdbstub.h"
1de7afc9 25#include "qemu/host-utils.h"
e67db06e
JL
26#ifndef CONFIG_USER_ONLY
27#include "hw/loader.h"
28#endif
29
726fe045
JL
30#ifndef CONFIG_USER_ONLY
31int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
a8170e5e 32 hwaddr *physical,
726fe045
JL
33 int *prot, target_ulong address, int rw)
34{
35 *physical = address;
04359e6b 36 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
726fe045
JL
37 return TLBRET_MATCH;
38}
39
40int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu,
a8170e5e 41 hwaddr *physical,
726fe045
JL
42 int *prot, target_ulong address, int rw)
43{
44 int vpn = address >> TARGET_PAGE_BITS;
45 int idx = vpn & ITLB_MASK;
46 int right = 0;
47
48 if ((cpu->env.tlb->itlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
49 return TLBRET_NOMATCH;
50 }
51 if (!(cpu->env.tlb->itlb[0][idx].mr & 1)) {
52 return TLBRET_INVALID;
53 }
54
55 if (cpu->env.sr & SR_SM) { /* supervisor mode */
56 if (cpu->env.tlb->itlb[0][idx].tr & SXE) {
57 right |= PAGE_EXEC;
58 }
59 } else {
60 if (cpu->env.tlb->itlb[0][idx].tr & UXE) {
61 right |= PAGE_EXEC;
62 }
63 }
64
65 if ((rw & 2) && ((right & PAGE_EXEC) == 0)) {
66 return TLBRET_BADADDR;
67 }
68
69 *physical = (cpu->env.tlb->itlb[0][idx].tr & TARGET_PAGE_MASK) |
70 (address & (TARGET_PAGE_SIZE-1));
71 *prot = right;
72 return TLBRET_MATCH;
73}
74
75int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
a8170e5e 76 hwaddr *physical,
726fe045
JL
77 int *prot, target_ulong address, int rw)
78{
79 int vpn = address >> TARGET_PAGE_BITS;
80 int idx = vpn & DTLB_MASK;
81 int right = 0;
82
83 if ((cpu->env.tlb->dtlb[0][idx].mr >> TARGET_PAGE_BITS) != vpn) {
84 return TLBRET_NOMATCH;
85 }
86 if (!(cpu->env.tlb->dtlb[0][idx].mr & 1)) {
87 return TLBRET_INVALID;
88 }
89
90 if (cpu->env.sr & SR_SM) { /* supervisor mode */
91 if (cpu->env.tlb->dtlb[0][idx].tr & SRE) {
92 right |= PAGE_READ;
93 }
94 if (cpu->env.tlb->dtlb[0][idx].tr & SWE) {
95 right |= PAGE_WRITE;
96 }
97 } else {
98 if (cpu->env.tlb->dtlb[0][idx].tr & URE) {
99 right |= PAGE_READ;
100 }
101 if (cpu->env.tlb->dtlb[0][idx].tr & UWE) {
102 right |= PAGE_WRITE;
103 }
104 }
105
bf961b52 106 if (!(rw & 1) && ((right & PAGE_READ) == 0)) {
726fe045
JL
107 return TLBRET_BADADDR;
108 }
109 if ((rw & 1) && ((right & PAGE_WRITE) == 0)) {
110 return TLBRET_BADADDR;
111 }
112
113 *physical = (cpu->env.tlb->dtlb[0][idx].tr & TARGET_PAGE_MASK) |
114 (address & (TARGET_PAGE_SIZE-1));
115 *prot = right;
116 return TLBRET_MATCH;
117}
118
119static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu,
a8170e5e 120 hwaddr *physical,
726fe045
JL
121 int *prot, target_ulong address,
122 int rw)
123{
124 int ret = TLBRET_MATCH;
125
726fe045
JL
126 if (rw == 2) { /* ITLB */
127 *physical = 0;
128 ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical,
129 prot, address, rw);
130 } else { /* DTLB */
131 ret = cpu->env.tlb->cpu_openrisc_map_address_data(cpu, physical,
132 prot, address, rw);
133 }
134
135 return ret;
136}
137#endif
138
139static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu,
140 target_ulong address,
141 int rw, int tlb_error)
142{
27103424 143 CPUState *cs = CPU(cpu);
726fe045
JL
144 int exception = 0;
145
146 switch (tlb_error) {
147 default:
148 if (rw == 2) {
149 exception = EXCP_IPF;
150 } else {
151 exception = EXCP_DPF;
152 }
153 break;
154#ifndef CONFIG_USER_ONLY
155 case TLBRET_BADADDR:
156 if (rw == 2) {
157 exception = EXCP_IPF;
158 } else {
159 exception = EXCP_DPF;
160 }
161 break;
162 case TLBRET_INVALID:
163 case TLBRET_NOMATCH:
164 /* No TLB match for a mapped address */
165 if (rw == 2) {
166 exception = EXCP_ITLBMISS;
167 } else {
168 exception = EXCP_DTLBMISS;
169 }
170 break;
171#endif
172 }
173
27103424 174 cs->exception_index = exception;
726fe045
JL
175 cpu->env.eear = address;
176}
177
178#ifndef CONFIG_USER_ONLY
7510454e
AF
179int openrisc_cpu_handle_mmu_fault(CPUState *cs,
180 vaddr address, int rw, int mmu_idx)
726fe045 181{
7510454e 182 OpenRISCCPU *cpu = OPENRISC_CPU(cs);
726fe045 183 int ret = 0;
a8170e5e 184 hwaddr physical = 0;
726fe045 185 int prot = 0;
726fe045
JL
186
187 ret = cpu_openrisc_get_phys_addr(cpu, &physical, &prot,
188 address, rw);
189
190 if (ret == TLBRET_MATCH) {
0c591eb0 191 tlb_set_page(cs, address & TARGET_PAGE_MASK,
04359e6b 192 physical & TARGET_PAGE_MASK, prot,
726fe045
JL
193 mmu_idx, TARGET_PAGE_SIZE);
194 ret = 0;
195 } else if (ret < 0) {
196 cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret);
197 ret = 1;
198 }
199
200 return ret;
201}
202#else
7510454e
AF
203int openrisc_cpu_handle_mmu_fault(CPUState *cs,
204 vaddr address, int rw, int mmu_idx)
726fe045 205{
7510454e 206 OpenRISCCPU *cpu = OPENRISC_CPU(cs);
726fe045 207 int ret = 0;
726fe045
JL
208
209 cpu_openrisc_raise_mmu_exception(cpu, address, rw, ret);
210 ret = 1;
211
212 return ret;
213}
214#endif
215
e67db06e 216#ifndef CONFIG_USER_ONLY
00b941e5 217hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
e67db06e 218{
00b941e5 219 OpenRISCCPU *cpu = OPENRISC_CPU(cs);
a8170e5e 220 hwaddr phys_addr;
726fe045 221 int prot;
726fe045
JL
222
223 if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) {
224 return -1;
225 }
226
227 return phys_addr;
e67db06e
JL
228}
229
230void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)
231{
726fe045
JL
232 cpu->env.tlb = g_malloc0(sizeof(CPUOpenRISCTLBContext));
233
234 cpu->env.tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
235 cpu->env.tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
e67db06e
JL
236}
237#endif
This page took 0.285868 seconds and 4 git commands to generate.