Rev 748 | Rev 751 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 748 | Rev 749 | ||
---|---|---|---|
Line 28... | Line 28... | ||
28 | */ |
28 | */ |
29 | 29 | ||
30 | #include <arch/mm/page.h> |
30 | #include <arch/mm/page.h> |
31 | #include <genarch/mm/page_ht.h> |
31 | #include <genarch/mm/page_ht.h> |
32 | #include <mm/asid.h> |
32 | #include <mm/asid.h> |
- | 33 | #include <arch/mm/asid.h> |
|
33 | #include <arch/types.h> |
34 | #include <arch/types.h> |
- | 35 | #include <typedefs.h> |
|
34 | #include <print.h> |
36 | #include <print.h> |
35 | #include <mm/page.h> |
37 | #include <mm/page.h> |
36 | #include <mm/frame.h> |
38 | #include <mm/frame.h> |
37 | #include <config.h> |
39 | #include <config.h> |
38 | #include <panic.h> |
40 | #include <panic.h> |
39 | #include <arch/asm.h> |
41 | #include <arch/asm.h> |
40 | #include <arch/barrier.h> |
42 | #include <arch/barrier.h> |
41 | #include <memstr.h> |
43 | #include <memstr.h> |
42 | 44 | ||
- | 45 | static void set_vhpt_environment(void); |
|
- | 46 | ||
- | 47 | /** Initialize ia64 virtual address translation subsystem. */ |
|
- | 48 | void page_arch_init(void) |
|
- | 49 | { |
|
- | 50 | page_operations = &page_ht_operations; |
|
- | 51 | pk_disable(); |
|
- | 52 | set_vhpt_environment(); |
|
- | 53 | } |
|
- | 54 | ||
43 | /** Initialize VHPT and region registers. */ |
55 | /** Initialize VHPT and region registers. */ |
44 | static void set_vhpt_environment(void) |
56 | void set_vhpt_environment(void) |
45 | { |
57 | { |
46 | region_register rr; |
58 | region_register rr; |
47 | pta_register pta; |
59 | pta_register pta; |
48 | int i; |
60 | int i; |
49 | 61 | ||
Line 92... | Line 104... | ||
92 | pta_write(pta.word); |
104 | pta_write(pta.word); |
93 | srlz_i(); |
105 | srlz_i(); |
94 | srlz_d(); |
106 | srlz_d(); |
95 | } |
107 | } |
96 | 108 | ||
97 | /** Initialize ia64 virtual address translation subsystem. */ |
- | |
98 | void page_arch_init(void) |
- | |
99 | { |
- | |
100 | page_operations = &page_ht_operations; |
- | |
101 | pk_disable(); |
- | |
102 | set_vhpt_environment(); |
- | |
103 | } |
- | |
104 | - | ||
105 | /** Calculate address of collision chain from VPN and ASID. |
109 | /** Calculate address of collision chain from VPN and ASID. |
106 | * |
110 | * |
107 | * This is rather non-trivial function. |
- | |
108 | * First, it has to translate ASID to RID. |
- | |
109 | * This is achieved by taking VRN bits of |
- | |
110 | * page into account. |
- | |
111 | * Second, it must preserve the region register |
- | |
112 | * it writes the RID to. |
111 | * Interrupts must be disabled. |
113 | * |
112 | * |
114 | * @param page Address of virtual page including VRN bits. |
113 | * @param page Address of virtual page including VRN bits. |
115 | * @param asid Address space identifier. |
114 | * @param asid Address space identifier. |
116 | * |
115 | * |
117 | * @return Head of VHPT collision chain for page and asid. |
116 | * @return Head of VHPT collision chain for page and asid. |
118 | */ |
117 | */ |
119 | pte_t *vhpt_hash(__address page, asid_t asid) |
118 | pte_t *vhpt_hash(__address page, asid_t asid) |
120 | { |
119 | { |
121 | region_register rr_save, rr; |
120 | region_register rr_save, rr; |
- | 121 | index_t vrn; |
|
- | 122 | rid_t rid; |
|
122 | pte_t *t; |
123 | pte_t *t; |
123 | 124 | ||
- | 125 | vrn = page >> VRN_SHIFT; |
|
- | 126 | rid = ASID2RID(asid, vrn); |
|
- | 127 | ||
124 | rr_save.word = rr_read(VRN_WORK); |
128 | rr_save.word = rr_read(vrn); |
- | 129 | if (rr_save.map.rid == rid) { |
|
- | 130 | /* |
|
- | 131 | * The RID is already in place, compute thash and return. |
|
- | 132 | */ |
|
- | 133 | t = (pte_t *) thash(page); |
|
- | 134 | return t; |
|
- | 135 | } |
|
- | 136 | ||
- | 137 | /* |
|
- | 138 | * The RID must be written to some region register. |
|
- | 139 | * To speed things up, register indexed by vrn is used. |
|
- | 140 | */ |
|
125 | rr.word = rr_save.word; |
141 | rr.word = rr_save.word; |
126 | if ((page >> VRN_SHIFT) != VRN_KERNEL) |
- | |
127 | rr.map.rid = (asid * RIDS_PER_ASID) + (page >> VRN_SHIFT); |
- | |
128 | else |
- | |
129 | rr.map.rid = ASID_KERNEL; |
142 | rr.map.rid = rid; |
130 | rr_write(VRN_WORK, rr.word); |
143 | rr_write(vrn, rr.word); |
131 | srlz_i(); |
144 | srlz_i(); |
132 | t = (pte_t *) thash((VRN_WORK << VRN_SHIFT) | (~(VRN_MASK) & page)); |
145 | t = (pte_t *) thash(page); |
133 | rr_write(VRN_WORK, rr_save.word); |
146 | rr_write(vrn, rr_save.word); |
134 | srlz_i(); |
147 | srlz_i(); |
135 | srlz_d(); |
148 | srlz_d(); |
136 | 149 | ||
137 | return t; |
150 | return t; |
138 | } |
151 | } |
- | 152 | ||
- | 153 | /** Compare ASID and VPN against PTE. |
|
- | 154 | * |
|
- | 155 | * Interrupts must be disabled. |
|
- | 156 | * |
|
- | 157 | * @param page Address of virtual page including VRN bits. |
|
- | 158 | * @param asid Address space identifier. |
|
- | 159 | * |
|
- | 160 | * @return True if page and asid match the page and asid of t, false otherwise. |
|
- | 161 | */ |
|
- | 162 | bool vhpt_compare(__address page, asid_t asid, pte_t *t) |
|
- | 163 | { |
|
- | 164 | region_register rr_save, rr; |
|
- | 165 | index_t vrn; |
|
- | 166 | rid_t rid; |
|
- | 167 | bool match; |
|
- | 168 | ||
- | 169 | ASSERT(t); |
|
- | 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) == t->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) == t->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 t 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 page belongs. |
|
- | 203 | * @param frame Physical address of the frame to wich page is mapped. |
|
- | 204 | * @param flags Different flags for the mapping. |
|
- | 205 | */ |
|
- | 206 | void vhpt_set_record(pte_t *t, __address page, asid_t asid, __address frame, int flags) |
|
- | 207 | { |
|
- | 208 | region_register rr_save, rr; |
|
- | 209 | index_t vrn; |
|
- | 210 | rid_t rid; |
|
- | 211 | __u64 tag; |
|
- | 212 | ||
- | 213 | ASSERT(t); |
|
- | 214 | ||
- | 215 | vrn = page >> VRN_SHIFT; |
|
- | 216 | rid = ASID2RID(asid, vrn); |
|
- | 217 | ||
- | 218 | /* |
|
- | 219 | * Compute ttag. |
|
- | 220 | */ |
|
- | 221 | rr_save.word = rr_read(vrn); |
|
- | 222 | rr.word = rr_save.word; |
|
- | 223 | rr.map.rid = rid; |
|
- | 224 | rr_write(vrn, rr.word); |
|
- | 225 | srlz_i(); |
|
- | 226 | tag = ttag(page); |
|
- | 227 | rr_write(vrn, rr_save.word); |
|
- | 228 | srlz_i(); |
|
- | 229 | srlz_d(); |
|
- | 230 | ||
- | 231 | /* |
|
- | 232 | * Clear the entry. |
|
- | 233 | */ |
|
- | 234 | t->word[0] = 0; |
|
- | 235 | t->word[1] = 0; |
|
- | 236 | t->word[2] = 0; |
|
- | 237 | t->word[3] = 0; |
|
- | 238 | ||
- | 239 | t->present.p = true; |
|
- | 240 | t->present.ma = (flags & PAGE_CACHEABLE) ? MA_WRITEBACK : MA_UNCACHEABLE; |
|
- | 241 | t->present.a = false; /* not accessed */ |
|
- | 242 | t->present.d = false; /* not dirty */ |
|
- | 243 | t->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL; |
|
- | 244 | t->present.ar = (flags & PAGE_WRITE) ? AR_WRITE : AR_READ; |
|
- | 245 | t->present.ar |= (flags & PAGE_EXEC) ? AR_EXECUTE : 0; |
|
- | 246 | t->present.ppn = frame >> PPN_SHIFT; |
|
- | 247 | t->present.ed = false; /* exception not deffered */ |
|
- | 248 | t->present.ps = PAGE_WIDTH; |
|
- | 249 | t->present.key = 0; |
|
- | 250 | t->present.tag.tag_word = tag; |
|
- | 251 | t->present.next = NULL; |
|
- | 252 | } |