Rev 3972 | Rev 4048 | 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. |