Rev 3972 | Rev 4230 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3972 | Rev 3973 | ||
---|---|---|---|
Line 46... | Line 46... | ||
46 | #include <mm/frame.h> |
46 | #include <mm/frame.h> |
47 | #include <mm/as.h> |
47 | #include <mm/as.h> |
48 | #include <panic.h> |
48 | #include <panic.h> |
49 | #include <debug.h> |
49 | #include <debug.h> |
50 | #include <adt/list.h> |
50 | #include <adt/list.h> |
51 | #include <synch/spinlock.h> |
- | |
52 | #include <synch/mutex.h> |
51 | #include <synch/mutex.h> |
53 | #include <synch/condvar.h> |
52 | #include <synch/condvar.h> |
54 | #include <arch/asm.h> |
53 | #include <arch/asm.h> |
55 | #include <arch.h> |
54 | #include <arch.h> |
56 | #include <print.h> |
55 | #include <print.h> |
Line 58... | Line 57... | ||
58 | #include <mm/slab.h> |
57 | #include <mm/slab.h> |
59 | #include <bitops.h> |
58 | #include <bitops.h> |
60 | #include <macros.h> |
59 | #include <macros.h> |
61 | #include <config.h> |
60 | #include <config.h> |
62 | 61 | ||
63 | typedef struct { |
- | |
64 | count_t refcount; /**< Tracking of shared frames */ |
- | |
65 | uint8_t buddy_order; /**< Buddy system block order */ |
- | |
66 | link_t buddy_link; /**< Link to the next free block inside |
- | |
67 | one order */ |
- | |
68 | void *parent; /**< If allocated by slab, this points there */ |
- | |
69 | } frame_t; |
- | |
70 | - | ||
71 | typedef struct { |
- | |
72 | pfn_t base; /**< Frame_no of the first frame |
- | |
73 | in the frames array */ |
- | |
74 | count_t count; /**< Size of zone */ |
- | |
75 | count_t free_count; /**< Number of free frame_t |
- | |
76 | structures */ |
- | |
77 | count_t busy_count; /**< Number of busy frame_t |
- | |
78 | structures */ |
- | |
79 | zone_flags_t flags; /**< Type of the zone */ |
- | |
80 | - | ||
81 | frame_t *frames; /**< Array of frame_t structures |
- | |
82 | in this zone */ |
- | |
83 | buddy_system_t *buddy_system; /**< Buddy system for the zone */ |
- | |
84 | } zone_t; |
- | |
85 | - | ||
86 | /* |
- | |
87 | * The zoneinfo.lock must be locked when accessing zoneinfo structure. |
- | |
88 | * Some of the attributes in zone_t structures are 'read-only' |
- | |
89 | */ |
- | |
90 | typedef struct { |
- | |
91 | SPINLOCK_DECLARE(lock); |
- | |
92 | count_t count; |
- | |
93 | zone_t info[ZONES_MAX]; |
- | |
94 | } zones_t; |
- | |
95 | - | ||
96 | static zones_t zones; |
62 | zones_t zones; |
97 | 63 | ||
98 | /* |
64 | /* |
99 | * Synchronization primitives used to sleep when there is no memory |
65 | * Synchronization primitives used to sleep when there is no memory |
100 | * available. |
66 | * available. |
101 | */ |
67 | */ |
Line 126... | Line 92... | ||
126 | static inline index_t make_frame_index(zone_t *zone, frame_t *frame) |
92 | static inline index_t make_frame_index(zone_t *zone, frame_t *frame) |
127 | { |
93 | { |
128 | return (frame - zone->frames); |
94 | return (frame - zone->frames); |
129 | } |
95 | } |
130 | 96 | ||
131 | static inline bool zone_flags_available(zone_flags_t flags) |
- | |
132 | { |
- | |
133 | return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0); |
- | |
134 | } |
- | |
135 | - | ||
136 | /** Initialize frame structure. |
97 | /** Initialize frame structure. |
137 | * |
98 | * |
138 | * @param frame Frame structure to be initialized. |
99 | * @param frame Frame structure to be initialized. |
139 | * |
100 | * |
140 | */ |
101 | */ |
Line 178... | Line 139... | ||
178 | break; |
139 | break; |
179 | } |
140 | } |
180 | 141 | ||
181 | /* Move other zones up */ |
142 | /* Move other zones up */ |
182 | count_t j; |
143 | count_t j; |
183 | for (j = i; j < zones.count; j++) |
144 | for (j = zones.count; j > i; j--) { |
184 | zones.info[j + 1] = zones.info[j]; |
145 | zones.info[j] = zones.info[j - 1]; |
- | 146 | zones.info[j].buddy_system->data = |
|
- | 147 | (void *) &zones.info[j - 1]; |
|
- | 148 | } |
|
185 | 149 | ||
186 | zones.count++; |
150 | zones.count++; |
187 | 151 | ||
188 | return i; |
152 | return i; |
189 | } |
153 | } |
Line 204... | Line 168... | ||
204 | total += zones.info[i].free_count; |
168 | total += zones.info[i].free_count; |
205 | 169 | ||
206 | return total; |
170 | return total; |
207 | } |
171 | } |
208 | 172 | ||
209 | /** Find a zone with a given frame. |
173 | /** Find a zone with a given frames. |
210 | * |
174 | * |
211 | * Assume interrupts are disabled and zones lock is |
175 | * Assume interrupts are disabled and zones lock is |
212 | * locked. |
176 | * locked. |
213 | * |
177 | * |
214 | * @param frame Frame number contained in zone. |
178 | * @param frame Frame number contained in zone. |
- | 179 | * @param count Number of frames to look for. |
|
215 | * @param hint Used as zone hint. |
180 | * @param hint Used as zone hint. |
216 | * |
181 | * |
217 | * @return Zone index or -1 if not found. |
182 | * @return Zone index or -1 if not found. |
218 | * |
183 | * |
219 | */ |
184 | */ |
220 | static count_t find_zone(pfn_t frame, count_t hint) |
185 | count_t find_zone(pfn_t frame, count_t count, count_t hint) |
221 | { |
186 | { |
222 | if (hint >= zones.count) |
187 | if (hint >= zones.count) |
223 | hint = 0; |
188 | hint = 0; |
224 | 189 | ||
225 | count_t i = hint; |
190 | count_t i = hint; |
226 | do { |
191 | do { |
227 | if ((zones.info[i].base <= frame) |
192 | if ((zones.info[i].base <= frame) |
228 | && (zones.info[i].base + zones.info[i].count > frame)) |
193 | && (zones.info[i].base + zones.info[i].count >= frame + count)) |
229 | return i; |
194 | return i; |
230 | 195 | ||
231 | i++; |
196 | i++; |
232 | if (i >= zones.count) |
197 | if (i >= zones.count) |
233 | i = 0; |
198 | i = 0; |
Line 763... | Line 728... | ||
763 | ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count); |
728 | ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count); |
764 | return_config_frames(z1, |
729 | return_config_frames(z1, |
765 | ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)), |
730 | ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)), |
766 | zones.info[z2].count); |
731 | zones.info[z2].count); |
767 | 732 | ||
768 | /* Shift existing zones */ |
733 | /* Move zones down */ |
769 | count_t i; |
734 | count_t i; |
770 | for (i = z2 + 1; i < zones.count; i++) |
735 | for (i = z2 + 1; i < zones.count; i++) { |
771 | zones.info[i - 1] = zones.info[i]; |
736 | zones.info[i - 1] = zones.info[i]; |
- | 737 | zones.info[i - 1].buddy_system->data = |
|
- | 738 | (void *) &zones.info[i - 1]; |
|
- | 739 | } |
|
- | 740 | ||
772 | zones.count--; |
741 | zones.count--; |
773 | 742 | ||
774 | errout: |
743 | errout: |
775 | spinlock_unlock(&zones.lock); |
744 | spinlock_unlock(&zones.lock); |
776 | interrupts_restore(ipl); |
745 | interrupts_restore(ipl); |
Line 962... | Line 931... | ||
962 | void frame_set_parent(pfn_t pfn, void *data, count_t hint) |
931 | void frame_set_parent(pfn_t pfn, void *data, count_t hint) |
963 | { |
932 | { |
964 | ipl_t ipl = interrupts_disable(); |
933 | ipl_t ipl = interrupts_disable(); |
965 | spinlock_lock(&zones.lock); |
934 | spinlock_lock(&zones.lock); |
966 | 935 | ||
967 | count_t znum = find_zone(pfn, hint); |
936 | count_t znum = find_zone(pfn, 1, hint); |
968 | 937 | ||
969 | ASSERT(znum != (count_t) -1); |
938 | ASSERT(znum != (count_t) -1); |
970 | 939 | ||
971 | zone_get_frame(&zones.info[znum], |
940 | zone_get_frame(&zones.info[znum], |
972 | pfn - zones.info[znum].base)->parent = data; |
941 | pfn - zones.info[znum].base)->parent = data; |
Line 978... | Line 947... | ||
978 | void *frame_get_parent(pfn_t pfn, count_t hint) |
947 | void *frame_get_parent(pfn_t pfn, count_t hint) |
979 | { |
948 | { |
980 | ipl_t ipl = interrupts_disable(); |
949 | ipl_t ipl = interrupts_disable(); |
981 | spinlock_lock(&zones.lock); |
950 | spinlock_lock(&zones.lock); |
982 | 951 | ||
983 | count_t znum = find_zone(pfn, hint); |
952 | count_t znum = find_zone(pfn, 1, hint); |
984 | 953 | ||
985 | ASSERT(znum != (count_t) -1); |
954 | ASSERT(znum != (count_t) -1); |
986 | 955 | ||
987 | void *res = zone_get_frame(&zones.info[znum], |
956 | void *res = zone_get_frame(&zones.info[znum], |
988 | pfn - zones.info[znum].base)->parent; |
957 | pfn - zones.info[znum].base)->parent; |
Line 1109... | Line 1078... | ||
1109 | 1078 | ||
1110 | /* |
1079 | /* |
1111 | * First, find host frame zone for addr. |
1080 | * First, find host frame zone for addr. |
1112 | */ |
1081 | */ |
1113 | pfn_t pfn = ADDR2PFN(frame); |
1082 | pfn_t pfn = ADDR2PFN(frame); |
1114 | count_t znum = find_zone(pfn, NULL); |
1083 | count_t znum = find_zone(pfn, 1, NULL); |
1115 | 1084 | ||
1116 | ASSERT(znum != (count_t) -1); |
1085 | ASSERT(znum != (count_t) -1); |
1117 | 1086 | ||
1118 | zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); |
1087 | zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); |
1119 | 1088 | ||
Line 1148... | Line 1117... | ||
1148 | spinlock_lock(&zones.lock); |
1117 | spinlock_lock(&zones.lock); |
1149 | 1118 | ||
1150 | /* |
1119 | /* |
1151 | * First, find host frame zone for addr. |
1120 | * First, find host frame zone for addr. |
1152 | */ |
1121 | */ |
1153 | count_t znum = find_zone(pfn, NULL); |
1122 | count_t znum = find_zone(pfn, 1, NULL); |
1154 | 1123 | ||
1155 | ASSERT(znum != (count_t) -1); |
1124 | ASSERT(znum != (count_t) -1); |
1156 | 1125 | ||
1157 | zones.info[znum].frames[pfn - zones.info[znum].base].refcount++; |
1126 | zones.info[znum].frames[pfn - zones.info[znum].base].refcount++; |
1158 | 1127 | ||
Line 1166... | Line 1135... | ||
1166 | ipl_t ipl = interrupts_disable(); |
1135 | ipl_t ipl = interrupts_disable(); |
1167 | spinlock_lock(&zones.lock); |
1136 | spinlock_lock(&zones.lock); |
1168 | 1137 | ||
1169 | count_t i; |
1138 | count_t i; |
1170 | for (i = 0; i < count; i++) { |
1139 | for (i = 0; i < count; i++) { |
1171 | count_t znum = find_zone(start + i, 0); |
1140 | count_t znum = find_zone(start + i, 1, 0); |
1172 | if (znum == (count_t) -1) /* PFN not found */ |
1141 | if (znum == (count_t) -1) /* PFN not found */ |
1173 | continue; |
1142 | continue; |
1174 | 1143 | ||
1175 | zone_mark_unavailable(&zones.info[znum], |
1144 | zone_mark_unavailable(&zones.info[znum], |
1176 | start + i - zones.info[znum].base); |
1145 | start + i - zones.info[znum].base); |
Line 1235... | Line 1204... | ||
1235 | 1204 | ||
1236 | /** Prints list of zones. */ |
1205 | /** Prints list of zones. */ |
1237 | void zone_print_list(void) |
1206 | void zone_print_list(void) |
1238 | { |
1207 | { |
1239 | #ifdef __32_BITS__ |
1208 | #ifdef __32_BITS__ |
1240 | printf("# base address flags free frames busy frames\n"); |
1209 | printf("# base address frames flags free frames busy frames\n"); |
1241 | printf("-- ------------ -------- ------------ ------------\n"); |
1210 | printf("-- ------------ ------------ -------- ------------ ------------\n"); |
1242 | #endif |
1211 | #endif |
1243 | 1212 | ||
1244 | #ifdef __64_BITS__ |
1213 | #ifdef __64_BITS__ |
1245 | printf("# base address flags free frames busy frames\n"); |
1214 | printf("# base address frames flags free frames busy frames\n"); |
1246 | printf("-- -------------------- -------- ------------ ------------\n"); |
1215 | printf("-- -------------------- ------------ -------- ------------ ------------\n"); |
1247 | #endif |
1216 | #endif |
1248 | 1217 | ||
1249 | /* |
1218 | /* |
1250 | * Because printing may require allocation of memory, we may not hold |
1219 | * Because printing may require allocation of memory, we may not hold |
1251 | * the frame allocator locks when printing zone statistics. Therefore, |
1220 | * the frame allocator locks when printing zone statistics. Therefore, |
Line 1267... | Line 1236... | ||
1267 | interrupts_restore(ipl); |
1236 | interrupts_restore(ipl); |
1268 | break; |
1237 | break; |
1269 | } |
1238 | } |
1270 | 1239 | ||
1271 | uintptr_t base = PFN2ADDR(zones.info[i].base); |
1240 | uintptr_t base = PFN2ADDR(zones.info[i].base); |
- | 1241 | count_t count = zones.info[i].count; |
|
1272 | zone_flags_t flags = zones.info[i].flags; |
1242 | zone_flags_t flags = zones.info[i].flags; |
1273 | count_t free_count = zones.info[i].free_count; |
1243 | count_t free_count = zones.info[i].free_count; |
1274 | count_t busy_count = zones.info[i].busy_count; |
1244 | count_t busy_count = zones.info[i].busy_count; |
1275 | 1245 | ||
1276 | spinlock_unlock(&zones.lock); |
1246 | spinlock_unlock(&zones.lock); |
1277 | interrupts_restore(ipl); |
1247 | interrupts_restore(ipl); |
1278 | 1248 | ||
1279 | bool available = zone_flags_available(flags); |
1249 | bool available = zone_flags_available(flags); |
1280 | 1250 | ||
- | 1251 | printf("%-2" PRIc, i); |
|
- | 1252 | ||
1281 | #ifdef __32_BITS__ |
1253 | #ifdef __32_BITS__ |
1282 | printf("%-2" PRIc " %10p %c%c%c ", i, base, |
1254 | printf(" %10p", base); |
1283 | available ? 'A' : ' ', |
- | |
1284 | (flags & ZONE_RESERVED) ? 'R' : ' ', |
- | |
1285 | (flags & ZONE_FIRMWARE) ? 'F' : ' '); |
- | |
1286 | #endif |
1255 | #endif |
1287 | 1256 | ||
1288 | #ifdef __64_BITS__ |
1257 | #ifdef __64_BITS__ |
- | 1258 | printf(" %18p", base); |
|
- | 1259 | #endif |
|
- | 1260 | ||
1289 | printf("%-2" PRIc " %18p %c%c%c ", i, base, |
1261 | printf(" %12" PRIc " %c%c%c ", count, |
1290 | available ? 'A' : ' ', |
1262 | available ? 'A' : ' ', |
1291 | (flags & ZONE_RESERVED) ? 'R' : ' ', |
1263 | (flags & ZONE_RESERVED) ? 'R' : ' ', |
1292 | (flags & ZONE_FIRMWARE) ? 'F' : ' '); |
1264 | (flags & ZONE_FIRMWARE) ? 'F' : ' '); |
1293 | #endif |
- | |
1294 | 1265 | ||
1295 | if (available) |
1266 | if (available) |
1296 | printf("%12" PRIc " %12" PRIc, |
1267 | printf("%12" PRIc " %12" PRIc, |
1297 | free_count, busy_count); |
1268 | free_count, busy_count); |
- | 1269 | ||
1298 | printf("\n"); |
1270 | printf("\n"); |
1299 | } |
1271 | } |
1300 | } |
1272 | } |
1301 | 1273 | ||
1302 | /** Prints zone details. |
1274 | /** Prints zone details. |