Changeset 544a2e4 in mainline for kernel/generic/src


Ignore:
Timestamp:
2011-05-30T21:37:43Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7b712b60
Parents:
18ba2e4f (diff), 0743493a (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.

Location:
kernel/generic/src
Files:
1 added
28 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/adt/list.c

    r18ba2e4f r544a2e4  
    5252 *
    5353 */
    54 bool list_member(const link_t *link, const link_t *head)
     54int list_member(const link_t *link, const link_t *head)
    5555{
    5656        bool found = false;
  • kernel/generic/src/console/cmd.c

    r18ba2e4f r544a2e4  
    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

    r18ba2e4f r544a2e4  
    5353#include <str.h>
    5454
    55 #define KLOG_PAGES    4
     55#define KLOG_PAGES    8
    5656#define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
    57 #define KLOG_LATENCY  8
    5857
    5958/** Kernel log cyclic buffer */
     
    6160
    6261/** Kernel log initialized */
    63 static bool klog_inited = false;
     62static atomic_t klog_inited = {false};
    6463
    6564/** First kernel log characters */
     
    7675
    7776/** Kernel log spinlock */
    78 SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "*klog_lock");
     77SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "klog_lock");
    7978
    8079/** Physical memory area used for klog buffer */
     
    166165        sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES);
    167166       
    168         spinlock_lock(&klog_lock);
    169         klog_inited = true;
    170         spinlock_unlock(&klog_lock);
     167        event_set_unmask_callback(EVENT_KLOG, klog_update);
     168        atomic_set(&klog_inited, true);
    171169}
    172170
     
    263261void klog_update(void)
    264262{
     263        if (!atomic_get(&klog_inited))
     264                return;
     265       
    265266        spinlock_lock(&klog_lock);
    266267       
    267         if ((klog_inited) && (event_is_subscribed(EVENT_KLOG)) && (klog_uspace > 0)) {
    268                 event_notify_3(EVENT_KLOG, klog_start, klog_len, klog_uspace);
    269                 klog_uspace = 0;
     268        if (klog_uspace > 0) {
     269                if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
     270                    klog_uspace) == EOK)
     271                        klog_uspace = 0;
    270272        }
    271273       
     
    275277void putchar(const wchar_t ch)
    276278{
     279        bool ordy = ((stdout) && (stdout->op->write));
     280       
    277281        spinlock_lock(&klog_lock);
    278282       
    279         if ((klog_stored > 0) && (stdout) && (stdout->op->write)) {
    280                 /* Print charaters stored in kernel log */
    281                 size_t i;
    282                 for (i = klog_len - klog_stored; i < klog_len; i++)
    283                         stdout->op->write(stdout, klog[(klog_start + i) % KLOG_LENGTH], silent);
    284                 klog_stored = 0;
     283        /* Print charaters stored in kernel log */
     284        if (ordy) {
     285                while (klog_stored > 0) {
     286                        wchar_t tmp = klog[(klog_start + klog_len - klog_stored) % KLOG_LENGTH];
     287                        klog_stored--;
     288                       
     289                        /*
     290                         * We need to give up the spinlock for
     291                         * the physical operation of writting out
     292                         * the character.
     293                         */
     294                        spinlock_unlock(&klog_lock);
     295                        stdout->op->write(stdout, tmp, silent);
     296                        spinlock_lock(&klog_lock);
     297                }
    285298        }
    286299       
     
    292305                klog_start = (klog_start + 1) % KLOG_LENGTH;
    293306       
    294         if ((stdout) && (stdout->op->write))
     307        if (!ordy) {
     308                if (klog_stored < klog_len)
     309                        klog_stored++;
     310        }
     311       
     312        /* The character is stored for uspace */
     313        if (klog_uspace < klog_len)
     314                klog_uspace++;
     315       
     316        spinlock_unlock(&klog_lock);
     317       
     318        if (ordy) {
     319                /*
     320                 * Output the character. In this case
     321                 * it should be no longer buffered.
     322                 */
    295323                stdout->op->write(stdout, ch, silent);
    296         else {
     324        } else {
    297325                /*
    298326                 * No standard output routine defined yet.
     
    304332                 * Note that the early_putc() function might be
    305333                 * a no-op on certain hardware configurations.
    306                  *
    307334                 */
    308335                early_putchar(ch);
    309                
    310                 if (klog_stored < klog_len)
    311                         klog_stored++;
    312         }
    313        
    314         /* The character is stored for uspace */
    315         if (klog_uspace < klog_len)
    316                 klog_uspace++;
    317        
    318         /* Check notify uspace to update */
    319         bool update;
    320         if ((klog_uspace > KLOG_LATENCY) || (ch == '\n'))
    321                 update = true;
    322         else
    323                 update = false;
    324        
    325         spinlock_unlock(&klog_lock);
    326        
    327         if (update)
     336        }
     337       
     338        /* Force notification on newline */
     339        if (ch == '\n')
    328340                klog_update();
    329341}
  • kernel/generic/src/ddi/ddi.c

    r18ba2e4f r544a2e4  
    224224        task_t *task = task_find_by_id(id);
    225225       
    226         if ((!task) || (!context_check(CONTEXT, task->context))) {
     226        if ((!task) || (!container_check(CONTAINER, task->container))) {
    227227                /*
    228228                 * There is no task with the specified ID
  • kernel/generic/src/debug/panic.c

    r18ba2e4f r544a2e4  
    9595        printf("\n");
    9696       
     97        printf("THE=%p: ", THE);
     98        if (THE != NULL) {
     99                printf("pe=%" PRIun " thr=%p task=%p cpu=%p as=%p"
     100                    " magic=%#" PRIx32 "\n", THE->preemption_disabled,
     101                    THE->thread, THE->task, THE->cpu, THE->as, THE->magic);
     102        } else
     103                printf("invalid\n");
     104       
    97105        if (istate) {
    98106                istate_decode(istate);
  • kernel/generic/src/interrupt/interrupt.c

    r18ba2e4f r544a2e4  
    205205         * stack.
    206206         */
    207         return (istate_t *) ((uint8_t *) thread->kstack + THREAD_STACK_SIZE -
    208             sizeof(istate_t));
     207        return (istate_t *) ((uint8_t *)
     208            thread->kstack + STACK_SIZE - sizeof(istate_t));
    209209}
    210210
  • kernel/generic/src/ipc/event.c

    r18ba2e4f r544a2e4  
    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_callback = 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 callback Callback function to be called when
     90 *                 the event is unmasked.
     91 *
     92 */
     93void event_set_unmask_callback(event_type_t evno, event_callback_t callback)
     94{
     95        ASSERT(evno < EVENT_END);
     96       
     97        spinlock_lock(&events[evno].lock);
     98        events[evno].unmask_callback = callback;
     99        spinlock_unlock(&events[evno].lock);
     100}
     101
     102/** Send kernel notification event
     103 *
     104 * @param evno Event type.
     105 * @param mask Mask further notifications after a successful
     106 *             sending.
     107 * @param a1   First argument.
     108 * @param a2   Second argument.
     109 * @param a3   Third argument.
     110 * @param a4   Fourth argument.
     111 * @param a5   Fifth argument.
     112 *
     113 * @return EOK if notification was successfully sent.
     114 * @return ENOMEM if the notification IPC message failed to allocate.
     115 * @return EBUSY if the notifications of the given type are
     116 *         currently masked.
     117 * @return ENOENT if the notifications of the given type are
     118 *         currently not subscribed.
     119 *
     120 */
     121int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2,
     122    sysarg_t a3, sysarg_t a4, sysarg_t a5)
     123{
     124        ASSERT(evno < EVENT_END);
     125       
     126        spinlock_lock(&events[evno].lock);
     127       
     128        int ret;
     129       
     130        if (events[evno].answerbox != NULL) {
     131                if (!events[evno].masked) {
     132                        call_t *call = ipc_call_alloc(FRAME_ATOMIC);
     133                       
     134                        if (call) {
     135                                call->flags |= IPC_CALL_NOTIF;
     136                                call->priv = ++events[evno].counter;
     137                               
     138                                IPC_SET_IMETHOD(call->data, events[evno].imethod);
     139                                IPC_SET_ARG1(call->data, a1);
     140                                IPC_SET_ARG2(call->data, a2);
     141                                IPC_SET_ARG3(call->data, a3);
     142                                IPC_SET_ARG4(call->data, a4);
     143                                IPC_SET_ARG5(call->data, a5);
     144                               
     145                                irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
     146                                list_append(&call->link, &events[evno].answerbox->irq_notifs);
     147                                irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
     148                               
     149                                waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
     150                               
     151                                if (mask)
     152                                        events[evno].masked = true;
     153                               
     154                                ret = EOK;
     155                        } else
     156                                ret = ENOMEM;
     157                } else
     158                        ret = EBUSY;
     159        } else
     160                ret = ENOENT;
     161       
     162        spinlock_unlock(&events[evno].lock);
     163       
     164        return ret;
     165}
     166
     167/** Subscribe event notifications
     168 *
     169 * @param evno      Event type.
     170 * @param imethod   IPC interface and method to be used for
     171 *                  the notifications.
     172 * @param answerbox Answerbox to send the notifications to.
     173 *
     174 * @return EOK if the subscription was successful.
     175 * @return EEXISTS if the notifications of the given type are
     176 *         already subscribed.
     177 *
     178 */
    63179static int event_subscribe(event_type_t evno, sysarg_t imethod,
    64180    answerbox_t *answerbox)
    65181{
    66         if (evno >= EVENT_END)
    67                 return ELIMIT;
     182        ASSERT(evno < EVENT_END);
    68183       
    69184        spinlock_lock(&events[evno].lock);
     
    75190                events[evno].imethod = imethod;
    76191                events[evno].counter = 0;
     192                events[evno].masked = false;
    77193                res = EOK;
    78194        } else
     
    84200}
    85201
     202/** Unmask event notifications
     203 *
     204 * @param evno Event type to unmask.
     205 *
     206 */
     207static void event_unmask(event_type_t evno)
     208{
     209        ASSERT(evno < EVENT_END);
     210       
     211        spinlock_lock(&events[evno].lock);
     212        events[evno].masked = false;
     213        event_callback_t callback = events[evno].unmask_callback;
     214        spinlock_unlock(&events[evno].lock);
     215       
     216        /*
     217         * Check if there is an unmask callback
     218         * function defined for this event.
     219         */
     220        if (callback != NULL)
     221                callback();
     222}
     223
     224/** Event notification syscall wrapper
     225 *
     226 * @param evno    Event type to subscribe.
     227 * @param imethod IPC interface and method to be used for
     228 *                the notifications.
     229 *
     230 * @return EOK on success.
     231 * @return ELIMIT on unknown event type.
     232 * @return EEXISTS if the notifications of the given type are
     233 *         already subscribed.
     234 *
     235 */
    86236sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
    87237{
     238        if (evno >= EVENT_END)
     239                return ELIMIT;
     240       
    88241        return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
    89242            imethod, &TASK->answerbox);
    90243}
    91244
    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);
     245/** Event notification unmask syscall wrapper
     246 *
     247 * Note that currently no tests are performed whether the calling
     248 * task is entitled to unmask the notifications. However, thanks
     249 * to the fact that notification masking is only a performance
     250 * optimization, this has probably no security implications.
     251 *
     252 * @param evno Event type to unmask.
     253 *
     254 * @return EOK on success.
     255 * @return ELIMIT on unknown event type.
     256 *
     257 */
     258sysarg_t sys_event_unmask(sysarg_t evno)
     259{
     260        if (evno >= EVENT_END)
     261                return ELIMIT;
     262       
     263        event_unmask((event_type_t) evno);
     264        return EOK;
    147265}
    148266
  • kernel/generic/src/lib/elf.c

    r18ba2e4f r544a2e4  
    114114        }
    115115       
    116         /* Inspect all section headers and proccess them. */
     116        /* Inspect all section headers and process them. */
    117117        for (i = 0; i < header->e_shnum; i++) {
    118118                elf_section_header_t *sechdr =
  • kernel/generic/src/lib/memfnc.c

    r18ba2e4f r544a2e4  
    5656void *memset(void *dst, int val, size_t cnt)
    5757{
    58         size_t i;
    59         uint8_t *ptr = (uint8_t *) dst;
     58        uint8_t *dp = (uint8_t *) dst;
    6059       
    61         for (i = 0; i < cnt; i++)
    62                 ptr[i] = val;
     60        while (cnt-- != 0)
     61                *dp++ = val;
    6362       
    6463        return dst;
     
    8382       
    8483        while (cnt-- != 0)
    85                         *dp++ = *sp++;
     84                *dp++ = *sp++;
    8685       
    8786        return dst;
  • kernel/generic/src/lib/str.c

    r18ba2e4f r544a2e4  
    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

    r18ba2e4f r544a2e4  
    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>
     
    117118#endif
    118119
    119 #define CONFIG_STACK_SIZE  ((1 << STACK_FRAMES) * STACK_SIZE)
    120 
    121120/** Main kernel routine for bootstrap CPU.
    122121 *
     
    138137        config.kernel_size = ALIGN_UP(hardcoded_ktext_size +
    139138            hardcoded_kdata_size, PAGE_SIZE);
    140         config.stack_size = CONFIG_STACK_SIZE;
     139        config.stack_size = STACK_SIZE;
    141140       
    142141        /* Initialy the stack is placed just after the kernel */
     
    164163       
    165164        context_save(&ctx);
    166         context_set(&ctx, FADDR(main_bsp_separated_stack), config.stack_base,
    167             THREAD_STACK_SIZE);
     165        context_set(&ctx, FADDR(main_bsp_separated_stack),
     166            config.stack_base, STACK_SIZE);
    168167        context_restore(&ctx);
    169168        /* not reached */
     
    217216        ddi_init();
    218217        arch_post_mm_init();
     218        reserve_init();
    219219        arch_pre_smp_init();
    220220        smp_init();
     
    223223        slab_enable_cpucache();
    224224       
    225         printf("Detected %u CPU(s), %" PRIu64 " MiB free memory\n",
    226             config.cpu_count, SIZE2MB(zones_total_size()));
     225        uint64_t size;
     226        const char *size_suffix;
     227        bin_order_suffix(zones_total_size(), &size, &size_suffix, false);
     228        printf("Detected %u CPU(s), %" PRIu64 " %s free memory\n",
     229            config.cpu_count, size, size_suffix);
    227230       
    228231        cpu_init();
     
    318321        context_save(&CPU->saved_context);
    319322        context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
    320             (uintptr_t) CPU->stack, CPU_STACK_SIZE);
     323            (uintptr_t) CPU->stack, STACK_SIZE);
    321324        context_restore(&CPU->saved_context);
    322325        /* not reached */
  • kernel/generic/src/main/uinit.c

    r18ba2e4f r544a2e4  
    3333/**
    3434 * @file
    35  * @brief       Userspace bootstrap thread.
     35 * @brief Userspace bootstrap thread.
    3636 *
    3737 * This file contains uinit kernel thread wich is used to start every
     
    4040 * @see SYS_THREAD_CREATE
    4141 */
    42  
     42
    4343#include <main/uinit.h>
    4444#include <typedefs.h>
     
    4848#include <arch.h>
    4949#include <udebug/udebug.h>
    50 
    5150
    5251/** Thread used to bring up userspace thread.
     
    5857{
    5958        uspace_arg_t uarg;
    60 
     59       
    6160        /*
    6261         * So far, we don't have a use for joining userspace threads so we
     
    6867         */
    6968        thread_detach(THREAD);
    70 
     69       
    7170#ifdef CONFIG_UDEBUG
    7271        udebug_stoppable_end();
     
    7877        uarg.uspace_thread_function = NULL;
    7978        uarg.uspace_thread_arg = NULL;
    80 
     79       
    8180        free((uspace_arg_t *) arg);
    8281       
  • kernel/generic/src/mm/as.c

    r18ba2e4f r544a2e4  
    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
     
    306302         * We don't want any area to have conflicts with NULL page.
    307303         */
    308         if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
     304        if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
    309305                return false;
    310306       
     
    333329                        mutex_lock(&area->lock);
    334330                       
    335                         if (overlaps(addr, count << PAGE_WIDTH,
    336                             area->base, area->pages << PAGE_WIDTH)) {
     331                        if (overlaps(addr, P2SZ(count), area->base,
     332                            P2SZ(area->pages))) {
    337333                                mutex_unlock(&area->lock);
    338334                                return false;
     
    350346                        mutex_lock(&area->lock);
    351347                       
    352                         if (overlaps(addr, count << PAGE_WIDTH,
    353                             area->base, area->pages << PAGE_WIDTH)) {
     348                        if (overlaps(addr, P2SZ(count), area->base,
     349                            P2SZ(area->pages))) {
    354350                                mutex_unlock(&area->lock);
    355351                                return false;
     
    370366                mutex_lock(&area->lock);
    371367               
    372                 if (overlaps(addr, count << PAGE_WIDTH,
    373                     area->base, area->pages << PAGE_WIDTH)) {
     368                if (overlaps(addr, P2SZ(count), area->base,
     369                    P2SZ(area->pages))) {
    374370                        mutex_unlock(&area->lock);
    375371                        return false;
     
    384380         */
    385381        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    386                 return !overlaps(addr, count << PAGE_WIDTH,
    387                     KERNEL_ADDRESS_SPACE_START,
     382                return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START,
    388383                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    389384        }
     
    448443                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
    449444       
     445        if (area->backend && area->backend->create) {
     446                if (!area->backend->create(area)) {
     447                        free(area);
     448                        mutex_unlock(&as->lock);
     449                        return NULL;
     450                }
     451        }
     452       
    450453        btree_create(&area->used_space);
    451454        btree_insert(&as->as_area_btree, base, (void *) area, NULL);
     
    470473       
    471474        btree_node_t *leaf;
    472         as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     475        as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va,
     476            &leaf);
    473477        if (area) {
    474478                /* va is the base address of an address space area */
     
    478482       
    479483        /*
    480          * Search the leaf node and the righmost record of its left neighbour
     484         * Search the leaf node and the rightmost record of its left neighbour
    481485         * to find out whether this is a miss or va belongs to an address
    482486         * space area found there.
     
    490494               
    491495                mutex_lock(&area->lock);
    492                
     496
    493497                if ((area->base <= va) &&
    494                     (va < area->base + (area->pages << PAGE_WIDTH)))
     498                    (va <= area->base + (P2SZ(area->pages) - 1)))
    495499                        return area;
    496500               
     
    502506         * Because of its position in the B+tree, it must have base < va.
    503507         */
    504         btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     508        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree,
     509            leaf);
    505510        if (lnode) {
    506511                area = (as_area_t *) lnode->value[lnode->keys - 1];
     
    508513                mutex_lock(&area->lock);
    509514               
    510                 if (va < area->base + (area->pages << PAGE_WIDTH))
     515                if (va <= area->base + (P2SZ(area->pages) - 1))
    511516                        return area;
    512517               
     
    573578       
    574579        if (pages < area->pages) {
    575                 uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
     580                uintptr_t start_free = area->base + P2SZ(pages);
    576581               
    577582                /*
     
    586591                 */
    587592                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    588                     area->base + (pages << PAGE_WIDTH), area->pages - pages);
     593                    area->base + P2SZ(pages), area->pages - pages);
    589594               
    590595                /*
     
    609614                                size_t i = 0;
    610615                               
    611                                 if (overlaps(ptr, size << PAGE_WIDTH, area->base,
    612                                     pages << PAGE_WIDTH)) {
     616                                if (overlaps(ptr, P2SZ(size), area->base,
     617                                    P2SZ(pages))) {
    613618                                       
    614                                         if (ptr + (size << PAGE_WIDTH) <= start_free) {
     619                                        if (ptr + P2SZ(size) <= start_free) {
    615620                                                /*
    616621                                                 * The whole interval fits
     
    643648                               
    644649                                for (; i < size; i++) {
    645                                         pte_t *pte = page_mapping_find(as, ptr +
    646                                             (i << PAGE_WIDTH));
     650                                        pte_t *pte = page_mapping_find(as,
     651                                            ptr + P2SZ(i), false);
    647652                                       
    648653                                        ASSERT(pte);
     
    653658                                            (area->backend->frame_free)) {
    654659                                                area->backend->frame_free(area,
    655                                                     ptr + (i << PAGE_WIDTH),
     660                                                    ptr + P2SZ(i),
    656661                                                    PTE_GET_FRAME(pte));
    657662                                        }
    658663                                       
    659                                         page_mapping_remove(as, ptr +
    660                                             (i << PAGE_WIDTH));
     664                                        page_mapping_remove(as, ptr + P2SZ(i));
    661665                                }
    662666                        }
     
    667671                 */
    668672               
    669                 tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
     673                tlb_invalidate_pages(as->asid, area->base + P2SZ(pages),
    670674                    area->pages - pages);
    671675               
    672676                /*
    673                  * Invalidate software translation caches (e.g. TSB on sparc64).
    674                  */
    675                 as_invalidate_translation_cache(as, area->base +
    676                     (pages << PAGE_WIDTH), area->pages - pages);
     677                 * Invalidate software translation caches
     678                 * (e.g. TSB on sparc64, PHT on ppc32).
     679                 */
     680                as_invalidate_translation_cache(as, area->base + P2SZ(pages),
     681                    area->pages - pages);
    677682                tlb_shootdown_finalize(ipl);
    678683               
     
    687692                        mutex_unlock(&as->lock);
    688693                        return EADDRNOTAVAIL;
     694                }
     695        }
     696       
     697        if (area->backend && area->backend->resize) {
     698                if (!area->backend->resize(area, pages)) {
     699                        mutex_unlock(&area->lock);
     700                        mutex_unlock(&as->lock);
     701                        return ENOMEM;
    689702                }
    690703        }
     
    756769                return ENOENT;
    757770        }
     771
     772        if (area->backend && area->backend->destroy)
     773                area->backend->destroy(area);
    758774       
    759775        uintptr_t base = area->base;
     
    782798                       
    783799                        for (size = 0; size < (size_t) node->value[i]; size++) {
    784                                 pte_t *pte =
    785                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     800                                pte_t *pte = page_mapping_find(as,
     801                                     ptr + P2SZ(size), false);
    786802                               
    787803                                ASSERT(pte);
     
    792808                                    (area->backend->frame_free)) {
    793809                                        area->backend->frame_free(area,
    794                                             ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
     810                                            ptr + P2SZ(size),
     811                                            PTE_GET_FRAME(pte));
    795812                                }
    796813                               
    797                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     814                                page_mapping_remove(as, ptr + P2SZ(size));
    798815                        }
    799816                }
     
    807824       
    808825        /*
    809          * Invalidate potential software translation caches (e.g. TSB on
    810          * sparc64).
     826         * Invalidate potential software translation caches
     827         * (e.g. TSB on sparc64, PHT on ppc32).
    811828         */
    812829        as_invalidate_translation_cache(as, area->base, area->pages);
     
    882899        }
    883900       
    884         size_t src_size = src_area->pages << PAGE_WIDTH;
     901        size_t src_size = P2SZ(src_area->pages);
    885902        unsigned int src_flags = src_area->flags;
    886903        mem_backend_t *src_backend = src_area->backend;
     
    10791096        for (cur = area->used_space.leaf_head.next;
    10801097            cur != &area->used_space.leaf_head; cur = cur->next) {
    1081                 btree_node_t *node
    1082                     = list_get_instance(cur, btree_node_t, leaf_link);
     1098                btree_node_t *node = list_get_instance(cur, btree_node_t,
     1099                    leaf_link);
    10831100                btree_key_t i;
    10841101               
     
    10881105                       
    10891106                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1090                                 pte_t *pte =
    1091                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     1107                                pte_t *pte = page_mapping_find(as,
     1108                                    ptr + P2SZ(size), false);
    10921109                               
    10931110                                ASSERT(pte);
     
    10981115                               
    10991116                                /* Remove old mapping */
    1100                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     1117                                page_mapping_remove(as, ptr + P2SZ(size));
    11011118                        }
    11021119                }
     
    11101127       
    11111128        /*
    1112          * Invalidate potential software translation caches (e.g. TSB on
    1113          * sparc64).
     1129         * Invalidate potential software translation caches
     1130         * (e.g. TSB on sparc64, PHT on ppc32).
    11141131         */
    11151132        as_invalidate_translation_cache(as, area->base, area->pages);
     
    11441161                               
    11451162                                /* Insert the new mapping */
    1146                                 page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
     1163                                page_mapping_insert(as, ptr + P2SZ(size),
    11471164                                    old_frame[frame_idx++], page_flags);
    11481165                               
     
    12251242         */
    12261243        pte_t *pte;
    1227         if ((pte = page_mapping_find(AS, page))) {
     1244        if ((pte = page_mapping_find(AS, page, false))) {
    12281245                if (PTE_PRESENT(pte)) {
    12291246                        if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) ||
     
    14661483       
    14671484        if (src_area) {
    1468                 size = src_area->pages << PAGE_WIDTH;
     1485                size = P2SZ(src_area->pages);
    14691486                mutex_unlock(&src_area->lock);
    14701487        } else
     
    15211538                if (page >= right_pg) {
    15221539                        /* Do nothing. */
    1523                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1524                     left_cnt << PAGE_WIDTH)) {
     1540                } else if (overlaps(page, P2SZ(count), left_pg,
     1541                    P2SZ(left_cnt))) {
    15251542                        /* The interval intersects with the left interval. */
    15261543                        return false;
    1527                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1528                     right_cnt << PAGE_WIDTH)) {
     1544                } else if (overlaps(page, P2SZ(count), right_pg,
     1545                    P2SZ(right_cnt))) {
    15291546                        /* The interval intersects with the right interval. */
    15301547                        return false;
    1531                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1532                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1548                } else if ((page == left_pg + P2SZ(left_cnt)) &&
     1549                    (page + P2SZ(count) == right_pg)) {
    15331550                        /*
    15341551                         * The interval can be added by merging the two already
     
    15381555                        btree_remove(&area->used_space, right_pg, leaf);
    15391556                        goto success;
    1540                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1557                } else if (page == left_pg + P2SZ(left_cnt)) {
    15411558                        /*
    15421559                         * The interval can be added by simply growing the left
     
    15451562                        node->value[node->keys - 1] += count;
    15461563                        goto success;
    1547                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1564                } else if (page + P2SZ(count) == right_pg) {
    15481565                        /*
    15491566                         * The interval can be addded by simply moving base of
     
    15721589                 */
    15731590               
    1574                 if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1575                     right_cnt << PAGE_WIDTH)) {
     1591                if (overlaps(page, P2SZ(count), right_pg, P2SZ(right_cnt))) {
    15761592                        /* The interval intersects with the right interval. */
    15771593                        return false;
    1578                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1594                } else if (page + P2SZ(count) == right_pg) {
    15791595                        /*
    15801596                         * The interval can be added by moving the base of the
     
    16111627                if (page < left_pg) {
    16121628                        /* Do nothing. */
    1613                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1614                     left_cnt << PAGE_WIDTH)) {
     1629                } else if (overlaps(page, P2SZ(count), left_pg,
     1630                    P2SZ(left_cnt))) {
    16151631                        /* The interval intersects with the left interval. */
    16161632                        return false;
    1617                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1618                     right_cnt << PAGE_WIDTH)) {
     1633                } else if (overlaps(page, P2SZ(count), right_pg,
     1634                    P2SZ(right_cnt))) {
    16191635                        /* The interval intersects with the right interval. */
    16201636                        return false;
    1621                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1622                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1637                } else if ((page == left_pg + P2SZ(left_cnt)) &&
     1638                    (page + P2SZ(count) == right_pg)) {
    16231639                        /*
    16241640                         * The interval can be added by merging the two already
     
    16281644                        btree_remove(&area->used_space, right_pg, node);
    16291645                        goto success;
    1630                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1646                } else if (page == left_pg + P2SZ(left_cnt)) {
    16311647                        /*
    16321648                         * The interval can be added by simply growing the left
     
    16351651                        leaf->value[leaf->keys - 1] += count;
    16361652                        goto success;
    1637                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1653                } else if (page + P2SZ(count) == right_pg) {
    16381654                        /*
    16391655                         * The interval can be addded by simply moving base of
     
    16621678                 */
    16631679               
    1664                 if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1665                     left_cnt << PAGE_WIDTH)) {
     1680                if (overlaps(page, P2SZ(count), left_pg, P2SZ(left_cnt))) {
    16661681                        /* The interval intersects with the left interval. */
    16671682                        return false;
    1668                 } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
     1683                } else if (left_pg + P2SZ(left_cnt) == page) {
    16691684                        /*
    16701685                         * The interval can be added by growing the left
     
    17011716                         */
    17021717                       
    1703                         if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1704                             left_cnt << PAGE_WIDTH)) {
     1718                        if (overlaps(page, P2SZ(count), left_pg,
     1719                            P2SZ(left_cnt))) {
    17051720                                /*
    17061721                                 * The interval intersects with the left
     
    17081723                                 */
    17091724                                return false;
    1710                         } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1711                             right_cnt << PAGE_WIDTH)) {
     1725                        } else if (overlaps(page, P2SZ(count), right_pg,
     1726                            P2SZ(right_cnt))) {
    17121727                                /*
    17131728                                 * The interval intersects with the right
     
    17151730                                 */
    17161731                                return false;
    1717                         } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1718                             (page + (count << PAGE_WIDTH) == right_pg)) {
     1732                        } else if ((page == left_pg + P2SZ(left_cnt)) &&
     1733                            (page + P2SZ(count) == right_pg)) {
    17191734                                /*
    17201735                                 * The interval can be added by merging the two
     
    17241739                                btree_remove(&area->used_space, right_pg, leaf);
    17251740                                goto success;
    1726                         } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1741                        } else if (page == left_pg + P2SZ(left_cnt)) {
    17271742                                /*
    17281743                                 * The interval can be added by simply growing
     
    17311746                                leaf->value[i - 1] += count;
    17321747                                goto success;
    1733                         } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1748                        } else if (page + P2SZ(count) == right_pg) {
    17341749                                /*
    17351750                                 * The interval can be addded by simply moving
     
    17971812                        for (i = 0; i < leaf->keys; i++) {
    17981813                                if (leaf->key[i] == page) {
    1799                                         leaf->key[i] += count << PAGE_WIDTH;
     1814                                        leaf->key[i] += P2SZ(count);
    18001815                                        leaf->value[i] -= count;
    18011816                                        goto success;
     
    18071822        }
    18081823       
    1809         btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
     1824        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space,
     1825            leaf);
    18101826        if ((node) && (page < leaf->key[0])) {
    18111827                uintptr_t left_pg = node->key[node->keys - 1];
    18121828                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18131829               
    1814                 if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1815                     count << PAGE_WIDTH)) {
    1816                         if (page + (count << PAGE_WIDTH) ==
    1817                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1830                if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
     1831                        if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
    18181832                                /*
    18191833                                 * The interval is contained in the rightmost
     
    18241838                                node->value[node->keys - 1] -= count;
    18251839                                goto success;
    1826                         } else if (page + (count << PAGE_WIDTH) <
    1827                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1840                        } else if (page + P2SZ(count) <
     1841                            left_pg + P2SZ(left_cnt)) {
     1842                                size_t new_cnt;
     1843
    18281844                                /*
    18291845                                 * The interval is contained in the rightmost
     
    18331849                                 * new interval.
    18341850                                 */
    1835                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1836                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1851                                new_cnt = ((left_pg + P2SZ(left_cnt)) -
     1852                                    (page + P2SZ(count))) >> PAGE_WIDTH;
    18371853                                node->value[node->keys - 1] -= count + new_cnt;
    18381854                                btree_insert(&area->used_space, page +
    1839                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1855                                    P2SZ(count), (void *) new_cnt, leaf);
    18401856                                goto success;
    18411857                        }
     
    18501866                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    18511867               
    1852                 if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1853                     count << PAGE_WIDTH)) {
    1854                         if (page + (count << PAGE_WIDTH) ==
    1855                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1868                if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
     1869                        if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
    18561870                                /*
    18571871                                 * The interval is contained in the rightmost
     
    18611875                                leaf->value[leaf->keys - 1] -= count;
    18621876                                goto success;
    1863                         } else if (page + (count << PAGE_WIDTH) < left_pg +
    1864                             (left_cnt << PAGE_WIDTH)) {
     1877                        } else if (page + P2SZ(count) < left_pg +
     1878                            P2SZ(left_cnt)) {
     1879                                size_t new_cnt;
     1880
    18651881                                /*
    18661882                                 * The interval is contained in the rightmost
     
    18701886                                 * interval.
    18711887                                 */
    1872                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1873                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1888                                new_cnt = ((left_pg + P2SZ(left_cnt)) -
     1889                                    (page + P2SZ(count))) >> PAGE_WIDTH;
    18741890                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    18751891                                btree_insert(&area->used_space, page +
    1876                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1892                                    P2SZ(count), (void *) new_cnt, leaf);
    18771893                                goto success;
    18781894                        }
     
    18961912                         * to (i - 1) and i.
    18971913                         */
    1898                         if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1899                             count << PAGE_WIDTH)) {
    1900                                 if (page + (count << PAGE_WIDTH) ==
    1901                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1914                        if (overlaps(left_pg, P2SZ(left_cnt), page,
     1915                            P2SZ(count))) {
     1916                                if (page + P2SZ(count) ==
     1917                                    left_pg + P2SZ(left_cnt)) {
    19021918                                        /*
    19031919                                         * The interval is contained in the
     
    19081924                                        leaf->value[i - 1] -= count;
    19091925                                        goto success;
    1910                                 } else if (page + (count << PAGE_WIDTH) <
    1911                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1926                                } else if (page + P2SZ(count) <
     1927                                    left_pg + P2SZ(left_cnt)) {
     1928                                        size_t new_cnt;
     1929
    19121930                                        /*
    19131931                                         * The interval is contained in the
     
    19171935                                         * also inserting a new interval.
    19181936                                         */
    1919                                         size_t new_cnt = ((left_pg +
    1920                                             (left_cnt << PAGE_WIDTH)) -
    1921                                             (page + (count << PAGE_WIDTH))) >>
     1937                                        new_cnt = ((left_pg + P2SZ(left_cnt)) -
     1938                                            (page + P2SZ(count))) >>
    19221939                                            PAGE_WIDTH;
    19231940                                        leaf->value[i - 1] -= count + new_cnt;
    19241941                                        btree_insert(&area->used_space, page +
    1925                                             (count << PAGE_WIDTH), (void *) new_cnt,
     1942                                            P2SZ(count), (void *) new_cnt,
    19261943                                            leaf);
    19271944                                        goto success;
     
    20192036                btree_key_t i;
    20202037                for (i = 0; (ret == 0) && (i < node->keys); i++) {
     2038                        uintptr_t addr;
     2039
    20212040                        as_area_t *area = (as_area_t *) node->value[i];
    20222041                       
    20232042                        mutex_lock(&area->lock);
    20242043                       
    2025                         uintptr_t addr =
    2026                             ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
     2044                        addr = ALIGN_UP(area->base + P2SZ(area->pages),
    20272045                            PAGE_SIZE);
    20282046                       
     
    20832101                       
    20842102                        info[area_idx].start_addr = area->base;
    2085                         info[area_idx].size = FRAMES2SIZE(area->pages);
     2103                        info[area_idx].size = P2SZ(area->pages);
    20862104                        info[area_idx].flags = area->flags;
    20872105                        ++area_idx;
     
    21212139                            " (%p - %p)\n", area, (void *) area->base,
    21222140                            area->pages, (void *) area->base,
    2123                             (void *) (area->base + FRAMES2SIZE(area->pages)));
     2141                            (void *) (area->base + P2SZ(area->pages)));
    21242142                        mutex_unlock(&area->lock);
    21252143                }
  • kernel/generic/src/mm/backend_anon.c

    r18ba2e4f r544a2e4  
    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>
     
    4950#include <typedefs.h>
    5051#include <align.h>
     52#include <memstr.h>
    5153#include <arch.h>
    5254
    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);
     55static bool anon_create(as_area_t *);
     56static bool anon_resize(as_area_t *, size_t);
     57static void anon_share(as_area_t *);
     58static void anon_destroy(as_area_t *);
     59
     60static int anon_page_fault(as_area_t *, uintptr_t, pf_access_t);
     61static void anon_frame_free(as_area_t *, uintptr_t, uintptr_t);
    6062
    6163mem_backend_t anon_backend = {
     64        .create = anon_create,
     65        .resize = anon_resize,
     66        .share = anon_share,
     67        .destroy = anon_destroy,
     68
    6269        .page_fault = anon_page_fault,
    6370        .frame_free = anon_frame_free,
    64         .share = anon_share
    6571};
     72
     73bool anon_create(as_area_t *area)
     74{
     75        return reserve_try_alloc(area->pages);
     76}
     77
     78bool anon_resize(as_area_t *area, size_t new_pages)
     79{
     80        if (new_pages > area->pages)
     81                return reserve_try_alloc(new_pages - area->pages);
     82        else if (new_pages < area->pages)
     83                reserve_free(area->pages - new_pages);
     84
     85        return true;
     86}
     87
     88/** Share the anonymous address space area.
     89 *
     90 * Sharing of anonymous area is done by duplicating its entire mapping
     91 * to the pagemap. Page faults will primarily search for frames there.
     92 *
     93 * The address space and address space area must be already locked.
     94 *
     95 * @param area Address space area to be shared.
     96 */
     97void anon_share(as_area_t *area)
     98{
     99        link_t *cur;
     100
     101        ASSERT(mutex_locked(&area->as->lock));
     102        ASSERT(mutex_locked(&area->lock));
     103
     104        /*
     105         * Copy used portions of the area to sh_info's page map.
     106         */
     107        mutex_lock(&area->sh_info->lock);
     108        for (cur = area->used_space.leaf_head.next;
     109            cur != &area->used_space.leaf_head; cur = cur->next) {
     110                btree_node_t *node;
     111                unsigned int i;
     112               
     113                node = list_get_instance(cur, btree_node_t, leaf_link);
     114                for (i = 0; i < node->keys; i++) {
     115                        uintptr_t base = node->key[i];
     116                        size_t count = (size_t) node->value[i];
     117                        unsigned int j;
     118                       
     119                        for (j = 0; j < count; j++) {
     120                                pte_t *pte;
     121                       
     122                                page_table_lock(area->as, false);
     123                                pte = page_mapping_find(area->as,
     124                                    base + P2SZ(j), false);
     125                                ASSERT(pte && PTE_VALID(pte) &&
     126                                    PTE_PRESENT(pte));
     127                                btree_insert(&area->sh_info->pagemap,
     128                                    (base + P2SZ(j)) - area->base,
     129                                    (void *) PTE_GET_FRAME(pte), NULL);
     130                                page_table_unlock(area->as, false);
     131
     132                                pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
     133                                frame_reference_add(pfn);
     134                        }
     135
     136                }
     137        }
     138        mutex_unlock(&area->sh_info->lock);
     139}
     140
     141void anon_destroy(as_area_t *area)
     142{
     143        reserve_free(area->pages);
     144}
     145
    66146
    67147/** Service a page fault in the anonymous memory address space area.
     
    115195                        }
    116196                        if (allocate) {
    117                                 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
     197                                frame = (uintptr_t) frame_alloc_noreserve(
     198                                    ONE_FRAME, 0);
    118199                                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    119200                               
     
    145226                 *   the different causes
    146227                 */
    147                 frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
     228                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
    148229                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
    149230        }
     
    174255        ASSERT(mutex_locked(&area->lock));
    175256
    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);
     257        frame_free_noreserve(frame);
    230258}
    231259
  • kernel/generic/src/mm/backend_elf.c

    r18ba2e4f r544a2e4  
    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
     
    321170                        if (!(area->flags & AS_AREA_WRITE))
    322171                                if (base >= entry->p_vaddr &&
    323                                     base + count * PAGE_SIZE <= start_anon)
     172                                    base + P2SZ(count) <= start_anon)
    324173                                        continue;
    325174                       
     
    333182                                if (!(area->flags & AS_AREA_WRITE))
    334183                                        if (base >= entry->p_vaddr &&
    335                                             base + (j + 1) * PAGE_SIZE <=
    336                                             start_anon)
     184                                            base + P2SZ(j + 1) <= start_anon)
    337185                                                continue;
    338186                               
    339187                                page_table_lock(area->as, false);
    340188                                pte = page_mapping_find(area->as,
    341                                     base + j * PAGE_SIZE);
     189                                    base + P2SZ(j), false);
    342190                                ASSERT(pte && PTE_VALID(pte) &&
    343191                                    PTE_PRESENT(pte));
    344192                                btree_insert(&area->sh_info->pagemap,
    345                                     (base + j * PAGE_SIZE) - area->base,
     193                                    (base + P2SZ(j)) - area->base,
    346194                                    (void *) PTE_GET_FRAME(pte), NULL);
    347195                                page_table_unlock(area->as, false);
     
    356204}
    357205
     206void elf_destroy(as_area_t *area)
     207{
     208        size_t nonanon_pages = elf_nonanon_pages_get(area);
     209
     210        if (area->pages > nonanon_pages)
     211                reserve_free(area->pages - nonanon_pages);
     212}
     213
     214/** Service a page fault in the ELF backend address space area.
     215 *
     216 * The address space area and page tables must be already locked.
     217 *
     218 * @param area          Pointer to the address space area.
     219 * @param addr          Faulting virtual address.
     220 * @param access        Access mode that caused the fault (i.e.
     221 *                      read/write/exec).
     222 *
     223 * @return              AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK
     224 *                      on success (i.e. serviced).
     225 */
     226int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
     227{
     228        elf_header_t *elf = area->backend_data.elf;
     229        elf_segment_header_t *entry = area->backend_data.segment;
     230        btree_node_t *leaf;
     231        uintptr_t base, frame, page, start_anon;
     232        size_t i;
     233        bool dirty = false;
     234
     235        ASSERT(page_table_locked(AS));
     236        ASSERT(mutex_locked(&area->lock));
     237
     238        if (!as_area_check_access(area, access))
     239                return AS_PF_FAULT;
     240       
     241        if (addr < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
     242                return AS_PF_FAULT;
     243       
     244        if (addr >= entry->p_vaddr + entry->p_memsz)
     245                return AS_PF_FAULT;
     246       
     247        i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
     248        base = (uintptr_t)
     249            (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
     250
     251        /* Virtual address of faulting page*/
     252        page = ALIGN_DOWN(addr, PAGE_SIZE);
     253
     254        /* Virtual address of the end of initialized part of segment */
     255        start_anon = entry->p_vaddr + entry->p_filesz;
     256
     257        if (area->sh_info) {
     258                bool found = false;
     259
     260                /*
     261                 * The address space area is shared.
     262                 */
     263               
     264                mutex_lock(&area->sh_info->lock);
     265                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
     266                    page - area->base, &leaf);
     267                if (!frame) {
     268                        unsigned int i;
     269
     270                        /*
     271                         * Workaround for valid NULL address.
     272                         */
     273
     274                        for (i = 0; i < leaf->keys; i++) {
     275                                if (leaf->key[i] == page - area->base) {
     276                                        found = true;
     277                                        break;
     278                                }
     279                        }
     280                }
     281                if (frame || found) {
     282                        frame_reference_add(ADDR2PFN(frame));
     283                        page_mapping_insert(AS, addr, frame,
     284                            as_area_get_flags(area));
     285                        if (!used_space_insert(area, page, 1))
     286                                panic("Cannot insert used space.");
     287                        mutex_unlock(&area->sh_info->lock);
     288                        return AS_PF_OK;
     289                }
     290        }
     291
     292        /*
     293         * The area is either not shared or the pagemap does not contain the
     294         * mapping.
     295         */
     296        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     297                /*
     298                 * Initialized portion of the segment. The memory is backed
     299                 * directly by the content of the ELF image. Pages are
     300                 * only copied if the segment is writable so that there
     301                 * can be more instantions of the same memory ELF image
     302                 * used at a time. Note that this could be later done
     303                 * as COW.
     304                 */
     305                if (entry->p_flags & PF_W) {
     306                        frame = (uintptr_t)frame_alloc_noreserve(ONE_FRAME, 0);
     307                        memcpy((void *) PA2KA(frame),
     308                            (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
     309                        if (entry->p_flags & PF_X) {
     310                                smc_coherence_block((void *) PA2KA(frame),
     311                                    FRAME_SIZE);
     312                        }
     313                        dirty = true;
     314                } else {
     315                        frame = KA2PA(base + i * FRAME_SIZE);
     316                }       
     317        } else if (page >= start_anon) {
     318                /*
     319                 * This is the uninitialized portion of the segment.
     320                 * It is not physically present in the ELF image.
     321                 * To resolve the situation, a frame must be allocated
     322                 * and cleared.
     323                 */
     324                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
     325                memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
     326                dirty = true;
     327        } else {
     328                size_t pad_lo, pad_hi;
     329                /*
     330                 * The mixed case.
     331                 *
     332                 * The middle part is backed by the ELF image and
     333                 * the lower and upper parts are anonymous memory.
     334                 * (The segment can be and often is shorter than 1 page).
     335                 */
     336                if (page < entry->p_vaddr)
     337                        pad_lo = entry->p_vaddr - page;
     338                else
     339                        pad_lo = 0;
     340
     341                if (start_anon < page + PAGE_SIZE)
     342                        pad_hi = page + PAGE_SIZE - start_anon;
     343                else
     344                        pad_hi = 0;
     345
     346                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
     347                memcpy((void *) (PA2KA(frame) + pad_lo),
     348                    (void *) (base + i * FRAME_SIZE + pad_lo),
     349                    FRAME_SIZE - pad_lo - pad_hi);
     350                if (entry->p_flags & PF_X) {
     351                        smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
     352                            FRAME_SIZE - pad_lo - pad_hi);
     353                }
     354                memsetb((void *) PA2KA(frame), pad_lo, 0);
     355                memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
     356                    0);
     357                dirty = true;
     358        }
     359
     360        if (dirty && area->sh_info) {
     361                frame_reference_add(ADDR2PFN(frame));
     362                btree_insert(&area->sh_info->pagemap, page - area->base,
     363                    (void *) frame, leaf);
     364        }
     365
     366        if (area->sh_info)
     367                mutex_unlock(&area->sh_info->lock);
     368
     369        page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
     370        if (!used_space_insert(area, page, 1))
     371                panic("Cannot insert used space.");
     372
     373        return AS_PF_OK;
     374}
     375
     376/** Free a frame that is backed by the ELF backend.
     377 *
     378 * The address space area and page tables must be already locked.
     379 *
     380 * @param area          Pointer to the address space area.
     381 * @param page          Page that is mapped to frame. Must be aligned to
     382 *                      PAGE_SIZE.
     383 * @param frame         Frame to be released.
     384 *
     385 */
     386void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame)
     387{
     388        elf_segment_header_t *entry = area->backend_data.segment;
     389        uintptr_t start_anon;
     390
     391        ASSERT(page_table_locked(area->as));
     392        ASSERT(mutex_locked(&area->lock));
     393
     394        ASSERT(page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE));
     395        ASSERT(page < entry->p_vaddr + entry->p_memsz);
     396
     397        start_anon = entry->p_vaddr + entry->p_filesz;
     398
     399        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     400                if (entry->p_flags & PF_W) {
     401                        /*
     402                         * Free the frame with the copy of writable segment
     403                         * data.
     404                         */
     405                        frame_free_noreserve(frame);
     406                }
     407        } else {
     408                /*
     409                 * The frame is either anonymous memory or the mixed case (i.e.
     410                 * lower part is backed by the ELF image and the upper is
     411                 * anonymous). In any case, a frame needs to be freed.
     412                 */
     413                frame_free_noreserve(frame);
     414        }
     415}
     416
    358417/** @}
    359418 */
  • kernel/generic/src/mm/backend_phys.c

    r18ba2e4f r544a2e4  
    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

    r18ba2e4f r544a2e4  
    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/mm/page.c

    r18ba2e4f r544a2e4  
    108108 * using flags. Allocate and setup any missing page tables.
    109109 *
    110  * @param as    Address space to wich page belongs.
     110 * @param as    Address space to which page belongs.
    111111 * @param page  Virtual address of the page to be mapped.
    112112 * @param frame Physical address of memory frame to which the mapping is
     
    135135 * this call visible.
    136136 *
    137  * @param as   Address space to wich page belongs.
     137 * @param as   Address space to which page belongs.
    138138 * @param page Virtual address of the page to be demapped.
    139139 *
     
    152152}
    153153
    154 /** Find mapping for virtual page
     154/** Find mapping for virtual page.
    155155 *
    156  * Find mapping for virtual page.
    157  *
    158  * @param as   Address space to wich page belongs.
    159  * @param page Virtual page.
     156 * @param as     Address space to which page belongs.
     157 * @param page   Virtual page.
     158 * @param nolock True if the page tables need not be locked.
    160159 *
    161160 * @return NULL if there is no such mapping; requested mapping
     
    163162 *
    164163 */
    165 NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page)
     164NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page, bool nolock)
    166165{
    167         ASSERT(page_table_locked(as));
     166        ASSERT(nolock || page_table_locked(as));
    168167       
    169168        ASSERT(page_mapping_operations);
    170169        ASSERT(page_mapping_operations->mapping_find);
    171170       
    172         return page_mapping_operations->mapping_find(as, page);
     171        return page_mapping_operations->mapping_find(as, page, nolock);
    173172}
    174173
  • kernel/generic/src/printf/vprintf.c

    r18ba2e4f r544a2e4  
    4141#include <typedefs.h>
    4242#include <str.h>
    43 
    44 IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(printf_lock, "*printf_lock");
    4543
    4644static int vprintf_str_write(const char *str, size_t size, void *data)
     
    9391        };
    9492       
    95         irq_spinlock_lock(&printf_lock, true);
    96         int ret = printf_core(fmt, &ps, ap);
    97         irq_spinlock_unlock(&printf_lock, true);
    98        
    99         return ret;
     93        return printf_core(fmt, &ps, ap);
    10094}
    10195
  • kernel/generic/src/proc/program.c

    r18ba2e4f r544a2e4  
    5454#include <proc/program.h>
    5555
    56 #ifndef LOADED_PROG_STACK_PAGES_NO
    57 #define LOADED_PROG_STACK_PAGES_NO 1
    58 #endif
    59 
    6056/**
    6157 * Points to the binary image used as the program loader. All non-initial
     
    9086       
    9187        /*
    92          * Create the data address space area.
     88         * Create the stack address space area.
    9389         */
    9490        as_area_t *area = as_area_create(as,
    9591            AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
    96             LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
    97             AS_AREA_ATTR_NONE, &anon_backend, NULL);
     92            STACK_SIZE, USTACK_ADDRESS, AS_AREA_ATTR_NONE,
     93            &anon_backend, NULL);
    9894        if (!area)
    9995                return ENOMEM;
  • kernel/generic/src/proc/scheduler.c

    r18ba2e4f r544a2e4  
    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.
     
    376376        context_save(&CPU->saved_context);
    377377        context_set(&CPU->saved_context, FADDR(scheduler_separated_stack),
    378             (uintptr_t) CPU->stack, CPU_STACK_SIZE);
     378            (uintptr_t) CPU->stack, STACK_SIZE);
    379379        context_restore(&CPU->saved_context);
    380380       
  • kernel/generic/src/proc/task.c

    r18ba2e4f r544a2e4  
    190190        str_cpy(task->name, TASK_NAME_BUFLEN, name);
    191191       
    192         task->context = CONTEXT;
     192        task->container = CONTAINER;
    193193        task->capabilities = 0;
    194194        task->ucycles = 0;
     
    211211       
    212212        if ((ipc_phone_0) &&
    213             (context_check(ipc_phone_0->task->context, task->context)))
     213            (container_check(ipc_phone_0->task->container, task->container)))
    214214                ipc_phone_connect(&task->phones[0], ipc_phone_0);
    215215       
     
    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. */
     
    586584                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p"
    587585                    " %9" PRIu64 "%c %9" PRIu64 "%c\n", task->taskid,
    588                     task->name, task->context, task, task->as,
     586                    task->name, task->container, task, task->as,
    589587                    ucycles, usuffix, kcycles, ksuffix);
    590588#endif
     
    597595        else
    598596                printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n",
    599                     task->taskid, task->name, task->context, task, task->as);
     597                    task->taskid, task->name, task->container, task, task->as);
    600598#endif
    601599       
     
    627625                printf("[id    ] [threads] [calls] [callee\n");
    628626        else
    629                 printf("[id    ] [name        ] [ctx] [address ] [as      ]"
     627                printf("[id    ] [name        ] [ctn] [address ] [as      ]"
    630628                    " [ucycles ] [kcycles ]\n");
    631629#endif
     
    636634                    " [callee\n");
    637635        else
    638                 printf("[id    ] [name        ] [ctx] [address         ]"
     636                printf("[id    ] [name        ] [ctn] [address         ]"
    639637                    " [as              ]\n");
    640638#endif
  • kernel/generic/src/proc/the.c

    r18ba2e4f r544a2e4  
    5858        the->task = NULL;
    5959        the->as = NULL;
     60        the->magic = MAGIC;
    6061}
    6162
     
    7071NO_TRACE void the_copy(the_t *src, the_t *dst)
    7172{
     73        ASSERT(src->magic == MAGIC);
    7274        *dst = *src;
    7375}
  • kernel/generic/src/proc/thread.c

    r18ba2e4f r544a2e4  
    6868#include <errno.h>
    6969
    70 
    71 #ifndef LOADED_PROG_STACK_PAGES_NO
    72 #define LOADED_PROG_STACK_PAGES_NO 1
    73 #endif
    74 
    75 
    7670/** Thread states */
    7771const char *thread_states[] = {
     
    300294       
    301295        /* Not needed, but good for debugging */
    302         memsetb(thread->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
     296        memsetb(thread->kstack, STACK_SIZE, 0);
    303297       
    304298        irq_spinlock_lock(&tidlock, true);
     
    308302        context_save(&thread->saved_context);
    309303        context_set(&thread->saved_context, FADDR(cushion),
    310             (uintptr_t) thread->kstack, THREAD_STACK_SIZE);
     304            (uintptr_t) thread->kstack, STACK_SIZE);
    311305       
    312306        the_initialize((the_t *) thread->kstack);
     
    605599                printf("%-8" PRIu64 " %-14s %10p %-8s %10p %-5" PRIu32 "\n",
    606600                    thread->tid, name, thread, thread_states[thread->state],
    607                     thread->task, thread->task->context);
     601                    thread->task, thread->task->container);
    608602#endif
    609603       
     
    617611                printf("%-8" PRIu64 " %-14s %18p %-8s %18p %-5" PRIu32 "\n",
    618612                    thread->tid, name, thread, thread_states[thread->state],
    619                     thread->task, thread->task->context);
     613                    thread->task, thread->task->container);
    620614#endif
    621615       
     
    658652        else
    659653                printf("[id    ] [name        ] [address ] [state ] [task    ]"
    660                     " [ctx]\n");
     654                    " [ctn]\n");
    661655#endif
    662656       
     
    667661        } else
    668662                printf("[id    ] [name        ] [address         ] [state ]"
    669                     " [task            ] [ctx]\n");
     663                    " [task            ] [ctn]\n");
    670664#endif
    671665       
  • kernel/generic/src/security/cap.c

    r18ba2e4f r544a2e4  
    9292        task_t *task = task_find_by_id(taskid);
    9393       
    94         if ((!task) || (!context_check(CONTEXT, task->context))) {
     94        if ((!task) || (!container_check(CONTAINER, task->container))) {
    9595                irq_spinlock_unlock(&tasks_lock, true);
    9696                return (sysarg_t) ENOENT;
     
    121121       
    122122        task_t *task = task_find_by_id(taskid);
    123         if ((!task) || (!context_check(CONTEXT, task->context))) {
     123        if ((!task) || (!container_check(CONTAINER, task->container))) {
    124124                irq_spinlock_unlock(&tasks_lock, true);
    125125                return (sysarg_t) ENOENT;
  • kernel/generic/src/synch/futex.c

    r18ba2e4f r544a2e4  
    119119         */
    120120        page_table_lock(AS, true);
    121         t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
     121        t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE), false);
    122122        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    123123                page_table_unlock(AS, true);
     
    155155         */
    156156        page_table_lock(AS, true);
    157         t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
     157        t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE), false);
    158158        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    159159                page_table_unlock(AS, true);
  • kernel/generic/src/synch/spinlock.c

    r18ba2e4f r544a2e4  
    9696                 * run in a simulator) that caused problems with both
    9797                 * printf_lock and the framebuffer lock.
    98                  *
    9998                 */
    10099                if (lock->name[0] == '*')
  • kernel/generic/src/syscall/syscall.c

    r18ba2e4f r544a2e4  
    161161        /* Event notification syscalls. */
    162162        (syshandler_t) sys_event_subscribe,
     163        (syshandler_t) sys_event_unmask,
    163164       
    164165        /* Capabilities related syscalls. */
Note: See TracChangeset for help on using the changeset viewer.