Changeset 3375bd4 in mainline for kernel/generic


Ignore:
Timestamp:
2011-05-17T07:44:17Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
04c418d, 2586860, 5e6e50b
Parents:
72cd53d (diff), 0d8a304 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

Conflicts:
kernel/generic/src/console/console.c

size of klog, taken upstream

uspace/app/klog/klog.c

taken upstream (upstream fixed the broken output on huge load)

uspace/app/tester/Makefile
uspace/app/tester/tester.c
uspace/app/tester/tester.h

merged without problems

uspace/lib/c/include/as.h

merged without problems (upstream use bare declarations)

Also needed to fix some missing includes.

Location:
kernel/generic
Files:
2 added
20 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/event.h

    r72cd53d r3375bd4  
    5151        /** Counter. */
    5252        size_t counter;
     53        /** Masked flag. */
     54        bool masked;
     55        /** Unmask callback. */
     56        void (*unmask_cb)(void);
    5357} event_t;
    5458
    5559extern void event_init(void);
     60extern void event_cleanup_answerbox(answerbox_t *);
     61extern void event_set_unmask_callback(event_type_t, void (*)(void));
     62
     63#define event_notify_0(e, m) \
     64        event_notify((e), (m), 0, 0, 0, 0, 0)
     65#define event_notify_1(e, m, a1) \
     66        event_notify((e), (m), (a1), 0, 0, 0, 0)
     67#define event_notify_2(e, m, a1, a2) \
     68        event_notify((e), (m), (a1), (a2), 0, 0, 0)
     69#define event_notify_3(e, m, a1, a2, a3) \
     70        event_notify((e), (m), (a1), (a2), (a3), 0, 0)
     71#define event_notify_4(e, m, a1, a2, a3, a4) \
     72        event_notify((e), (m), (a1), (a2), (a3), (a4), 0)
     73#define event_notify_5(e, m, a1, a2, a3, a4, a5) \
     74        event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
     75
     76extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
     77    sysarg_t, sysarg_t);
     78
    5679extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
    57 extern bool event_is_subscribed(event_type_t);
    58 extern void event_cleanup_answerbox(answerbox_t *);
    59 
    60 #define event_notify_0(e) \
    61         event_notify((e), 0, 0, 0, 0, 0)
    62 #define event_notify_1(e, a1) \
    63         event_notify((e), (a1), 0, 0, 0, 0)
    64 #define event_notify_2(e, a1, a2) \
    65         event_notify((e), (a1), (a2), 0, 0, 0)
    66 #define event_notify_3(e, a1, a2, a3) \
    67         event_notify((e), (a1), (a2), (a3), 0, 0)
    68 #define event_notify_4(e, a1, a2, a3, a4) \
    69         event_notify((e), (a1), (a2), (a3), (a4), 0)
    70 #define event_notify_5(e, a1, a2, a3, a4, a5) \
    71         event_notify((e), (a1), (a2), (a3), (a4), (a5))
    72 
    73 extern void event_notify(event_type_t, sysarg_t, sysarg_t, sysarg_t,
    74     sysarg_t, sysarg_t);
     80extern sysarg_t sys_event_unmask(sysarg_t);
    7581
    7682#endif
  • kernel/generic/include/ipc/event_types.h

    r72cd53d r3375bd4  
    3939        /** New data available in kernel log */
    4040        EVENT_KLOG = 0,
    41         /** Returning from kernel console to userspace */
     41        /** Returning from kernel console to uspace */
    4242        EVENT_KCONSOLE,
    4343        /** A task/thread has faulted and will be terminated */
  • kernel/generic/include/macros.h

    r72cd53d r3375bd4  
    9595        overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy))
    9696
    97 #define SIZE2KB(size)  ((size) >> 10)
    98 #define SIZE2MB(size)  ((size) >> 20)
    99 
    100 #define KB2SIZE(kb)  ((kb) << 10)
    101 #define MB2SIZE(mb)  ((mb) << 20)
     97#define KiB2SIZE(kb)  ((kb) << 10)
     98#define MiB2SIZE(mb)  ((mb) << 20)
    10299
    103100#define STRING(arg)      STRING_ARG(arg)
  • kernel/generic/include/mm/as.h

    r72cd53d r3375bd4  
    238238/** Address space area backend structure. */
    239239typedef struct mem_backend {
     240        bool (* create)(as_area_t *);
     241        bool (* resize)(as_area_t *, size_t);
     242        void (* share)(as_area_t *);
     243        void (* destroy)(as_area_t *);
     244
    240245        int (* page_fault)(as_area_t *, uintptr_t, pf_access_t);
    241246        void (* frame_free)(as_area_t *, uintptr_t, uintptr_t);
    242         void (* share)(as_area_t *);
    243247} mem_backend_t;
    244248
  • kernel/generic/include/mm/frame.h

    r72cd53d r3375bd4  
    6262
    6363/** Convert the frame address to kernel VA. */
    64 #define FRAME_KA          0x01
     64#define FRAME_KA          0x1
    6565/** Do not panic and do not sleep on failure. */
    66 #define FRAME_ATOMIC      0x02
     66#define FRAME_ATOMIC      0x2
    6767/** Do not start reclaiming when no free memory. */
    68 #define FRAME_NO_RECLAIM  0x04
     68#define FRAME_NO_RECLAIM  0x4
     69/** Do not reserve / unreserve memory. */
     70#define FRAME_NO_RESERVE  0x8
    6971
    7072typedef uint8_t zone_flags_t;
    7173
    7274/** Available zone (free for allocation) */
    73 #define ZONE_AVAILABLE  0x00
     75#define ZONE_AVAILABLE  0x0
    7476/** Zone is reserved (not available for allocation) */
    75 #define ZONE_RESERVED   0x08
     77#define ZONE_RESERVED   0x8
    7678/** Zone is used by firmware (not available for allocation) */
    7779#define ZONE_FIRMWARE   0x10
     
    8587        uint8_t buddy_order;  /**< Buddy system block order */
    8688        link_t buddy_link;    /**< Link to the next free block inside
    87                                one order */
     89                                   one order */
    8890        void *parent;         /**< If allocated by slab, this points there */
    8991} frame_t;
     
    9193typedef struct {
    9294        pfn_t base;                    /**< Frame_no of the first frame
    93                                         in the frames array */
     95                                            in the frames array */
    9496        size_t count;                  /**< Size of zone */
    9597        size_t free_count;             /**< Number of free frame_t
    96                                         structures */
     98                                            structures */
    9799        size_t busy_count;             /**< Number of busy frame_t
    98                                         structures */
     100                                            structures */
    99101        zone_flags_t flags;            /**< Type of the zone */
    100102       
    101103        frame_t *frames;               /**< Array of frame_t structures
    102                                         in this zone */
     104                                            in this zone */
    103105        buddy_system_t *buddy_system;  /**< Buddy system for the zone */
    104106} zone_t;
     
    146148    ((~(((sysarg_t) -1) << (order)) & (index)) == 0)
    147149#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
    148     (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
     150    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
    149151#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
    150     (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
     152    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
    151153#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
    152     (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
     154    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
    153155#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
    154     (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
    155 
    156 #define frame_alloc(order, flags) \
    157     frame_alloc_generic(order, flags, NULL)
     156    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
    158157
    159158extern void frame_init(void);
    160159extern void *frame_alloc_generic(uint8_t, frame_flags_t, size_t *);
     160extern void *frame_alloc(uint8_t, frame_flags_t);
     161extern void *frame_alloc_noreserve(uint8_t, frame_flags_t);
     162extern void frame_free_generic(uintptr_t, frame_flags_t);
    161163extern void frame_free(uintptr_t);
     164extern void frame_free_noreserve(uintptr_t);
    162165extern void frame_reference_add(pfn_t);
     166extern size_t frame_total_free_get(void);
    163167
    164 extern size_t find_zone(pfn_t frame, size_t count, size_t hint);
     168extern size_t find_zone(pfn_t, size_t, size_t);
    165169extern size_t zone_create(pfn_t, size_t, pfn_t, zone_flags_t);
    166170extern void *frame_get_parent(pfn_t, size_t);
  • kernel/generic/include/str.h

    r72cd53d r3375bd4  
    9999extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *);
    100100
    101 extern void order_suffix(const uint64_t val, uint64_t *rv, char *suffix);
     101extern void order_suffix(const uint64_t, uint64_t *, char *);
     102extern void bin_order_suffix(const uint64_t, uint64_t *, const char **, bool);
    102103
    103104#endif
  • kernel/generic/include/syscall/syscall.h

    r72cd53d r3375bd4  
    7878       
    7979        SYS_EVENT_SUBSCRIBE,
     80        SYS_EVENT_UNMASK,
    8081       
    8182        SYS_CAP_GRANT,
  • kernel/generic/src/console/cmd.c

    r72cd53d r3375bd4  
    11071107        release_console();
    11081108       
    1109         event_notify_0(EVENT_KCONSOLE);
     1109        event_notify_0(EVENT_KCONSOLE, false);
    11101110        indev_pop_character(stdin);
    11111111       
  • kernel/generic/src/console/console.c

    r72cd53d r3375bd4  
    5353#include <str.h>
    5454
    55 /*
    56  * devman produces a lot of output and by giving so many pages
    57  * we to allow /app/klog to catch-up.
    58  */
    59 #ifdef CONFIG_DEVMAN_EARLY_LAUNCH
    60 #define KLOG_PAGES    64
    61 #else
    62 #define KLOG_PAGES    4
    63 #endif
    64 
     55#define KLOG_PAGES    8
    6556#define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
    6657#define KLOG_LATENCY  8
     
    174165        sysinfo_set_item_val("klog.faddr", NULL, (sysarg_t) faddr);
    175166        sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES);
     167
     168        event_set_unmask_callback(EVENT_KLOG, klog_update);
    176169       
    177170        spinlock_lock(&klog_lock);
     
    274267        spinlock_lock(&klog_lock);
    275268       
    276         if ((klog_inited) && (event_is_subscribed(EVENT_KLOG)) && (klog_uspace > 0)) {
    277                 event_notify_3(EVENT_KLOG, klog_start, klog_len, klog_uspace);
    278                 klog_uspace = 0;
     269        if ((klog_inited) && (klog_uspace > 0)) {
     270                if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
     271                    klog_uspace) == EOK)
     272                        klog_uspace = 0;
    279273        }
    280274       
  • kernel/generic/src/ipc/event.c

    r72cd53d r3375bd4  
    4848static event_t events[EVENT_END];
    4949
    50 /** Initialize kernel events. */
     50/** Initialize kernel events.
     51 *
     52 */
    5153void event_init(void)
    5254{
    53         unsigned int i;
    54        
    55         for (i = 0; i < EVENT_END; i++) {
     55        for (unsigned int i = 0; i < EVENT_END; i++) {
    5656                spinlock_initialize(&events[i].lock, "event.lock");
    5757                events[i].answerbox = NULL;
    5858                events[i].counter = 0;
    5959                events[i].imethod = 0;
     60                events[i].masked = false;
     61                events[i].unmask_cb = NULL;
    6062        }
    6163}
    6264
     65/** Unsubscribe kernel events associated with an answerbox
     66 *
     67 * @param answerbox Answerbox to be unsubscribed.
     68 *
     69 */
     70void event_cleanup_answerbox(answerbox_t *answerbox)
     71{
     72        for (unsigned int i = 0; i < EVENT_END; i++) {
     73                spinlock_lock(&events[i].lock);
     74               
     75                if (events[i].answerbox == answerbox) {
     76                        events[i].answerbox = NULL;
     77                        events[i].counter = 0;
     78                        events[i].imethod = 0;
     79                        events[i].masked = false;
     80                }
     81               
     82                spinlock_unlock(&events[i].lock);
     83        }
     84}
     85
     86/** Define a callback function for the event unmask event.
     87 *
     88 * @param evno Event type.
     89 * @param cb   Callback function to be called when the event is unmasked.
     90 *
     91 */
     92void event_set_unmask_callback(event_type_t evno, void (*cb)(void))
     93{
     94        ASSERT(evno < EVENT_END);
     95       
     96        spinlock_lock(&events[evno].lock);
     97        events[evno].unmask_cb = cb;
     98        spinlock_unlock(&events[evno].lock);
     99}
     100
     101/** Send kernel notification event
     102 *
     103 * @param evno Event type.
     104 * @param mask Mask further notifications after a successful
     105 *             sending.
     106 * @param a1   First argument.
     107 * @param a2   Second argument.
     108 * @param a3   Third argument.
     109 * @param a4   Fourth argument.
     110 * @param a5   Fifth argument.
     111 *
     112 * @return EOK if notification was successfully sent.
     113 * @return ENOMEM if the notification IPC message failed to allocate.
     114 * @return EBUSY if the notifications of the given type are
     115 *         currently masked.
     116 * @return ENOENT if the notifications of the given type are
     117 *         currently not subscribed.
     118 *
     119 */
     120int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2,
     121    sysarg_t a3, sysarg_t a4, sysarg_t a5)
     122{
     123        ASSERT(evno < EVENT_END);
     124       
     125        spinlock_lock(&events[evno].lock);
     126       
     127        int ret;
     128       
     129        if (events[evno].answerbox != NULL) {
     130                if (!events[evno].masked) {
     131                        call_t *call = ipc_call_alloc(FRAME_ATOMIC);
     132                       
     133                        if (call) {
     134                                call->flags |= IPC_CALL_NOTIF;
     135                                call->priv = ++events[evno].counter;
     136                               
     137                                IPC_SET_IMETHOD(call->data, events[evno].imethod);
     138                                IPC_SET_ARG1(call->data, a1);
     139                                IPC_SET_ARG2(call->data, a2);
     140                                IPC_SET_ARG3(call->data, a3);
     141                                IPC_SET_ARG4(call->data, a4);
     142                                IPC_SET_ARG5(call->data, a5);
     143                               
     144                                irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
     145                                list_append(&call->link, &events[evno].answerbox->irq_notifs);
     146                                irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
     147                               
     148                                waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
     149                               
     150                                if (mask)
     151                                        events[evno].masked = true;
     152                               
     153                                ret = EOK;
     154                        } else
     155                                ret = ENOMEM;
     156                } else
     157                        ret = EBUSY;
     158        } else
     159                ret = ENOENT;
     160       
     161        spinlock_unlock(&events[evno].lock);
     162       
     163        return ret;
     164}
     165
     166/** Subscribe event notifications
     167 *
     168 * @param evno      Event type.
     169 * @param imethod   IPC interface and method to be used for
     170 *                  the notifications.
     171 * @param answerbox Answerbox to send the notifications to.
     172 *
     173 * @return EOK if the subscription was successful.
     174 * @return EEXISTS if the notifications of the given type are
     175 *         already subscribed.
     176 *
     177 */
    63178static int event_subscribe(event_type_t evno, sysarg_t imethod,
    64179    answerbox_t *answerbox)
    65180{
    66         if (evno >= EVENT_END)
    67                 return ELIMIT;
     181        ASSERT(evno < EVENT_END);
    68182       
    69183        spinlock_lock(&events[evno].lock);
     
    75189                events[evno].imethod = imethod;
    76190                events[evno].counter = 0;
     191                events[evno].masked = false;
    77192                res = EOK;
    78193        } else
     
    84199}
    85200
     201/** Unmask event notifications
     202 *
     203 * @param evno Event type to unmask.
     204 *
     205 */
     206static void event_unmask(event_type_t evno)
     207{
     208        void (*cb)(void);
     209        ASSERT(evno < EVENT_END);
     210       
     211        spinlock_lock(&events[evno].lock);
     212        events[evno].masked = false;
     213        cb = events[evno].unmask_cb;
     214        spinlock_unlock(&events[evno].lock);
     215       
     216        /*
     217         * Check if there is an unmask callback function defined for this event.
     218         */
     219        if (cb)
     220            cb();
     221}
     222
     223/** Event notification syscall wrapper
     224 *
     225 * @param evno    Event type to subscribe.
     226 * @param imethod IPC interface and method to be used for
     227 *                the notifications.
     228 *
     229 * @return EOK on success.
     230 * @return ELIMIT on unknown event type.
     231 * @return EEXISTS if the notifications of the given type are
     232 *         already subscribed.
     233 *
     234 */
    86235sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    87236{
     237        if (evno >= EVENT_END)
     238                return ELIMIT;
     239       
    88240        return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    89241            imethod, &TASK->answerbox);
    90242}
    91243
    92 bool event_is_subscribed(event_type_t evno)
    93 {
    94         bool res;
    95        
    96         ASSERT(evno < EVENT_END);
    97        
    98         spinlock_lock(&events[evno].lock);
    99         res = events[evno].answerbox != NULL;
    100         spinlock_unlock(&events[evno].lock);
    101        
    102         return res;
    103 }
    104 
    105 
    106 void event_cleanup_answerbox(answerbox_t *answerbox)
    107 {
    108         unsigned int i;
    109        
    110         for (i = 0; i < EVENT_END; i++) {
    111                 spinlock_lock(&events[i].lock);
    112                 if (events[i].answerbox == answerbox) {
    113                         events[i].answerbox = NULL;
    114                         events[i].counter = 0;
    115                         events[i].imethod = 0;
    116                 }
    117                 spinlock_unlock(&events[i].lock);
    118         }
    119 }
    120 
    121 void event_notify(event_type_t evno, sysarg_t a1, sysarg_t a2, sysarg_t a3,
    122     sysarg_t a4, sysarg_t a5)
    123 {
    124         ASSERT(evno < EVENT_END);
    125        
    126         spinlock_lock(&events[evno].lock);
    127         if (events[evno].answerbox != NULL) {
    128                 call_t *call = ipc_call_alloc(FRAME_ATOMIC);
    129                 if (call) {
    130                         call->flags |= IPC_CALL_NOTIF;
    131                         call->priv = ++events[evno].counter;
    132                         IPC_SET_IMETHOD(call->data, events[evno].imethod);
    133                         IPC_SET_ARG1(call->data, a1);
    134                         IPC_SET_ARG2(call->data, a2);
    135                         IPC_SET_ARG3(call->data, a3);
    136                         IPC_SET_ARG4(call->data, a4);
    137                         IPC_SET_ARG5(call->data, a5);
    138                        
    139                         irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
    140                         list_append(&call->link, &events[evno].answerbox->irq_notifs);
    141                         irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
    142                        
    143                         waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
    144                 }
    145         }
    146         spinlock_unlock(&events[evno].lock);
     244/** Event notification unmask syscall wrapper
     245 *
     246 * Note that currently no tests are performed whether the calling
     247 * task is entitled to unmask the notifications. However, thanks
     248 * to the fact that notification masking is only a performance
     249 * optimization, this has probably no security implications.
     250 *
     251 * @param evno Event type to unmask.
     252 *
     253 * @return EOK on success.
     254 * @return ELIMIT on unknown event type.
     255 *
     256 */
     257sysarg_t sys_event_unmask(sysarg_t evno)
     258{
     259        if (evno >= EVENT_END)
     260                return ELIMIT;
     261       
     262        event_unmask((event_type_t) evno);
     263        return EOK;
    147264}
    148265
  • kernel/generic/src/lib/str.c

    r72cd53d r3375bd4  
    922922void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
    923923{
    924         if (val > 10000000000000000000ULL) {
    925                 *rv = val / 1000000000000000000ULL;
     924        if (val > UINT64_C(10000000000000000000)) {
     925                *rv = val / UINT64_C(1000000000000000000);
    926926                *suffix = 'Z';
    927         } else if (val > 1000000000000000000ULL) {
    928                 *rv = val / 1000000000000000ULL;
     927        } else if (val > UINT64_C(1000000000000000000)) {
     928                *rv = val / UINT64_C(1000000000000000);
    929929                *suffix = 'E';
    930         } else if (val > 1000000000000000ULL) {
    931                 *rv = val / 1000000000000ULL;
     930        } else if (val > UINT64_C(1000000000000000)) {
     931                *rv = val / UINT64_C(1000000000000);
    932932                *suffix = 'T';
    933         } else if (val > 1000000000000ULL) {
    934                 *rv = val / 1000000000ULL;
     933        } else if (val > UINT64_C(1000000000000)) {
     934                *rv = val / UINT64_C(1000000000);
    935935                *suffix = 'G';
    936         } else if (val > 1000000000ULL) {
    937                 *rv = val / 1000000ULL;
     936        } else if (val > UINT64_C(1000000000)) {
     937                *rv = val / UINT64_C(1000000);
    938938                *suffix = 'M';
    939         } else if (val > 1000000ULL) {
    940                 *rv = val / 1000ULL;
     939        } else if (val > UINT64_C(1000000)) {
     940                *rv = val / UINT64_C(1000);
    941941                *suffix = 'k';
    942942        } else {
     
    946946}
    947947
     948void bin_order_suffix(const uint64_t val, uint64_t *rv, const char **suffix,
     949    bool fixed)
     950{
     951        if (val > UINT64_C(1152921504606846976)) {
     952                *rv = val / UINT64_C(1125899906842624);
     953                *suffix = "EiB";
     954        } else if (val > UINT64_C(1125899906842624)) {
     955                *rv = val / UINT64_C(1099511627776);
     956                *suffix = "TiB";
     957        } else if (val > UINT64_C(1099511627776)) {
     958                *rv = val / UINT64_C(1073741824);
     959                *suffix = "GiB";
     960        } else if (val > UINT64_C(1073741824)) {
     961                *rv = val / UINT64_C(1048576);
     962                *suffix = "MiB";
     963        } else if (val > UINT64_C(1048576)) {
     964                *rv = val / UINT64_C(1024);
     965                *suffix = "KiB";
     966        } else {
     967                *rv = val;
     968                if (fixed)
     969                        *suffix = "B  ";
     970                else
     971                        *suffix = "B";
     972        }
     973}
     974
    948975/** @}
    949976 */
  • kernel/generic/src/main/main.c

    r72cd53d r3375bd4  
    7171#include <mm/as.h>
    7272#include <mm/slab.h>
     73#include <mm/reserve.h>
    7374#include <synch/waitq.h>
    7475#include <synch/futex.h>
     
    217218        ddi_init();
    218219        arch_post_mm_init();
     220        reserve_init();
    219221        arch_pre_smp_init();
    220222        smp_init();
     
    223225        slab_enable_cpucache();
    224226       
    225         printf("Detected %u CPU(s), %" PRIu64 " MiB free memory\n",
    226             config.cpu_count, SIZE2MB(zones_total_size()));
     227        uint64_t size;
     228        const char *size_suffix;
     229        bin_order_suffix(zones_total_size(), &size, &size_suffix, false);
     230        printf("Detected %u CPU(s), %" PRIu64 " %s free memory\n",
     231            config.cpu_count, size, size_suffix);
    227232       
    228233        cpu_init();
  • kernel/generic/src/mm/as.c

    r72cd53d r3375bd4  
    8080#include <arch/interrupt.h>
    8181
    82 #ifdef CONFIG_VIRT_IDX_DCACHE
    83 #include <arch/mm/cache.h>
    84 #endif /* CONFIG_VIRT_IDX_DCACHE */
    85 
    8682/**
    8783 * Each architecture decides what functions will be used to carry out
     
    447443        else
    448444                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
     445       
     446        if (area->backend && area->backend->create) {
     447                if (!area->backend->create(area)) {
     448                        free(area);
     449                        mutex_unlock(&as->lock);
     450                        return NULL;
     451                }
     452        }
    449453       
    450454        btree_create(&area->used_space);
     
    690694        }
    691695       
     696        if (area->backend && area->backend->resize) {
     697                if (!area->backend->resize(area, pages)) {
     698                        mutex_unlock(&area->lock);
     699                        mutex_unlock(&as->lock);
     700                        return ENOMEM;
     701                }
     702        }
     703       
    692704        area->pages = pages;
    693705       
     
    756768                return ENOENT;
    757769        }
     770
     771        if (area->backend && area->backend->destroy)
     772                area->backend->destroy(area);
    758773       
    759774        uintptr_t base = area->base;
  • kernel/generic/src/mm/backend_anon.c

    r72cd53d r3375bd4  
    3939#include <mm/as.h>
    4040#include <mm/page.h>
     41#include <mm/reserve.h>
    4142#include <genarch/mm/page_pt.h>
    4243#include <genarch/mm/page_ht.h>
     
    5152#include <arch.h>
    5253
    53 #ifdef CONFIG_VIRT_IDX_DCACHE
    54 #include <arch/mm/cache.h>
    55 #endif
    56 
    57 static int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
    58 static void anon_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
    59 static void anon_share(as_area_t *area);
     54static bool anon_create(as_area_t *);
     55static bool anon_resize(as_area_t *, size_t);
     56static void anon_share(as_area_t *);
     57static void anon_destroy(as_area_t *);
     58
     59static int anon_page_fault(as_area_t *, uintptr_t, pf_access_t);
     60static void anon_frame_free(as_area_t *, uintptr_t, uintptr_t);
    6061
    6162mem_backend_t anon_backend = {
     63        .create = anon_create,
     64        .resize = anon_resize,
     65        .share = anon_share,
     66        .destroy = anon_destroy,
     67
    6268        .page_fault = anon_page_fault,
    6369        .frame_free = anon_frame_free,
    64         .share = anon_share
    6570};
     71
     72bool anon_create(as_area_t *area)
     73{
     74        return reserve_try_alloc(area->pages);
     75}
     76
     77bool anon_resize(as_area_t *area, size_t new_pages)
     78{
     79        if (new_pages > area->pages)
     80                return reserve_try_alloc(new_pages - area->pages);
     81        else if (new_pages < area->pages)
     82                reserve_free(area->pages - new_pages);
     83
     84        return true;
     85}
     86
     87/** Share the anonymous address space area.
     88 *
     89 * Sharing of anonymous area is done by duplicating its entire mapping
     90 * to the pagemap. Page faults will primarily search for frames there.
     91 *
     92 * The address space and address space area must be already locked.
     93 *
     94 * @param area Address space area to be shared.
     95 */
     96void anon_share(as_area_t *area)
     97{
     98        link_t *cur;
     99
     100        ASSERT(mutex_locked(&area->as->lock));
     101        ASSERT(mutex_locked(&area->lock));
     102
     103        /*
     104         * Copy used portions of the area to sh_info's page map.
     105         */
     106        mutex_lock(&area->sh_info->lock);
     107        for (cur = area->used_space.leaf_head.next;
     108            cur != &area->used_space.leaf_head; cur = cur->next) {
     109                btree_node_t *node;
     110                unsigned int i;
     111               
     112                node = list_get_instance(cur, btree_node_t, leaf_link);
     113                for (i = 0; i < node->keys; i++) {
     114                        uintptr_t base = node->key[i];
     115                        size_t count = (size_t) node->value[i];
     116                        unsigned int j;
     117                       
     118                        for (j = 0; j < count; j++) {
     119                                pte_t *pte;
     120                       
     121                                page_table_lock(area->as, false);
     122                                pte = page_mapping_find(area->as,
     123                                    base + j * PAGE_SIZE);
     124                                ASSERT(pte && PTE_VALID(pte) &&
     125                                    PTE_PRESENT(pte));
     126                                btree_insert(&area->sh_info->pagemap,
     127                                    (base + j * PAGE_SIZE) - area->base,
     128                                    (void *) PTE_GET_FRAME(pte), NULL);
     129                                page_table_unlock(area->as, false);
     130
     131                                pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
     132                                frame_reference_add(pfn);
     133                        }
     134
     135                }
     136        }
     137        mutex_unlock(&area->sh_info->lock);
     138}
     139
     140void anon_destroy(as_area_t *area)
     141{
     142        reserve_free(area->pages);
     143}
     144
    66145
    67146/** Service a page fault in the anonymous memory address space area.
     
    115194                        }
    116195                        if (allocate) {
    117                                 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
     196                                frame = (uintptr_t) frame_alloc_noreserve(
     197                                    ONE_FRAME, 0);
    118198                                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    119199                               
     
    145225                 *   the different causes
    146226                 */
    147                 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
     227                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
    148228                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    149229        }
     
    174254        ASSERT(mutex_locked(&area->lock));
    175255
    176         frame_free(frame);
    177 }
    178 
    179 /** Share the anonymous address space area.
    180  *
    181  * Sharing of anonymous area is done by duplicating its entire mapping
    182  * to the pagemap. Page faults will primarily search for frames there.
    183  *
    184  * The address space and address space area must be already locked.
    185  *
    186  * @param area Address space area to be shared.
    187  */
    188 void anon_share(as_area_t *area)
    189 {
    190         link_t *cur;
    191 
    192         ASSERT(mutex_locked(&area->as->lock));
    193         ASSERT(mutex_locked(&area->lock));
    194 
    195         /*
    196          * Copy used portions of the area to sh_info's page map.
    197          */
    198         mutex_lock(&area->sh_info->lock);
    199         for (cur = area->used_space.leaf_head.next;
    200             cur != &area->used_space.leaf_head; cur = cur->next) {
    201                 btree_node_t *node;
    202                 unsigned int i;
    203                
    204                 node = list_get_instance(cur, btree_node_t, leaf_link);
    205                 for (i = 0; i < node->keys; i++) {
    206                         uintptr_t base = node->key[i];
    207                         size_t count = (size_t) node->value[i];
    208                         unsigned int j;
    209                        
    210                         for (j = 0; j < count; j++) {
    211                                 pte_t *pte;
    212                        
    213                                 page_table_lock(area->as, false);
    214                                 pte = page_mapping_find(area->as,
    215                                     base + j * PAGE_SIZE);
    216                                 ASSERT(pte && PTE_VALID(pte) &&
    217                                     PTE_PRESENT(pte));
    218                                 btree_insert(&area->sh_info->pagemap,
    219                                     (base + j * PAGE_SIZE) - area->base,
    220                                     (void *) PTE_GET_FRAME(pte), NULL);
    221                                 page_table_unlock(area->as, false);
    222 
    223                                 pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
    224                                 frame_reference_add(pfn);
    225                         }
    226 
    227                 }
    228         }
    229         mutex_unlock(&area->sh_info->lock);
     256        frame_free_noreserve(frame);
    230257}
    231258
  • kernel/generic/src/mm/backend_elf.c

    r72cd53d r3375bd4  
    4343#include <mm/slab.h>
    4444#include <mm/page.h>
     45#include <mm/reserve.h>
    4546#include <genarch/mm/page_pt.h>
    4647#include <genarch/mm/page_ht.h>
     
    5152#include <arch/barrier.h>
    5253
    53 #ifdef CONFIG_VIRT_IDX_DCACHE
    54 #include <arch/mm/cache.h>
    55 #endif
    56 
    57 static int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
    58 static void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
    59 static void elf_share(as_area_t *area);
     54static bool elf_create(as_area_t *);
     55static bool elf_resize(as_area_t *, size_t);
     56static void elf_share(as_area_t *);
     57static void elf_destroy(as_area_t *);
     58
     59static int elf_page_fault(as_area_t *, uintptr_t, pf_access_t);
     60static void elf_frame_free(as_area_t *, uintptr_t, uintptr_t);
    6061
    6162mem_backend_t elf_backend = {
     63        .create = elf_create,
     64        .resize = elf_resize,
     65        .share = elf_share,
     66        .destroy = elf_destroy,
     67
    6268        .page_fault = elf_page_fault,
    6369        .frame_free = elf_frame_free,
    64         .share = elf_share
    6570};
    6671
    67 /** Service a page fault in the ELF backend address space area.
    68  *
    69  * The address space area and page tables must be already locked.
    70  *
    71  * @param area          Pointer to the address space area.
    72  * @param addr          Faulting virtual address.
    73  * @param access        Access mode that caused the fault (i.e.
    74  *                      read/write/exec).
    75  *
    76  * @return              AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK
    77  *                      on success (i.e. serviced).
    78  */
    79 int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
    80 {
    81         elf_header_t *elf = area->backend_data.elf;
     72static size_t elf_nonanon_pages_get(as_area_t *area)
     73{
    8274        elf_segment_header_t *entry = area->backend_data.segment;
    83         btree_node_t *leaf;
    84         uintptr_t base, frame, page, start_anon;
    85         size_t i;
    86         bool dirty = false;
    87 
    88         ASSERT(page_table_locked(AS));
    89         ASSERT(mutex_locked(&area->lock));
    90 
    91         if (!as_area_check_access(area, access))
    92                 return AS_PF_FAULT;
     75        uintptr_t first = ALIGN_UP(entry->p_vaddr, PAGE_SIZE);
     76        uintptr_t last = ALIGN_DOWN(entry->p_vaddr + entry->p_filesz,
     77            PAGE_SIZE);
     78
     79        if (entry->p_flags & PF_W)
     80                return 0;
     81
     82        if (last < first)
     83                return 0;
     84
     85        return last - first;
     86}
     87
     88bool elf_create(as_area_t *area)
     89{
     90        size_t nonanon_pages = elf_nonanon_pages_get(area);
     91
     92        if (area->pages <= nonanon_pages)
     93                return true;
    9394       
    94         if (addr < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
    95                 return AS_PF_FAULT;
     95        return reserve_try_alloc(area->pages - nonanon_pages);
     96}
     97
     98bool elf_resize(as_area_t *area, size_t new_pages)
     99{
     100        size_t nonanon_pages = elf_nonanon_pages_get(area);
     101
     102        if (new_pages > area->pages) {
     103                /* The area is growing. */
     104                if (area->pages >= nonanon_pages)
     105                        return reserve_try_alloc(new_pages - area->pages);
     106                else if (new_pages > nonanon_pages)
     107                        return reserve_try_alloc(new_pages - nonanon_pages);
     108        } else if (new_pages < area->pages) {
     109                /* The area is shrinking. */
     110                if (new_pages >= nonanon_pages)
     111                        reserve_free(area->pages - new_pages);
     112                else if (area->pages > nonanon_pages)
     113                        reserve_free(nonanon_pages - new_pages);
     114        }
    96115       
    97         if (addr >= entry->p_vaddr + entry->p_memsz)
    98                 return AS_PF_FAULT;
    99        
    100         i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
    101         base = (uintptr_t)
    102             (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
    103 
    104         /* Virtual address of faulting page*/
    105         page = ALIGN_DOWN(addr, PAGE_SIZE);
    106 
    107         /* Virtual address of the end of initialized part of segment */
    108         start_anon = entry->p_vaddr + entry->p_filesz;
    109 
    110         if (area->sh_info) {
    111                 bool found = false;
    112 
    113                 /*
    114                  * The address space area is shared.
    115                  */
    116                
    117                 mutex_lock(&area->sh_info->lock);
    118                 frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
    119                     page - area->base, &leaf);
    120                 if (!frame) {
    121                         unsigned int i;
    122 
    123                         /*
    124                          * Workaround for valid NULL address.
    125                          */
    126 
    127                         for (i = 0; i < leaf->keys; i++) {
    128                                 if (leaf->key[i] == page - area->base) {
    129                                         found = true;
    130                                         break;
    131                                 }
    132                         }
    133                 }
    134                 if (frame || found) {
    135                         frame_reference_add(ADDR2PFN(frame));
    136                         page_mapping_insert(AS, addr, frame,
    137                             as_area_get_flags(area));
    138                         if (!used_space_insert(area, page, 1))
    139                                 panic("Cannot insert used space.");
    140                         mutex_unlock(&area->sh_info->lock);
    141                         return AS_PF_OK;
    142                 }
    143         }
    144 
    145         /*
    146          * The area is either not shared or the pagemap does not contain the
    147          * mapping.
    148          */
    149         if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
    150                 /*
    151                  * Initialized portion of the segment. The memory is backed
    152                  * directly by the content of the ELF image. Pages are
    153                  * only copied if the segment is writable so that there
    154                  * can be more instantions of the same memory ELF image
    155                  * used at a time. Note that this could be later done
    156                  * as COW.
    157                  */
    158                 if (entry->p_flags & PF_W) {
    159                         frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    160                         memcpy((void *) PA2KA(frame),
    161                             (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
    162                         if (entry->p_flags & PF_X) {
    163                                 smc_coherence_block((void *) PA2KA(frame),
    164                                     FRAME_SIZE);
    165                         }
    166                         dirty = true;
    167                 } else {
    168                         frame = KA2PA(base + i * FRAME_SIZE);
    169                 }       
    170         } else if (page >= start_anon) {
    171                 /*
    172                  * This is the uninitialized portion of the segment.
    173                  * It is not physically present in the ELF image.
    174                  * To resolve the situation, a frame must be allocated
    175                  * and cleared.
    176                  */
    177                 frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    178                 memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    179                 dirty = true;
    180         } else {
    181                 size_t pad_lo, pad_hi;
    182                 /*
    183                  * The mixed case.
    184                  *
    185                  * The middle part is backed by the ELF image and
    186                  * the lower and upper parts are anonymous memory.
    187                  * (The segment can be and often is shorter than 1 page).
    188                  */
    189                 if (page < entry->p_vaddr)
    190                         pad_lo = entry->p_vaddr - page;
    191                 else
    192                         pad_lo = 0;
    193 
    194                 if (start_anon < page + PAGE_SIZE)
    195                         pad_hi = page + PAGE_SIZE - start_anon;
    196                 else
    197                         pad_hi = 0;
    198 
    199                 frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    200                 memcpy((void *) (PA2KA(frame) + pad_lo),
    201                     (void *) (base + i * FRAME_SIZE + pad_lo),
    202                     FRAME_SIZE - pad_lo - pad_hi);
    203                 if (entry->p_flags & PF_X) {
    204                         smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
    205                             FRAME_SIZE - pad_lo - pad_hi);
    206                 }
    207                 memsetb((void *) PA2KA(frame), pad_lo, 0);
    208                 memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
    209                     0);
    210                 dirty = true;
    211         }
    212 
    213         if (dirty && area->sh_info) {
    214                 frame_reference_add(ADDR2PFN(frame));
    215                 btree_insert(&area->sh_info->pagemap, page - area->base,
    216                     (void *) frame, leaf);
    217         }
    218 
    219         if (area->sh_info)
    220                 mutex_unlock(&area->sh_info->lock);
    221 
    222         page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
    223         if (!used_space_insert(area, page, 1))
    224                 panic("Cannot insert used space.");
    225 
    226         return AS_PF_OK;
    227 }
    228 
    229 /** Free a frame that is backed by the ELF backend.
    230  *
    231  * The address space area and page tables must be already locked.
    232  *
    233  * @param area          Pointer to the address space area.
    234  * @param page          Page that is mapped to frame. Must be aligned to
    235  *                      PAGE_SIZE.
    236  * @param frame         Frame to be released.
    237  *
    238  */
    239 void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
    240 {
    241         elf_segment_header_t *entry = area->backend_data.segment;
    242         uintptr_t start_anon;
    243 
    244         ASSERT(page_table_locked(area->as));
    245         ASSERT(mutex_locked(&area->lock));
    246 
    247         ASSERT(page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
    248         ASSERT(page < entry->p_vaddr + entry->p_memsz);
    249 
    250         start_anon = entry->p_vaddr + entry->p_filesz;
    251 
    252         if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
    253                 if (entry->p_flags & PF_W) {
    254                         /*
    255                          * Free the frame with the copy of writable segment
    256                          * data.
    257                          */
    258                         frame_free(frame);
    259                 }
    260         } else {
    261                 /*
    262                  * The frame is either anonymous memory or the mixed case (i.e.
    263                  * lower part is backed by the ELF image and the upper is
    264                  * anonymous). In any case, a frame needs to be freed.
    265                  */
    266                 frame_free(frame);
    267         }
     116        return true;
    268117}
    269118
     
    356205}
    357206
     207void elf_destroy(as_area_t *area)
     208{
     209        size_t nonanon_pages = elf_nonanon_pages_get(area);
     210
     211        if (area->pages > nonanon_pages)
     212                reserve_free(area->pages - nonanon_pages);
     213}
     214
     215/** Service a page fault in the ELF backend address space area.
     216 *
     217 * The address space area and page tables must be already locked.
     218 *
     219 * @param area          Pointer to the address space area.
     220 * @param addr          Faulting virtual address.
     221 * @param access        Access mode that caused the fault (i.e.
     222 *                      read/write/exec).
     223 *
     224 * @return              AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK
     225 *                      on success (i.e. serviced).
     226 */
     227int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
     228{
     229        elf_header_t *elf = area->backend_data.elf;
     230        elf_segment_header_t *entry = area->backend_data.segment;
     231        btree_node_t *leaf;
     232        uintptr_t base, frame, page, start_anon;
     233        size_t i;
     234        bool dirty = false;
     235
     236        ASSERT(page_table_locked(AS));
     237        ASSERT(mutex_locked(&area->lock));
     238
     239        if (!as_area_check_access(area, access))
     240                return AS_PF_FAULT;
     241       
     242        if (addr < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
     243                return AS_PF_FAULT;
     244       
     245        if (addr >= entry->p_vaddr + entry->p_memsz)
     246                return AS_PF_FAULT;
     247       
     248        i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
     249        base = (uintptr_t)
     250            (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
     251
     252        /* Virtual address of faulting page*/
     253        page = ALIGN_DOWN(addr, PAGE_SIZE);
     254
     255        /* Virtual address of the end of initialized part of segment */
     256        start_anon = entry->p_vaddr + entry->p_filesz;
     257
     258        if (area->sh_info) {
     259                bool found = false;
     260
     261                /*
     262                 * The address space area is shared.
     263                 */
     264               
     265                mutex_lock(&area->sh_info->lock);
     266                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
     267                    page - area->base, &leaf);
     268                if (!frame) {
     269                        unsigned int i;
     270
     271                        /*
     272                         * Workaround for valid NULL address.
     273                         */
     274
     275                        for (i = 0; i < leaf->keys; i++) {
     276                                if (leaf->key[i] == page - area->base) {
     277                                        found = true;
     278                                        break;
     279                                }
     280                        }
     281                }
     282                if (frame || found) {
     283                        frame_reference_add(ADDR2PFN(frame));
     284                        page_mapping_insert(AS, addr, frame,
     285                            as_area_get_flags(area));
     286                        if (!used_space_insert(area, page, 1))
     287                                panic("Cannot insert used space.");
     288                        mutex_unlock(&area->sh_info->lock);
     289                        return AS_PF_OK;
     290                }
     291        }
     292
     293        /*
     294         * The area is either not shared or the pagemap does not contain the
     295         * mapping.
     296         */
     297        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     298                /*
     299                 * Initialized portion of the segment. The memory is backed
     300                 * directly by the content of the ELF image. Pages are
     301                 * only copied if the segment is writable so that there
     302                 * can be more instantions of the same memory ELF image
     303                 * used at a time. Note that this could be later done
     304                 * as COW.
     305                 */
     306                if (entry->p_flags & PF_W) {
     307                        frame = (uintptr_t)frame_alloc_noreserve(ONE_FRAME, 0);
     308                        memcpy((void *) PA2KA(frame),
     309                            (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
     310                        if (entry->p_flags & PF_X) {
     311                                smc_coherence_block((void *) PA2KA(frame),
     312                                    FRAME_SIZE);
     313                        }
     314                        dirty = true;
     315                } else {
     316                        frame = KA2PA(base + i * FRAME_SIZE);
     317                }       
     318        } else if (page >= start_anon) {
     319                /*
     320                 * This is the uninitialized portion of the segment.
     321                 * It is not physically present in the ELF image.
     322                 * To resolve the situation, a frame must be allocated
     323                 * and cleared.
     324                 */
     325                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
     326                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
     327                dirty = true;
     328        } else {
     329                size_t pad_lo, pad_hi;
     330                /*
     331                 * The mixed case.
     332                 *
     333                 * The middle part is backed by the ELF image and
     334                 * the lower and upper parts are anonymous memory.
     335                 * (The segment can be and often is shorter than 1 page).
     336                 */
     337                if (page < entry->p_vaddr)
     338                        pad_lo = entry->p_vaddr - page;
     339                else
     340                        pad_lo = 0;
     341
     342                if (start_anon < page + PAGE_SIZE)
     343                        pad_hi = page + PAGE_SIZE - start_anon;
     344                else
     345                        pad_hi = 0;
     346
     347                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
     348                memcpy((void *) (PA2KA(frame) + pad_lo),
     349                    (void *) (base + i * FRAME_SIZE + pad_lo),
     350                    FRAME_SIZE - pad_lo - pad_hi);
     351                if (entry->p_flags & PF_X) {
     352                        smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
     353                            FRAME_SIZE - pad_lo - pad_hi);
     354                }
     355                memsetb((void *) PA2KA(frame), pad_lo, 0);
     356                memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
     357                    0);
     358                dirty = true;
     359        }
     360
     361        if (dirty && area->sh_info) {
     362                frame_reference_add(ADDR2PFN(frame));
     363                btree_insert(&area->sh_info->pagemap, page - area->base,
     364                    (void *) frame, leaf);
     365        }
     366
     367        if (area->sh_info)
     368                mutex_unlock(&area->sh_info->lock);
     369
     370        page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
     371        if (!used_space_insert(area, page, 1))
     372                panic("Cannot insert used space.");
     373
     374        return AS_PF_OK;
     375}
     376
     377/** Free a frame that is backed by the ELF backend.
     378 *
     379 * The address space area and page tables must be already locked.
     380 *
     381 * @param area          Pointer to the address space area.
     382 * @param page          Page that is mapped to frame. Must be aligned to
     383 *                      PAGE_SIZE.
     384 * @param frame         Frame to be released.
     385 *
     386 */
     387void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
     388{
     389        elf_segment_header_t *entry = area->backend_data.segment;
     390        uintptr_t start_anon;
     391
     392        ASSERT(page_table_locked(area->as));
     393        ASSERT(mutex_locked(&area->lock));
     394
     395        ASSERT(page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
     396        ASSERT(page < entry->p_vaddr + entry->p_memsz);
     397
     398        start_anon = entry->p_vaddr + entry->p_filesz;
     399
     400        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     401                if (entry->p_flags & PF_W) {
     402                        /*
     403                         * Free the frame with the copy of writable segment
     404                         * data.
     405                         */
     406                        frame_free_noreserve(frame);
     407                }
     408        } else {
     409                /*
     410                 * The frame is either anonymous memory or the mixed case (i.e.
     411                 * lower part is backed by the ELF image and the upper is
     412                 * anonymous). In any case, a frame needs to be freed.
     413                 */
     414                frame_free_noreserve(frame);
     415        }
     416}
     417
    358418/** @}
    359419 */
  • kernel/generic/src/mm/backend_phys.c

    r72cd53d r3375bd4  
    4848#include <align.h>
    4949
    50 static int phys_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
    51 static void phys_share(as_area_t *area);
     50static bool phys_create(as_area_t *);
     51static void phys_share(as_area_t *);
     52static void phys_destroy(as_area_t *);
     53
     54static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t);
    5255
    5356mem_backend_t phys_backend = {
     57        .create = phys_create,
     58        .resize = NULL,
     59        .share = phys_share,
     60        .destroy = phys_destroy,
     61
    5462        .page_fault = phys_page_fault,
    5563        .frame_free = NULL,
    56         .share = phys_share
    5764};
     65
     66bool phys_create(as_area_t *area)
     67{
     68        return true;
     69}
     70
     71/** Share address space area backed by physical memory.
     72 *
     73 * Do actually nothing as sharing of address space areas
     74 * that are backed up by physical memory is very easy.
     75 * Note that the function must be defined so that
     76 * as_area_share() will succeed.
     77 */
     78void phys_share(as_area_t *area)
     79{
     80        ASSERT(mutex_locked(&area->as->lock));
     81        ASSERT(mutex_locked(&area->lock));
     82}
     83
     84
     85void phys_destroy(as_area_t *area)
     86{
     87        /* Nothing to do. */
     88}
    5889
    5990/** Service a page fault in the address space area backed by physical memory.
     
    88119}
    89120
    90 /** Share address space area backed by physical memory.
    91  *
    92  * Do actually nothing as sharing of address space areas
    93  * that are backed up by physical memory is very easy.
    94  * Note that the function must be defined so that
    95  * as_area_share() will succeed.
    96  */
    97 void phys_share(as_area_t *area)
    98 {
    99         ASSERT(mutex_locked(&area->as->lock));
    100         ASSERT(mutex_locked(&area->lock));
    101 }
    102 
    103121/** @}
    104122 */
  • kernel/generic/src/mm/frame.c

    r72cd53d r3375bd4  
    4545#include <typedefs.h>
    4646#include <mm/frame.h>
     47#include <mm/reserve.h>
    4748#include <mm/as.h>
    4849#include <panic.h>
     
    5960#include <macros.h>
    6061#include <config.h>
     62#include <str.h>
    6163
    6264zones_t zones;
     
    180182 *
    181183 */
    182 #ifdef CONFIG_DEBUG
    183 NO_TRACE static size_t total_frames_free(void)
     184NO_TRACE static size_t frame_total_free_get_internal(void)
    184185{
    185186        size_t total = 0;
    186187        size_t i;
     188
    187189        for (i = 0; i < zones.count; i++)
    188190                total += zones.info[i].free_count;
     
    190192        return total;
    191193}
    192 #endif /* CONFIG_DEBUG */
     194
     195NO_TRACE size_t frame_total_free_get(void)
     196{
     197        size_t total;
     198
     199        irq_spinlock_lock(&zones.lock, true);
     200        total = frame_total_free_get_internal();
     201        irq_spinlock_unlock(&zones.lock, true);
     202
     203        return total;
     204}
     205
    193206
    194207/** Find a zone with a given frames.
     
    472485 * @param frame_idx Frame index relative to zone.
    473486 *
    474  */
    475 NO_TRACE static void zone_frame_free(zone_t *zone, size_t frame_idx)
     487 * @return          Number of freed frames.
     488 *
     489 */
     490NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
    476491{
    477492        ASSERT(zone_flags_available(zone->flags));
    478493       
    479494        frame_t *frame = &zone->frames[frame_idx];
    480        
    481         /* Remember frame order */
    482         uint8_t order = frame->buddy_order;
     495        size_t size = 0;
    483496       
    484497        ASSERT(frame->refcount);
    485498       
    486499        if (!--frame->refcount) {
    487                 buddy_system_free(zone->buddy_system, &frame->buddy_link);
    488                
     500                size = 1 << frame->buddy_order;
     501                buddy_system_free(zone->buddy_system, &frame->buddy_link);             
    489502                /* Update zone information. */
    490                 zone->free_count += (1 << order);
    491                 zone->busy_count -= (1 << order);
    492         }
     503                zone->free_count += size;
     504                zone->busy_count -= size;
     505        }
     506       
     507        return size;
    493508}
    494509
     
    516531        ASSERT(link);
    517532        zone->free_count--;
     533        reserve_force_alloc(1);
    518534}
    519535
     
    645661        for (i = 0; i < cframes; i++) {
    646662                zones.info[znum].busy_count++;
    647                 zone_frame_free(&zones.info[znum],
     663                (void) zone_frame_free(&zones.info[znum],
    648664                    pfn - zones.info[znum].base + i);
    649665        }
     
    683699        /* Free unneeded frames */
    684700        for (i = count; i < (size_t) (1 << order); i++)
    685                 zone_frame_free(&zones.info[znum], i + frame_idx);
     701                (void) zone_frame_free(&zones.info[znum], i + frame_idx);
    686702}
    687703
     
    695711 * not to be 2^order size. Once the allocator is running it is no longer
    696712 * possible, merged configuration data occupies more space :-/
    697  *
    698  * The function uses
    699713 *
    700714 */
     
    9991013        size_t hint = pzone ? (*pzone) : 0;
    10001014       
     1015        /*
     1016         * If not told otherwise, we must first reserve the memory.
     1017         */
     1018        if (!(flags & FRAME_NO_RESERVE))
     1019                reserve_force_alloc(size);
     1020
    10011021loop:
    10021022        irq_spinlock_lock(&zones.lock, true);
     
    10331053                if (flags & FRAME_ATOMIC) {
    10341054                        irq_spinlock_unlock(&zones.lock, true);
     1055                        if (!(flags & FRAME_NO_RESERVE))
     1056                                reserve_free(size);
    10351057                        return NULL;
    10361058                }
    10371059               
    10381060#ifdef CONFIG_DEBUG
    1039                 size_t avail = total_frames_free();
     1061                size_t avail = frame_total_free_get_internal();
    10401062#endif
    10411063               
     
    10881110}
    10891111
     1112void *frame_alloc(uint8_t order, frame_flags_t flags)
     1113{
     1114        return frame_alloc_generic(order, flags, NULL);
     1115}
     1116
     1117void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
     1118{
     1119        return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
     1120}
     1121
    10901122/** Free a frame.
    10911123 *
     
    10951127 *
    10961128 * @param frame Physical Address of of the frame to be freed.
    1097  *
    1098  */
    1099 void frame_free(uintptr_t frame)
    1100 {
     1129 * @param flags Flags to control memory reservation.
     1130 *
     1131 */
     1132void frame_free_generic(uintptr_t frame, frame_flags_t flags)
     1133{
     1134        size_t size;
     1135       
    11011136        irq_spinlock_lock(&zones.lock, true);
    11021137       
     
    11061141        pfn_t pfn = ADDR2PFN(frame);
    11071142        size_t znum = find_zone(pfn, 1, 0);
     1143
    11081144       
    11091145        ASSERT(znum != (size_t) -1);
    11101146       
    1111         zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
     1147        size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
    11121148       
    11131149        irq_spinlock_unlock(&zones.lock, true);
     
    11181154        mutex_lock(&mem_avail_mtx);
    11191155        if (mem_avail_req > 0)
    1120                 mem_avail_req--;
     1156                mem_avail_req -= min(mem_avail_req, size);
    11211157       
    11221158        if (mem_avail_req == 0) {
     
    11251161        }
    11261162        mutex_unlock(&mem_avail_mtx);
     1163       
     1164        if (!(flags & FRAME_NO_RESERVE))
     1165                reserve_free(size);
     1166}
     1167
     1168void frame_free(uintptr_t frame)
     1169{
     1170        frame_free_generic(frame, 0);
     1171}
     1172
     1173void frame_free_noreserve(uintptr_t frame)
     1174{
     1175        frame_free_generic(frame, FRAME_NO_RESERVE);
    11271176}
    11281177
     
    13551404        bool available = zone_flags_available(flags);
    13561405       
     1406        uint64_t size;
     1407        const char *size_suffix;
     1408        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
     1409       
    13571410        printf("Zone number:       %zu\n", znum);
    13581411        printf("Zone base address: %p\n", (void *) base);
    1359         printf("Zone size:         %zu frames (%zu KiB)\n", count,
    1360             SIZE2KB(FRAMES2SIZE(count)));
     1412        printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
     1413            size, size_suffix);
    13611414        printf("Zone flags:        %c%c%c\n",
    13621415            available ? 'A' : ' ',
     
    13651418       
    13661419        if (available) {
    1367                 printf("Allocated space:   %zu frames (%zu KiB)\n",
    1368                     busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
    1369                 printf("Available space:   %zu frames (%zu KiB)\n",
    1370                     free_count, SIZE2KB(FRAMES2SIZE(free_count)));
     1420                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
     1421                    false);
     1422                printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
     1423                    busy_count, size, size_suffix);
     1424                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
     1425                    false);
     1426                printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
     1427                    free_count, size, size_suffix);
    13711428        }
    13721429}
  • kernel/generic/src/proc/scheduler.c

    r72cd53d r3375bd4  
    354354       
    355355        /*
    356          * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, VM
     356         * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, AS
    357357         * and preemption counter. At this point THE could be coming either
    358358         * from THREAD's or CPU's stack.
  • kernel/generic/src/proc/task.c

    r72cd53d r3375bd4  
    534534        */
    535535        if (notify) {
    536                 if (event_is_subscribed(EVENT_FAULT)) {
    537                         /* Notify the subscriber that a fault occurred. */
    538                         event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
    539                             UPPER32(TASK->taskid), (sysarg_t) THREAD);
    540                
     536                /* Notify the subscriber that a fault occurred. */
     537                if (event_notify_3(EVENT_FAULT, false, LOWER32(TASK->taskid),
     538                    UPPER32(TASK->taskid), (sysarg_t) THREAD) == EOK) {
    541539#ifdef CONFIG_UDEBUG
    542540                        /* Wait for a debugging session. */
  • kernel/generic/src/syscall/syscall.c

    r72cd53d r3375bd4  
    166166        /* Event notification syscalls. */
    167167        (syshandler_t) sys_event_subscribe,
     168        (syshandler_t) sys_event_unmask,
    168169       
    169170        /* Capabilities related syscalls. */
Note: See TracChangeset for help on using the changeset viewer.