source: mainline/kernel/arch/ia64/src/mm/page.c@ 86018c1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 86018c1 was d9ee2ea, checked in by Jakub Jermar <jakub@…>, 15 years ago

Change the way how RIDs are mapped onto ASIDs. Instead of 7 RIDs per ASID, now
there will be 8 RIDs per one ASID. This will slightly reduce the number of
available ASIDs, but not significantly.

The kernel will now have all 8 RIDs instead of only one. RID 0 - 7 belong to the
kernel, but only RID 7 accessible from VRN 7 is actually used by the kernel.
This allows us to use RID 0 for VRN 0 and differentiate thus between
0x0000000000000000 and 0xe000000000000000 in a more elegant way. test fault1
will now associate the kernel bad trap with RID 0 which maps to ASID_KERNEL.

User tasks will also be given 8 RIDs, but will use only the lower 7 that fit
into VRN 0 - 6, because the last VRN needs to be reserved for the kernel. The
eighth RID will be unused for now. It can be used for something completely
different one day or if the task needs to establish some special mappings.

So with this change, the kernel now has a 64-bit address space compared to
previous 61 bits, but still makes use only of the highest 1/8 (i.e. 61-bits).
Applications continue to have an address space composed of 7 61-bit blocks which
are arranged in a consecutive way. Each application now has one hidden and
currently unused 61-bit segment.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * Copyright (c) 2006 Jakub Vana
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup ia64mm
31 * @{
32 */
33/** @file
34 */
35
36#include <arch/mm/page.h>
37#include <genarch/mm/page_ht.h>
38#include <mm/asid.h>
39#include <arch/mm/asid.h>
40#include <arch/mm/vhpt.h>
41#include <arch/types.h>
42#include <print.h>
43#include <mm/page.h>
44#include <mm/frame.h>
45#include <config.h>
46#include <panic.h>
47#include <arch/asm.h>
48#include <arch/barrier.h>
49#include <memstr.h>
50#include <align.h>
51
52static void set_environment(void);
53
54/** Initialize ia64 virtual address translation subsystem. */
55void page_arch_init(void)
56{
57 page_mapping_operations = &ht_mapping_operations;
58 pk_disable();
59 set_environment();
60}
61
62/** Initialize VHPT and region registers. */
63void set_environment(void)
64{
65 region_register_t rr;
66 pta_register_t pta;
67 int i;
68#ifdef CONFIG_VHPT
69 uintptr_t vhpt_base;
70#endif
71
72 /*
73 * Set up kernel region registers.
74 * VRN_KERNEL has already been set in start.S.
75 * For paranoia reasons, we set it again.
76 */
77 for(i = 0; i < REGION_REGISTERS; i++) {
78 rr.word = rr_read(i);
79 rr.map.ve = 0; /* disable VHPT walker */
80 rr.map.rid = ASID2RID(ASID_KERNEL, i);
81 rr.map.ps = PAGE_WIDTH;
82 rr_write(i, rr.word);
83 srlz_i();
84 srlz_d();
85 }
86
87#ifdef CONFIG_VHPT
88 vhpt_base = vhpt_set_up();
89#endif
90 /*
91 * Set up PTA register.
92 */
93 pta.word = pta_read();
94#ifndef CONFIG_VHPT
95 pta.map.ve = 0; /* disable VHPT walker */
96 pta.map.base = 0 >> PTA_BASE_SHIFT;
97#else
98 pta.map.ve = 1; /* enable VHPT walker */
99 pta.map.base = vhpt_base >> PTA_BASE_SHIFT;
100#endif
101 pta.map.vf = 1; /* large entry format */
102 pta.map.size = VHPT_WIDTH;
103 pta_write(pta.word);
104 srlz_i();
105 srlz_d();
106}
107
108/** Calculate address of collision chain from VPN and ASID.
109 *
110 * Interrupts must be disabled.
111 *
112 * @param page Address of virtual page including VRN bits.
113 * @param asid Address space identifier.
114 *
115 * @return VHPT entry address.
116 */
117vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid)
118{
119 region_register_t rr_save, rr;
120 size_t vrn;
121 rid_t rid;
122 vhpt_entry_t *v;
123
124 vrn = page >> VRN_SHIFT;
125 rid = ASID2RID(asid, vrn);
126
127 rr_save.word = rr_read(vrn);
128 if (rr_save.map.rid == rid) {
129 /*
130 * The RID is already in place, compute thash and return.
131 */
132 v = (vhpt_entry_t *) thash(page);
133 return v;
134 }
135
136 /*
137 * The RID must be written to some region register.
138 * To speed things up, register indexed by vrn is used.
139 */
140 rr.word = rr_save.word;
141 rr.map.rid = rid;
142 rr_write(vrn, rr.word);
143 srlz_i();
144 v = (vhpt_entry_t *) thash(page);
145 rr_write(vrn, rr_save.word);
146 srlz_i();
147 srlz_d();
148
149 return v;
150}
151
152/** Compare ASID and VPN against PTE.
153 *
154 * Interrupts must be disabled.
155 *
156 * @param page Address of virtual page including VRN bits.
157 * @param asid Address space identifier.
158 *
159 * @return True if page and asid match the page and asid of t,
160 * false otherwise.
161 */
162bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v)
163{
164 region_register_t rr_save, rr;
165 size_t vrn;
166 rid_t rid;
167 bool match;
168
169 ASSERT(v);
170
171 vrn = page >> VRN_SHIFT;
172 rid = ASID2RID(asid, vrn);
173
174 rr_save.word = rr_read(vrn);
175 if (rr_save.map.rid == rid) {
176 /*
177 * The RID is already in place, compare ttag with t and return.
178 */
179 return ttag(page) == v->present.tag.tag_word;
180 }
181
182 /*
183 * The RID must be written to some region register.
184 * To speed things up, register indexed by vrn is used.
185 */
186 rr.word = rr_save.word;
187 rr.map.rid = rid;
188 rr_write(vrn, rr.word);
189 srlz_i();
190 match = (ttag(page) == v->present.tag.tag_word);
191 rr_write(vrn, rr_save.word);
192 srlz_i();
193 srlz_d();
194
195 return match;
196}
197
198/** Set up one VHPT entry.
199 *
200 * @param v VHPT entry to be set up.
201 * @param page Virtual address of the page mapped by the entry.
202 * @param asid Address space identifier of the address space to which
203 * page belongs.
204 * @param frame Physical address of the frame to wich page is mapped.
205 * @param flags Different flags for the mapping.
206 */
207void
208vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame,
209 int flags)
210{
211 region_register_t rr_save, rr;
212 size_t vrn;
213 rid_t rid;
214 uint64_t tag;
215
216 ASSERT(v);
217
218 vrn = page >> VRN_SHIFT;
219 rid = ASID2RID(asid, vrn);
220
221 /*
222 * Compute ttag.
223 */
224 rr_save.word = rr_read(vrn);
225 rr.word = rr_save.word;
226 rr.map.rid = rid;
227 rr_write(vrn, rr.word);
228 srlz_i();
229 tag = ttag(page);
230 rr_write(vrn, rr_save.word);
231 srlz_i();
232 srlz_d();
233
234 /*
235 * Clear the entry.
236 */
237 v->word[0] = 0;
238 v->word[1] = 0;
239 v->word[2] = 0;
240 v->word[3] = 0;
241
242 v->present.p = true;
243 v->present.ma = (flags & PAGE_CACHEABLE) ?
244 MA_WRITEBACK : MA_UNCACHEABLE;
245 v->present.a = false; /* not accessed */
246 v->present.d = false; /* not dirty */
247 v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL;
248 v->present.ar = (flags & PAGE_WRITE) ? AR_WRITE : AR_READ;
249 v->present.ar |= (flags & PAGE_EXEC) ? AR_EXECUTE : 0;
250 v->present.ppn = frame >> PPN_SHIFT;
251 v->present.ed = false; /* exception not deffered */
252 v->present.ps = PAGE_WIDTH;
253 v->present.key = 0;
254 v->present.tag.tag_word = tag;
255}
256
257uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused)))
258{
259 /* THIS is a dirty hack. */
260 return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET);
261}
262
263/** @}
264 */
Note: See TracBrowser for help on using the repository browser.