Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f72906c in mainline


Ignore:
Timestamp:
2013-09-12T18:09:51Z (8 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master
Children:
69f5f19
Parents:
b11f6fb
Message:

prefer allocating physical frames from the so called low priority memory (< 16 MB on ia32 and amd64)
this saves the high priority memory for legacy DMA transfers, etc.

Location:
kernel
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/abs32le/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0
     42
    4143#include <typedefs.h>
    4244
  • kernel/arch/amd64/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0x1000
     42
    4143#ifndef __ASM__
    4244
  • kernel/arch/arm32/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_WIDTH  12  /* 4KB frames */
    4040#define FRAME_SIZE   (1 << FRAME_WIDTH)
     41
     42#define FRAME_LOWPRIO  0
    4143
    4244#ifndef __ASM__
  • kernel/arch/ia32/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0x1000
     42
    4143#ifndef __ASM__
    4244
  • kernel/arch/ia64/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0
     42
    4143#ifndef __ASM__
    4244
  • kernel/arch/mips32/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0
     42
    4143#ifndef __ASM__
    4244
  • kernel/arch/mips64/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0
     42
    4143#ifndef __ASM__
    4244
  • kernel/arch/ppc32/include/arch/mm/frame.h

    rb11f6fb rf72906c  
    3939#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
     41#define FRAME_LOWPRIO  0
     42
    4143#ifndef __ASM__
    4244
  • kernel/arch/sparc64/include/arch/mm/sun4u/frame.h

    rb11f6fb rf72906c  
    2727 */
    2828
    29 /** @addtogroup sparc64mm       
     29/** @addtogroup sparc64mm
    3030 * @{
    3131 */
     
    4141 * Therefore, the kernel uses 8K only internally on the TLB and TSB levels.
    4242 */
    43 #define MMU_FRAME_WIDTH         13      /* 8K */
    44 #define MMU_FRAME_SIZE          (1 << MMU_FRAME_WIDTH)
     43#define MMU_FRAME_WIDTH  13  /* 8K */
     44#define MMU_FRAME_SIZE   (1 << MMU_FRAME_WIDTH)
    4545
    4646/*
     
    4949 * each 16K page with a pair of adjacent 8K pages.
    5050 */
    51 #define FRAME_WIDTH             14      /* 16K */
    52 #define FRAME_SIZE              (1 << FRAME_WIDTH)
     51#define FRAME_WIDTH  14  /* 16K */
     52#define FRAME_SIZE   (1 << FRAME_WIDTH)
     53
     54#define FRAME_LOWPRIO  0
    5355
    5456#ifndef __ASM__
  • kernel/arch/sparc64/include/arch/mm/sun4v/frame.h

    rb11f6fb rf72906c  
    2727 */
    2828
    29 /** @addtogroup sparc64mm       
     29/** @addtogroup sparc64mm
    3030 * @{
    3131 */
     
    3636#define KERN_sparc64_sun4v_FRAME_H_
    3737
    38 #define MMU_FRAME_WIDTH         13      /* 8K */
    39 #define MMU_FRAME_SIZE          (1 << MMU_FRAME_WIDTH)
     38#define MMU_FRAME_WIDTH  13  /* 8K */
     39#define MMU_FRAME_SIZE   (1 << MMU_FRAME_WIDTH)
    4040
    41 #define FRAME_WIDTH             13
    42 #define FRAME_SIZE              (1 << FRAME_WIDTH)
     41#define FRAME_WIDTH  13
     42#define FRAME_SIZE   (1 << FRAME_WIDTH)
     43
     44#define FRAME_LOWPRIO  0
    4345
    4446#endif
  • kernel/generic/include/adt/bitmap.h

    rb11f6fb rf72906c  
    8181extern void bitmap_clear_range(bitmap_t *, size_t, size_t);
    8282
    83 extern int bitmap_allocate_range(bitmap_t *, size_t, size_t, size_t, size_t *);
     83extern int bitmap_allocate_range(bitmap_t *, size_t, size_t, size_t, size_t,
     84    size_t *);
    8485extern void bitmap_copy(bitmap_t *, bitmap_t *, size_t);
    8586
  • kernel/generic/include/mm/frame.h

    rb11f6fb rf72906c  
    131131extern void frame_init(void);
    132132extern bool frame_adjust_zone_bounds(bool, uintptr_t *, size_t *);
    133 extern uintptr_t frame_alloc_generic(size_t, frame_flags_t, uintptr_t, size_t *);
     133extern uintptr_t frame_alloc_generic(size_t, frame_flags_t, uintptr_t,
     134    size_t *);
    134135extern uintptr_t frame_alloc(size_t, frame_flags_t, uintptr_t);
    135 extern uintptr_t frame_alloc_noreserve(size_t, frame_flags_t, uintptr_t);
    136136extern void frame_free_generic(uintptr_t, size_t, frame_flags_t);
    137137extern void frame_free(uintptr_t, size_t);
  • kernel/generic/src/adt/bitmap.c

    rb11f6fb rf72906c  
    258258 * @param count      Number of continuous zero bits to find.
    259259 * @param base       Address of the first bit in the bitmap.
     260 * @param prefered   Prefered address to start searching from.
    260261 * @param constraint Constraint for the address of the first zero bit.
    261262 * @param index      Place to store the index of the first zero
     
    269270 */
    270271int bitmap_allocate_range(bitmap_t *bitmap, size_t count, size_t base,
    271     size_t constraint, size_t *index)
     272    size_t prefered, size_t constraint, size_t *index)
    272273{
    273274        if (count == 0)
     
    275276       
    276277        size_t size = bitmap_size(bitmap->elements);
     278        size_t next_fit = bitmap->next_fit;
     279       
     280        /*
     281         * Adjust the next-fit value according to the address
     282         * the caller prefers to start the search at.
     283         */
     284        if ((prefered > base) && (prefered < base + bitmap->elements)) {
     285                size_t prefered_fit = (prefered - base) / BITMAP_ELEMENT;
     286               
     287                if (prefered_fit > next_fit)
     288                        next_fit = prefered_fit;
     289        }
    277290       
    278291        for (size_t pos = 0; pos < size; pos++) {
    279                 size_t byte = (bitmap->next_fit + pos) % size;
     292                size_t byte = (next_fit + pos) % size;
    280293               
    281294                /* Skip if the current byte has all bits set */
  • kernel/generic/src/ddi/ddi.c

    rb11f6fb rf72906c  
    329329       
    330330        size_t frames = SIZE2FRAMES(size);
    331         *phys = frame_alloc_noreserve(frames, 0, constraint);
     331        *phys = frame_alloc(frames, FRAME_NO_RESERVE, constraint);
    332332        if (*phys == 0)
    333333                return ENOMEM;
  • kernel/generic/src/mm/frame.c

    rb11f6fb rf72906c  
    234234         * the bitmap if the last argument is NULL.
    235235         */
     236       
    236237        return ((zone->flags & ZONE_AVAILABLE) &&
    237238            bitmap_allocate_range(&zone->bitmap, count, zone->base,
    238             constraint, NULL));
     239            FRAME_LOWPRIO, constraint, NULL));
     240}
     241
     242/** Find a zone that can allocate specified number of frames
     243 *
     244 * This function searches among all zones. Assume interrupts are
     245 * disabled and zones lock is locked.
     246 *
     247 * @param count      Number of free frames we are trying to find.
     248 * @param flags      Required flags of the zone.
     249 * @param constraint Indication of bits that cannot be set in the
     250 *                   physical frame number of the first allocated frame.
     251 * @param hint       Preferred zone.
     252 *
     253 * @return Zone that can allocate specified number of frames.
     254 * @return -1 if no zone can satisfy the request.
     255 *
     256 */
     257NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags,
     258    pfn_t constraint, size_t hint)
     259{
     260        for (size_t pos = 0; pos < zones.count; pos++) {
     261                size_t i = (pos + hint) % zones.count;
     262               
     263                /* Check whether the zone meets the search criteria. */
     264                if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
     265                        continue;
     266               
     267                /* Check if the zone can satisfy the allocation request. */
     268                if (zone_can_alloc(&zones.info[i], count, constraint))
     269                        return i;
     270        }
     271       
     272        return (size_t) -1;
     273}
     274
     275/** Check if frame range  priority memory
     276 *
     277 * @param pfn   Starting frame.
     278 * @param count Number of frames.
     279 *
     280 * @return True if the range contains only priority memory.
     281 *
     282 */
     283NO_TRACE static bool is_high_priority(pfn_t base, size_t count)
     284{
     285        return (base + count <= FRAME_LOWPRIO);
     286}
     287
     288/** Find a zone that can allocate specified number of frames
     289 *
     290 * This function ignores zones that contain only high-priority
     291 * memory. Assume interrupts are disabled and zones lock is locked.
     292 *
     293 * @param count      Number of free frames we are trying to find.
     294 * @param flags      Required flags of the zone.
     295 * @param constraint Indication of bits that cannot be set in the
     296 *                   physical frame number of the first allocated frame.
     297 * @param hint       Preferred zone.
     298 *
     299 * @return Zone that can allocate specified number of frames.
     300 * @return -1 if no low-priority zone can satisfy the request.
     301 *
     302 */
     303NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags,
     304    pfn_t constraint, size_t hint)
     305{       
     306        for (size_t pos = 0; pos < zones.count; pos++) {
     307                size_t i = (pos + hint) % zones.count;
     308               
     309                /* Skip zones containing only high-priority memory. */
     310                if (is_high_priority(zones.info[i].base, zones.info[i].count))
     311                        continue;
     312               
     313                /* Check whether the zone meets the search criteria. */
     314                if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
     315                        continue;
     316               
     317                /* Check if the zone can satisfy the allocation request. */
     318                if (zone_can_alloc(&zones.info[i], count, constraint))
     319                        return i;
     320        }
     321       
     322        return (size_t) -1;
    239323}
    240324
     
    248332 * @param constraint Indication of bits that cannot be set in the
    249333 *                   physical frame number of the first allocated frame.
    250  * @param hind       Preferred zone.
     334 * @param hint       Preferred zone.
     335 *
     336 * @return Zone that can allocate specified number of frames.
     337 * @return -1 if no zone can satisfy the request.
    251338 *
    252339 */
     
    257344                hint = 0;
    258345       
    259         size_t i = hint;
    260         do {
    261                 /*
    262                  * Check whether the zone meets the search criteria.
    263                  */
    264                 if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
    265                         /*
    266                          * Check if the zone can satisfy the allocation request.
    267                          */
    268                         if (zone_can_alloc(&zones.info[i], count, constraint))
    269                                 return i;
    270                 }
    271                
    272                 i++;
    273                 if (i >= zones.count)
    274                         i = 0;
    275                
    276         } while (i != hint);
    277        
    278         return (size_t) -1;
     346        /*
     347         * Prefer zones with low-priority memory over
     348         * zones with high-priority memory.
     349         */
     350       
     351        size_t znum = find_free_zone_lowprio(count, flags, constraint, hint);
     352        if (znum != (size_t) -1)
     353                return znum;
     354       
     355        /* Take all zones into account */
     356        return find_free_zone_all(count, flags, constraint, hint);
    279357}
    280358
     
    312390        size_t index;
    313391        int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
    314             constraint, &index);
     392            FRAME_LOWPRIO, constraint, &index);
    315393       
    316394        ASSERT(avail);
     
    883961}
    884962
    885 uintptr_t frame_alloc_noreserve(size_t count, frame_flags_t flags,
    886     uintptr_t constraint)
    887 {
    888         return frame_alloc_generic(count, flags | FRAME_NO_RESERVE, constraint,
    889             NULL);
    890 }
    891 
    892963/** Free frames of physical memory.
    893964 *
     
    11371208        /*
    11381209         * Because printing may require allocation of memory, we may not hold
    1139          * the frame allocator locks when printing zone statistics.  Therefore,
     1210         * the frame allocator locks when printing zone statistics. Therefore,
    11401211         * we simply gather the statistics under the protection of the locks and
    11411212         * print the statistics when the locks have been released.
     
    11461217         */
    11471218       
     1219        size_t free_lowmem = 0;
     1220        size_t free_highmem = 0;
     1221        size_t free_highprio = 0;
     1222       
    11481223        for (size_t i = 0;; i++) {
    11491224                irq_spinlock_lock(&zones.lock, true);
     
    11541229                }
    11551230               
    1156                 uintptr_t base = PFN2ADDR(zones.info[i].base);
     1231                pfn_t fbase = zones.info[i].base;
     1232                uintptr_t base = PFN2ADDR(fbase);
    11571233                size_t count = zones.info[i].count;
    11581234                zone_flags_t flags = zones.info[i].flags;
     
    11601236                size_t busy_count = zones.info[i].busy_count;
    11611237               
     1238                bool available = ((flags & ZONE_AVAILABLE) != 0);
     1239                bool lowmem = ((flags & ZONE_LOWMEM) != 0);
     1240                bool highmem = ((flags & ZONE_HIGHMEM) != 0);
     1241                bool highprio = is_high_priority(fbase, count);
     1242               
     1243                if (available) {
     1244                        if (lowmem)
     1245                                free_lowmem += free_count;
     1246                       
     1247                        if (highmem)
     1248                                free_highmem += free_count;
     1249                       
     1250                        if (highprio) {
     1251                                free_highprio += free_count;
     1252                        } else {
     1253                                /*
     1254                                 * Walk all frames of the zone and examine
     1255                                 * all high priority memory to get accurate
     1256                                 * statistics.
     1257                                 */
     1258                               
     1259                                for (size_t index = 0; index < count; index++) {
     1260                                        if (is_high_priority(fbase + index, 0)) {
     1261                                                if (!bitmap_get(&zones.info[i].bitmap, index))
     1262                                                        free_highprio++;
     1263                                        } else
     1264                                                break;
     1265                                }
     1266                        }
     1267                }
     1268               
    11621269                irq_spinlock_unlock(&zones.lock, true);
    1163                
    1164                 bool available = ((flags & ZONE_AVAILABLE) != 0);
    11651270               
    11661271                printf("%-4zu", i);
     
    11871292                printf("\n");
    11881293        }
     1294       
     1295        printf("\n");
     1296       
     1297        uint64_t size;
     1298        const char *size_suffix;
     1299       
     1300        bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
     1301            false);
     1302        printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
     1303            free_lowmem, size, size_suffix);
     1304       
     1305        bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
     1306            false);
     1307        printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
     1308            free_highmem, size, size_suffix);
     1309       
     1310        bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
     1311            false);
     1312        printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
     1313            free_highprio, size, size_suffix);
    11891314}
    11901315
     
    12121337        }
    12131338       
    1214         uintptr_t base = PFN2ADDR(zones.info[znum].base);
     1339        size_t free_lowmem = 0;
     1340        size_t free_highmem = 0;
     1341        size_t free_highprio = 0;
     1342       
     1343        pfn_t fbase = zones.info[znum].base;
     1344        uintptr_t base = PFN2ADDR(fbase);
    12151345        zone_flags_t flags = zones.info[znum].flags;
    12161346        size_t count = zones.info[znum].count;
     
    12181348        size_t busy_count = zones.info[znum].busy_count;
    12191349       
     1350        bool available = ((flags & ZONE_AVAILABLE) != 0);
     1351        bool lowmem = ((flags & ZONE_LOWMEM) != 0);
     1352        bool highmem = ((flags & ZONE_HIGHMEM) != 0);
     1353        bool highprio = is_high_priority(fbase, count);
     1354       
     1355        if (available) {
     1356                if (lowmem)
     1357                        free_lowmem = free_count;
     1358               
     1359                if (highmem)
     1360                        free_highmem = free_count;
     1361               
     1362                if (highprio) {
     1363                        free_highprio = free_count;
     1364                } else {
     1365                        /*
     1366                         * Walk all frames of the zone and examine
     1367                         * all high priority memory to get accurate
     1368                         * statistics.
     1369                         */
     1370                       
     1371                        for (size_t index = 0; index < count; index++) {
     1372                                if (is_high_priority(fbase + index, 0)) {
     1373                                        if (!bitmap_get(&zones.info[znum].bitmap, index))
     1374                                                free_highprio++;
     1375                                } else
     1376                                        break;
     1377                        }
     1378                }
     1379        }
     1380       
    12201381        irq_spinlock_unlock(&zones.lock, true);
    1221        
    1222         bool available = ((flags & ZONE_AVAILABLE) != 0);
    12231382       
    12241383        uint64_t size;
    12251384        const char *size_suffix;
     1385       
    12261386        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
    12271387       
    1228         printf("Zone number:       %zu\n", znum);
    1229         printf("Zone base address: %p\n", (void *) base);
    1230         printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
     1388        printf("Zone number:             %zu\n", znum);
     1389        printf("Zone base address:       %p\n", (void *) base);
     1390        printf("Zone size:               %zu frames (%" PRIu64 " %s)\n", count,
    12311391            size, size_suffix);
    1232         printf("Zone flags:        %c%c%c%c%c\n",
     1392        printf("Zone flags:              %c%c%c%c%c\n",
    12331393            available ? 'A' : '-',
    12341394            (flags & ZONE_RESERVED) ? 'R' : '-',
     
    12401400                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
    12411401                    false);
    1242                 printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
     1402                printf("Allocated space:         %zu frames (%" PRIu64 " %s)\n",
    12431403                    busy_count, size, size_suffix);
     1404               
    12441405                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
    12451406                    false);
    1246                 printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
     1407                printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
    12471408                    free_count, size, size_suffix);
     1409               
     1410                bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
     1411                    false);
     1412                printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
     1413                    free_lowmem, size, size_suffix);
     1414               
     1415                bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
     1416                    false);
     1417                printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
     1418                    free_highmem, size, size_suffix);
     1419               
     1420                bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
     1421                    false);
     1422                printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
     1423                    free_highprio, size, size_suffix);
    12481424        }
    12491425}
Note: See TracChangeset for help on using the changeset viewer.