~galfy/helenos/bird-port-mainline

« back to all changes in this revision

Viewing changes to kernel/arch/ia64/src/mm/page.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
52
static void set_environment(void);
 
53
 
 
54
/** Initialize ia64 virtual address translation subsystem. */
 
55
void 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. */
 
63
void set_environment(void)
 
64
{
 
65
        region_register rr;
 
66
        pta_register pta;
 
67
        int i;
 
68
#ifdef CONFIG_VHPT
 
69
        uintptr_t vhpt_base;
 
70
#endif
 
71
 
 
72
        /*
 
73
         * First set up kernel region register.
 
74
         * This is redundant (see start.S) but we keep it here just for sure.
 
75
         */
 
76
        rr.word = rr_read(VRN_KERNEL);
 
77
        rr.map.ve = 0;                  /* disable VHPT walker */
 
78
        rr.map.ps = PAGE_WIDTH;
 
79
        rr.map.rid = ASID2RID(ASID_KERNEL, VRN_KERNEL);
 
80
        rr_write(VRN_KERNEL, rr.word);
 
81
        srlz_i();
 
82
        srlz_d();
 
83
 
 
84
        /*
 
85
         * And setup the rest of region register.
 
86
         */
 
87
        for(i = 0; i < REGION_REGISTERS; i++) {
 
88
                /* skip kernel rr */
 
89
                if (i == VRN_KERNEL)
 
90
                        continue;
 
91
        
 
92
                rr.word = rr_read(i);
 
93
                rr.map.ve = 0;          /* disable VHPT walker */
 
94
                rr.map.rid = RID_KERNEL;
 
95
                rr.map.ps = PAGE_WIDTH;
 
96
                rr_write(i, rr.word);
 
97
                srlz_i();
 
98
                srlz_d();
 
99
        }
 
100
 
 
101
#ifdef CONFIG_VHPT      
 
102
        vhpt_base = vhpt_set_up();
 
103
#endif
 
104
        /*
 
105
         * Set up PTA register.
 
106
         */
 
107
        pta.word = pta_read();
 
108
#ifndef CONFIG_VHPT
 
109
        pta.map.ve = 0;                   /* disable VHPT walker */
 
110
        pta.map.base = 0 >> PTA_BASE_SHIFT;
 
111
#else
 
112
        pta.map.ve = 1;                   /* enable VHPT walker */
 
113
        pta.map.base = vhpt_base >> PTA_BASE_SHIFT;
 
114
#endif
 
115
        pta.map.vf = 1;                   /* large entry format */
 
116
        pta.map.size = VHPT_WIDTH;
 
117
        pta_write(pta.word);
 
118
        srlz_i();
 
119
        srlz_d();
 
120
}
 
121
 
 
122
/** Calculate address of collision chain from VPN and ASID.
 
123
 *
 
124
 * Interrupts must be disabled.
 
125
 *
 
126
 * @param page          Address of virtual page including VRN bits.
 
127
 * @param asid          Address space identifier.
 
128
 *
 
129
 * @return              VHPT entry address.
 
130
 */
 
131
vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid)
 
132
{
 
133
        region_register rr_save, rr;
 
134
        size_t vrn;
 
135
        rid_t rid;
 
136
        vhpt_entry_t *v;
 
137
 
 
138
        vrn = page >> VRN_SHIFT;
 
139
        rid = ASID2RID(asid, vrn);
 
140
        
 
141
        rr_save.word = rr_read(vrn);
 
142
        if (rr_save.map.rid == rid) {
 
143
                /*
 
144
                 * The RID is already in place, compute thash and return.
 
145
                 */
 
146
                v = (vhpt_entry_t *) thash(page);
 
147
                return v;
 
148
        }
 
149
        
 
150
        /*
 
151
         * The RID must be written to some region register.
 
152
         * To speed things up, register indexed by vrn is used.
 
153
         */
 
154
        rr.word = rr_save.word;
 
155
        rr.map.rid = rid;
 
156
        rr_write(vrn, rr.word);
 
157
        srlz_i();
 
158
        v = (vhpt_entry_t *) thash(page);
 
159
        rr_write(vrn, rr_save.word);
 
160
        srlz_i();
 
161
        srlz_d();
 
162
 
 
163
        return v;
 
164
}
 
165
 
 
166
/** Compare ASID and VPN against PTE.
 
167
 *
 
168
 * Interrupts must be disabled.
 
169
 *
 
170
 * @param page          Address of virtual page including VRN bits.
 
171
 * @param asid          Address space identifier.
 
172
 *
 
173
 * @return              True if page and asid match the page and asid of t,
 
174
 *                      false otherwise.
 
175
 */
 
176
bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v)
 
177
{
 
178
        region_register rr_save, rr;    
 
179
        size_t vrn;
 
180
        rid_t rid;
 
181
        bool match;
 
182
 
 
183
        ASSERT(v);
 
184
 
 
185
        vrn = page >> VRN_SHIFT;
 
186
        rid = ASID2RID(asid, vrn);
 
187
        
 
188
        rr_save.word = rr_read(vrn);
 
189
        if (rr_save.map.rid == rid) {
 
190
                /*
 
191
                 * The RID is already in place, compare ttag with t and return.
 
192
                 */
 
193
                return ttag(page) == v->present.tag.tag_word;
 
194
        }
 
195
        
 
196
        /*
 
197
         * The RID must be written to some region register.
 
198
         * To speed things up, register indexed by vrn is used.
 
199
         */
 
200
        rr.word = rr_save.word;
 
201
        rr.map.rid = rid;
 
202
        rr_write(vrn, rr.word);
 
203
        srlz_i();
 
204
        match = (ttag(page) == v->present.tag.tag_word);
 
205
        rr_write(vrn, rr_save.word);
 
206
        srlz_i();
 
207
        srlz_d();
 
208
 
 
209
        return match;           
 
210
}
 
211
 
 
212
/** Set up one VHPT entry.
 
213
 *
 
214
 * @param v VHPT entry to be set up.
 
215
 * @param page          Virtual address of the page mapped by the entry.
 
216
 * @param asid          Address space identifier of the address space to which
 
217
 *                      page belongs.
 
218
 * @param frame         Physical address of the frame to wich page is mapped.
 
219
 * @param flags         Different flags for the mapping.
 
220
 */
 
221
void
 
222
vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame,
 
223
    int flags)
 
224
{
 
225
        region_register rr_save, rr;    
 
226
        size_t vrn;
 
227
        rid_t rid;
 
228
        uint64_t tag;
 
229
 
 
230
        ASSERT(v);
 
231
 
 
232
        vrn = page >> VRN_SHIFT;
 
233
        rid = ASID2RID(asid, vrn);
 
234
        
 
235
        /*
 
236
         * Compute ttag.
 
237
         */
 
238
        rr_save.word = rr_read(vrn);
 
239
        rr.word = rr_save.word;
 
240
        rr.map.rid = rid;
 
241
        rr_write(vrn, rr.word);
 
242
        srlz_i();
 
243
        tag = ttag(page);
 
244
        rr_write(vrn, rr_save.word);
 
245
        srlz_i();
 
246
        srlz_d();
 
247
        
 
248
        /*
 
249
         * Clear the entry.
 
250
         */
 
251
        v->word[0] = 0;
 
252
        v->word[1] = 0;
 
253
        v->word[2] = 0;
 
254
        v->word[3] = 0;
 
255
        
 
256
        v->present.p = true;
 
257
        v->present.ma = (flags & PAGE_CACHEABLE) ?
 
258
            MA_WRITEBACK : MA_UNCACHEABLE;
 
259
        v->present.a = false;   /* not accessed */
 
260
        v->present.d = false;   /* not dirty */
 
261
        v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL;
 
262
        v->present.ar = (flags & PAGE_WRITE) ? AR_WRITE : AR_READ;
 
263
        v->present.ar |= (flags & PAGE_EXEC) ? AR_EXECUTE : 0; 
 
264
        v->present.ppn = frame >> PPN_SHIFT;
 
265
        v->present.ed = false;  /* exception not deffered */
 
266
        v->present.ps = PAGE_WIDTH;
 
267
        v->present.key = 0;
 
268
        v->present.tag.tag_word = tag;
 
269
}
 
270
 
 
271
uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused)))
 
272
{
 
273
        /* THIS is a dirty hack. */
 
274
        return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET);
 
275
}
 
276
 
 
277
/** @}
 
278
 */