Rev 699 | Rev 755 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 699 | Rev 746 | ||
---|---|---|---|
Line 32... | Line 32... | ||
32 | #include <mm/heap.h> |
32 | #include <mm/heap.h> |
33 | #include <arch/mm/asid.h> |
33 | #include <arch/mm/asid.h> |
34 | #include <arch/types.h> |
34 | #include <arch/types.h> |
35 | #include <typedefs.h> |
35 | #include <typedefs.h> |
36 | #include <arch/asm.h> |
36 | #include <arch/asm.h> |
- | 37 | #include <synch/spinlock.h> |
|
- | 38 | #include <arch.h> |
|
37 | #include <debug.h> |
39 | #include <debug.h> |
38 | 40 | ||
- | 41 | /** |
|
- | 42 | * This lock protects the page hash table. Note that software must |
|
- | 43 | * be still careful about ordering of writes to ensure consistent |
|
- | 44 | * view of the page hash table for hardware helpers such as VHPT |
|
- | 45 | * walker on ia64. |
|
- | 46 | */ |
|
- | 47 | SPINLOCK_INITIALIZE(page_ht_lock); |
|
- | 48 | ||
- | 49 | /** |
|
- | 50 | * Page hash table pointer. |
|
- | 51 | * The page hash table may be accessed only when page_ht_lock is held. |
|
- | 52 | */ |
|
- | 53 | pte_t *page_ht = NULL; |
|
- | 54 | ||
39 | static void ht_mapping_insert(__address page, asid_t asid, __address frame, int flags, __address root); |
55 | static void ht_mapping_insert(__address page, asid_t asid, __address frame, int flags, __address root); |
40 | static pte_t *ht_mapping_find(__address page, asid_t asid, __address root); |
56 | static pte_t *ht_mapping_find(__address page, asid_t asid, __address root); |
41 | 57 | ||
42 | page_operations_t page_ht_operations = { |
58 | page_operations_t page_ht_operations = { |
43 | .mapping_insert = ht_mapping_insert, |
59 | .mapping_insert = ht_mapping_insert, |
Line 45... | Line 61... | ||
45 | }; |
61 | }; |
46 | 62 | ||
47 | /** Map page to frame using page hash table. |
63 | /** Map page to frame using page hash table. |
48 | * |
64 | * |
49 | * Map virtual address 'page' to physical address 'frame' |
65 | * Map virtual address 'page' to physical address 'frame' |
- | 66 | * using 'flags'. In order not to disturb hardware searching, |
|
- | 67 | * new mappings are appended to the end of the collision |
|
50 | * using 'flags'. |
68 | * chain. |
51 | * |
69 | * |
52 | * @param page Virtual address of the page to be mapped. |
70 | * @param page Virtual address of the page to be mapped. |
53 | * @param asid Address space to which page belongs. |
71 | * @param asid Address space to which page belongs. |
54 | * @param frame Physical address of memory frame to which the mapping is done. |
72 | * @param frame Physical address of memory frame to which the mapping is done. |
55 | * @param flags Flags to be used for mapping. |
73 | * @param flags Flags to be used for mapping. |
56 | * @param root Ignored. |
74 | * @param root Ignored. |
57 | */ |
75 | */ |
58 | void ht_mapping_insert(__address page, asid_t asid, __address frame, int flags, __address root) |
76 | void ht_mapping_insert(__address page, asid_t asid, __address frame, int flags, __address root) |
59 | { |
77 | { |
60 | pte_t *t, *u = NULL; |
78 | pte_t *t, *u; |
- | 79 | ipl_t ipl; |
|
- | 80 | ||
- | 81 | ipl = interrupts_disable(); |
|
- | 82 | spinlock_lock(&page_ht_lock); |
|
61 | 83 | ||
62 | t = HT_HASH(page, asid); |
84 | t = HT_HASH(page, asid); |
63 | if (!HT_SLOT_EMPTY(t)) { |
85 | if (!HT_SLOT_EMPTY(t)) { |
- | 86 | ||
- | 87 | /* |
|
- | 88 | * The slot is occupied. |
|
- | 89 | * Walk through the collision chain and append the mapping to its end. |
|
- | 90 | */ |
|
- | 91 | ||
- | 92 | do { |
|
- | 93 | u = t; |
|
- | 94 | if (HT_COMPARE(page, asid, t)) { |
|
- | 95 | /* |
|
- | 96 | * Nothing to do, |
|
- | 97 | * the record is already there. |
|
- | 98 | */ |
|
- | 99 | spinlock_unlock(&page_ht_lock); |
|
- | 100 | interrupts_restore(ipl); |
|
- | 101 | return; |
|
- | 102 | } |
|
- | 103 | } while ((t = HT_GET_NEXT(t))); |
|
- | 104 | ||
64 | u = (pte_t *) malloc(sizeof(pte_t)); /* FIXME: use slab allocator for this */ |
105 | t = (pte_t *) malloc(sizeof(pte_t)); /* FIXME: use slab allocator for this */ |
65 | if (!u) |
106 | if (!t) |
66 | panic("could not allocate memory for hash table\n"); |
107 | panic("could not allocate memory\n"); |
- | 108 | ||
67 | *u = *t; |
109 | HT_SET_NEXT(u, t); |
68 | } |
110 | } |
69 | HT_SET_NEXT(t, u); |
111 | |
70 | HT_SET_RECORD(t, page, asid, frame, flags); |
112 | HT_SET_RECORD(t, page, asid, frame, flags); |
- | 113 | HT_SET_NEXT(t, NULL); |
|
- | 114 | ||
- | 115 | spinlock_unlock(&page_ht_lock); |
|
- | 116 | interrupts_restore(ipl); |
|
71 | } |
117 | } |
72 | 118 | ||
73 | /** Find mapping for virtual page in page hash table. |
119 | /** Find mapping for virtual page in page hash table. |
74 | * |
120 | * |
75 | * Find mapping for virtual page. |
121 | * Find mapping for virtual page. |
76 | * |
122 | * |
- | 123 | * Interrupts must be disabled. |
|
- | 124 | * |
|
77 | * @param page Virtual page. |
125 | * @param page Virtual page. |
78 | * @param asid Address space to wich page belongs. |
126 | * @param asid Address space to wich page belongs. |
79 | * @param root Ignored. |
127 | * @param root Ignored. |
80 | * |
128 | * |
81 | * @return NULL if there is no such mapping; requested mapping otherwise. |
129 | * @return NULL if there is no such mapping; requested mapping otherwise. |
82 | */ |
130 | */ |
83 | pte_t *ht_mapping_find(__address page, asid_t asid, __address root) |
131 | pte_t *ht_mapping_find(__address page, asid_t asid, __address root) |
84 | { |
132 | { |
85 | pte_t *t; |
133 | pte_t *t; |
86 | 134 | ||
- | 135 | spinlock_lock(&page_ht_lock); |
|
87 | t = HT_HASH(page, asid); |
136 | t = HT_HASH(page, asid); |
- | 137 | if (!HT_SLOT_EMPTY(t)) { |
|
88 | while (!HT_COMPARE(page, asid, t) && HT_GET_NEXT(t)) |
138 | while (!HT_COMPARE(page, asid, t) && HT_GET_NEXT(t)) |
89 | t = HT_GET_NEXT(t); |
139 | t = HT_GET_NEXT(t); |
- | 140 | t = HT_COMPARE(page, asid, t) ? t : NULL; |
|
- | 141 | } else { |
|
- | 142 | t = NULL; |
|
- | 143 | } |
|
- | 144 | spinlock_unlock(&page_ht_lock); |
|
- | 145 | return t; |
|
- | 146 | } |
|
- | 147 | ||
- | 148 | /** Invalidate page hash table. |
|
- | 149 | * |
|
- | 150 | * Interrupts must be disabled. |
|
- | 151 | */ |
|
- | 152 | void ht_invalidate_all(void) |
|
- | 153 | { |
|
- | 154 | pte_t *t, *u; |
|
- | 155 | int i; |
|
90 | 156 | ||
- | 157 | spinlock_lock(&page_ht_lock); |
|
- | 158 | for (i = 0; i < HT_ENTRIES; i++) { |
|
- | 159 | if (!HT_SLOT_EMPTY(&page_ht[i])) { |
|
91 | return HT_COMPARE(page, asid, t) ? t : NULL; |
160 | t = HT_GET_NEXT(&page_ht[i]); |
- | 161 | while (t) { |
|
- | 162 | u = t; |
|
- | 163 | t = HT_GET_NEXT(t); |
|
- | 164 | free(u); /* FIXME: use slab allocator for this */ |
|
- | 165 | } |
|
- | 166 | HT_INVALIDATE_SLOT(&page_ht[i]); |
|
- | 167 | } |
|
- | 168 | } |
|
- | 169 | spinlock_unlock(&page_ht_lock); |
|
92 | } |
170 | } |