Changes in / [321052f7:3fe58d3c] in mainline


Ignore:
Location:
kernel
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/include/mm/km.h

    r321052f7 r3fe58d3c  
    3939
    4040#define KM_ARM32_IDENTITY_START         UINT32_C(0x80000000)
    41 #define KM_ARM32_IDENTITY_SIZE          UINT32_C(0x40000000)
     41#define KM_ARM32_IDENTITY_SIZE          UINT32_C(0x70000000)
    4242
    43 #define KM_ARM32_NON_IDENTITY_START     UINT32_C(0xc0000000)
    44 #define KM_ARM32_NON_IDENTITY_SIZE      UINT32_C(0x40000000)
     43#define KM_ARM32_NON_IDENTITY_START     UINT32_C(0xf0000000)
     44/*
     45 * The last virtual megabyte contains the high exception vectors (0xFFFF0000).
     46 * Do not include this range into kernel non-identity.
     47 */
     48#define KM_ARM32_NON_IDENTITY_SIZE      UINT32_C(0x0ff00000)
    4549
    4650extern void km_identity_arch_init(void);
  • kernel/arch/arm32/src/mm/page.c

    r321052f7 r3fe58d3c  
    6565                page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
    6666       
     67#ifdef HIGH_EXCEPTION_VECTORS
    6768        /* Create mapping for exception table at high offset */
    68 #ifdef HIGH_EXCEPTION_VECTORS
    69         // XXX: fixme to use proper non-identity page
    70         void *virtaddr = frame_alloc(ONE_FRAME, FRAME_KA);
    71         page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr),
    72             flags);
     69        uintptr_t ev_frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_NONE);
     70        page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, ev_frame, flags);
    7371#else
    7472#error "Only high exception vector supported now"
    7573#endif
    76         cur = ALIGN_DOWN(0x50008010, FRAME_SIZE);
    77         page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
    7874
    7975        page_table_unlock(AS_KERNEL, true);
  • kernel/arch/ia32/src/mm/frame.c

    r321052f7 r3fe58d3c  
    5454       
    5555        for (i = 0; i < e820counter; i++) {
    56                 uintptr_t base = (uintptr_t) e820table[i].base_address;
    57                 size_t size = (size_t) e820table[i].size;
     56                uint64_t base64 = e820table[i].base_address;
     57                uint64_t size64 = e820table[i].size;
     58
     59#ifdef KARCH_ia32
     60                /*
     61                 * Restrict the e820 table entries to 32-bits.
     62                 */
     63                if (base64 >= 0x100000000ULL)
     64                        continue;
     65                if (base64 + size64 > 0x100000000ULL)
     66                        size64 -= base64 + size64 - 0x100000000ULL;
     67#endif
     68
     69                uintptr_t base = (uintptr_t) base64;
     70                size_t size = (size_t) size64;
    5871               
    5972                if (!frame_adjust_zone_bounds(low, &base, &size))
  • kernel/genarch/src/mm/page_pt.c

    r321052f7 r3fe58d3c  
    322322
    323323        ASSERT(ispwr2(ptl0step));
    324 
    325         for (addr = ALIGN_DOWN(base, ptl0step); addr < base + size;
     324        ASSERT(size > 0);
     325
     326        for (addr = ALIGN_DOWN(base, ptl0step); addr - 1 < base + size - 1;
    326327            addr += ptl0step) {
    327328                uintptr_t l1;
  • kernel/generic/include/mm/frame.h

    r321052f7 r3fe58d3c  
    8383#define FRAME_TO_ZONE_FLAGS(ff) \
    8484        ((((ff) & FRAME_LOWMEM) ? ZONE_LOWMEM : \
    85             (((ff) & FRAME_HIGHMEM) ? ZONE_HIGHMEM : ZONE_NONE)) | \
    86             (ZONE_AVAILABLE | ZONE_LOWMEM /* | ZONE_HIGHMEM */))
     85            (((ff) & FRAME_HIGHMEM) ? ZONE_HIGHMEM : \
     86            ZONE_LOWMEM /* | ZONE_HIGHMEM */)) | \
     87            ZONE_AVAILABLE)
    8788
    8889#define ZONE_FLAGS_MATCH(zf, f) \
  • kernel/generic/include/mm/km.h

    r321052f7 r3fe58d3c  
    3737
    3838#include <typedefs.h>
     39#include <mm/frame.h>
    3940
    4041extern void km_identity_init(void);
     
    4849extern bool km_is_non_identity(uintptr_t);
    4950
     51extern uintptr_t km_temporary_page_get(uintptr_t *, frame_flags_t);
     52extern void km_temporary_page_put(uintptr_t);
     53
    5054#endif
    5155
  • kernel/generic/src/mm/backend_anon.c

    r321052f7 r3fe58d3c  
    4444#include <mm/frame.h>
    4545#include <mm/slab.h>
     46#include <mm/km.h>
    4647#include <synch/mutex.h>
    4748#include <adt/list.h>
     
    155156int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
    156157{
     158        uintptr_t upage = ALIGN_DOWN(addr, PAGE_SIZE);
     159        uintptr_t kpage;
    157160        uintptr_t frame;
    158161
     
    175178                mutex_lock(&area->sh_info->lock);
    176179                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
    177                     ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
     180                    upage - area->base, &leaf);
    178181                if (!frame) {
    179182                        bool allocate = true;
     
    185188                         */
    186189                        for (i = 0; i < leaf->keys; i++) {
    187                                 if (leaf->key[i] ==
    188                                     ALIGN_DOWN(addr, PAGE_SIZE) - area->base) {
     190                                if (leaf->key[i] == upage - area->base) {
    189191                                        allocate = false;
    190192                                        break;
     
    192194                        }
    193195                        if (allocate) {
    194                                 frame = (uintptr_t) frame_alloc_noreserve(
    195                                     ONE_FRAME, 0);
    196                                 memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
     196                                kpage = km_temporary_page_get(&frame,
     197                                    FRAME_NO_RESERVE);
     198                                memsetb((void *) kpage, PAGE_SIZE, 0);
     199                                km_temporary_page_put(kpage);
    197200                               
    198201                                /*
     
    201204                                 */
    202205                                btree_insert(&area->sh_info->pagemap,
    203                                     ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
    204                                     (void *) frame, leaf);
     206                                    upage - area->base, (void *) frame, leaf);
    205207                        }
    206208                }
     
    223225                 *   the different causes
    224226                 */
    225                 frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
    226                 memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
     227                kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
     228                memsetb((void *) kpage, PAGE_SIZE, 0);
     229                km_temporary_page_put(kpage);
    227230        }
    228231       
    229232        /*
    230          * Map 'page' to 'frame'.
     233         * Map 'upage' to 'frame'.
    231234         * Note that TLB shootdown is not attempted as only new information is
    232235         * being inserted into page tables.
    233236         */
    234         page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
    235         if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
     237        page_mapping_insert(AS, upage, frame, as_area_get_flags(area));
     238        if (!used_space_insert(area, upage, 1))
    236239                panic("Cannot insert used space.");
    237240               
  • kernel/generic/src/mm/backend_elf.c

    r321052f7 r3fe58d3c  
    4444#include <mm/page.h>
    4545#include <mm/reserve.h>
     46#include <mm/km.h>
    4647#include <genarch/mm/page_pt.h>
    4748#include <genarch/mm/page_ht.h>
     
    229230        elf_segment_header_t *entry = area->backend_data.segment;
    230231        btree_node_t *leaf;
    231         uintptr_t base, frame, page, start_anon;
     232        uintptr_t base;
     233        uintptr_t frame;
     234        uintptr_t kpage;
     235        uintptr_t upage;
     236        uintptr_t start_anon;
    232237        size_t i;
    233238        bool dirty = false;
     
    249254            (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
    250255
    251         /* Virtual address of faulting page*/
    252         page = ALIGN_DOWN(addr, PAGE_SIZE);
     256        /* Virtual address of faulting page */
     257        upage = ALIGN_DOWN(addr, PAGE_SIZE);
    253258
    254259        /* Virtual address of the end of initialized part of segment */
     
    264269                mutex_lock(&area->sh_info->lock);
    265270                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
    266                     page - area->base, &leaf);
     271                    upage - area->base, &leaf);
    267272                if (!frame) {
    268273                        unsigned int i;
     
    273278
    274279                        for (i = 0; i < leaf->keys; i++) {
    275                                 if (leaf->key[i] == page - area->base) {
     280                                if (leaf->key[i] == upage - area->base) {
    276281                                        found = true;
    277282                                        break;
     
    281286                if (frame || found) {
    282287                        frame_reference_add(ADDR2PFN(frame));
    283                         page_mapping_insert(AS, addr, frame,
     288                        page_mapping_insert(AS, upage, frame,
    284289                            as_area_get_flags(area));
    285                         if (!used_space_insert(area, page, 1))
     290                        if (!used_space_insert(area, upage, 1))
    286291                                panic("Cannot insert used space.");
    287292                        mutex_unlock(&area->sh_info->lock);
     
    294299         * mapping.
    295300         */
    296         if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
     301        if (upage >= entry->p_vaddr && upage + PAGE_SIZE <= start_anon) {
    297302                /*
    298303                 * Initialized portion of the segment. The memory is backed
     
    304309                 */
    305310                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);
     311                        kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
     312                        memcpy((void *) kpage, (void *) (base + i * PAGE_SIZE),
     313                            PAGE_SIZE);
    309314                        if (entry->p_flags & PF_X) {
    310                                 smc_coherence_block((void *) PA2KA(frame),
    311                                     FRAME_SIZE);
     315                                smc_coherence_block((void *) kpage, PAGE_SIZE);
    312316                        }
     317                        km_temporary_page_put(kpage);
    313318                        dirty = true;
    314319                } else {
    315320                        frame = KA2PA(base + i * FRAME_SIZE);
    316321                }       
    317         } else if (page >= start_anon) {
     322        } else if (upage >= start_anon) {
    318323                /*
    319324                 * This is the uninitialized portion of the segment.
     
    322327                 * and cleared.
    323328                 */
    324                 frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
    325                 memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
     329                kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
     330                memsetb((void *) kpage, PAGE_SIZE, 0);
     331                km_temporary_page_put(kpage);
    326332                dirty = true;
    327333        } else {
     
    334340                 * (The segment can be and often is shorter than 1 page).
    335341                 */
    336                 if (page < entry->p_vaddr)
    337                         pad_lo = entry->p_vaddr - page;
     342                if (upage < entry->p_vaddr)
     343                        pad_lo = entry->p_vaddr - upage;
    338344                else
    339345                        pad_lo = 0;
    340346
    341                 if (start_anon < page + PAGE_SIZE)
    342                         pad_hi = page + PAGE_SIZE - start_anon;
     347                if (start_anon < upage + PAGE_SIZE)
     348                        pad_hi = upage + PAGE_SIZE - start_anon;
    343349                else
    344350                        pad_hi = 0;
    345351
    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);
     352                kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
     353                memcpy((void *) (kpage + pad_lo),
     354                    (void *) (base + i * PAGE_SIZE + pad_lo),
     355                    PAGE_SIZE - pad_lo - pad_hi);
    350356                if (entry->p_flags & PF_X) {
    351                         smc_coherence_block((void *) (PA2KA(frame) + pad_lo),
    352                             FRAME_SIZE - pad_lo - pad_hi);
     357                        smc_coherence_block((void *) (kpage + pad_lo),
     358                            PAGE_SIZE - pad_lo - pad_hi);
    353359                }
    354                 memsetb((void *) PA2KA(frame), pad_lo, 0);
    355                 memsetb((void *) (PA2KA(frame) + FRAME_SIZE - pad_hi), pad_hi,
    356                     0);
     360                memsetb((void *) kpage, pad_lo, 0);
     361                memsetb((void *) (kpage + PAGE_SIZE - pad_hi), pad_hi, 0);
     362                km_temporary_page_put(kpage);
    357363                dirty = true;
    358364        }
     
    360366        if (dirty && area->sh_info) {
    361367                frame_reference_add(ADDR2PFN(frame));
    362                 btree_insert(&area->sh_info->pagemap, page - area->base,
     368                btree_insert(&area->sh_info->pagemap, upage - area->base,
    363369                    (void *) frame, leaf);
    364370        }
     
    367373                mutex_unlock(&area->sh_info->lock);
    368374
    369         page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
    370         if (!used_space_insert(area, page, 1))
     375        page_mapping_insert(AS, upage, frame, as_area_get_flags(area));
     376        if (!used_space_insert(area, upage, 1))
    371377                panic("Cannot insert used space.");
    372378
  • kernel/generic/src/mm/km.c

    r321052f7 r3fe58d3c  
    3939#include <arch/mm/km.h>
    4040#include <mm/page.h>
     41#include <mm/frame.h>
     42#include <mm/asid.h>
    4143#include <config.h>
    4244#include <typedefs.h>
    4345#include <lib/ra.h>
    4446#include <debug.h>
     47#include <arch.h>
    4548
    4649static ra_arena_t *km_ni_arena;
     50
     51#define DEFERRED_PAGES_MAX      (PAGE_SIZE / sizeof(uintptr_t))
     52
     53/** Number of freed pages in the deferred buffer. */
     54static volatile unsigned deferred_pages;
     55/** Buffer of deferred freed pages. */
     56static uintptr_t deferred_page[DEFERRED_PAGES_MAX];
     57
     58/** Flush the buffer of deferred freed pages.
     59 *
     60 * @return              Number of freed pages.
     61 */
     62static unsigned km_flush_deferred(void)
     63{
     64        unsigned i = 0;
     65        ipl_t ipl;
     66
     67        ipl = tlb_shootdown_start(TLB_INVL_ASID, ASID_KERNEL, 0, 0);
     68
     69        for (i = 0; i < deferred_pages; i++) {
     70                page_mapping_remove(AS_KERNEL, deferred_page[i]);
     71                km_page_free(deferred_page[i], PAGE_SIZE);
     72        }
     73
     74        tlb_invalidate_asid(ASID_KERNEL);
     75
     76        as_invalidate_translation_cache(AS_KERNEL, 0, -1);
     77        tlb_shootdown_finalize(ipl);
     78
     79        return i;
     80}
    4781
    4882/** Architecture dependent setup of identity-mapped kernel memory. */
     
    87121}
    88122
     123/** Unmap kernen non-identity page.
     124 *
     125 * @param[in] page      Non-identity page to be unmapped.
     126 */
     127static void km_unmap_deferred(uintptr_t page)
     128{
     129        page_table_lock(AS_KERNEL, true);
     130
     131        if (deferred_pages == DEFERRED_PAGES_MAX) {
     132                (void) km_flush_deferred();
     133                deferred_pages = 0;
     134        }
     135
     136        deferred_page[deferred_pages++] = page;
     137
     138        page_table_unlock(AS_KERNEL, true);
     139}
     140
     141/** Create a temporary page.
     142 *
     143 * The page is mapped read/write to a newly allocated frame of physical memory.
     144 * The page must be returned back to the system by a call to
     145 * km_temporary_page_put().
     146 *
     147 * @param[inout] framep Pointer to a variable which will receive the physical
     148 *                      address of the allocated frame.
     149 * @param[in] flags     Frame allocation flags. FRAME_NONE or FRAME_NO_RESERVE.
     150 * @return              Virtual address of the allocated frame.
     151 */
     152uintptr_t km_temporary_page_get(uintptr_t *framep, frame_flags_t flags)
     153{
     154        uintptr_t frame;
     155        uintptr_t page;
     156
     157        ASSERT(THREAD);
     158        ASSERT(framep);
     159        ASSERT(!(flags & ~FRAME_NO_RESERVE));
     160
     161        /*
     162         * Allocate a frame, preferably from high memory.
     163         */
     164        frame = (uintptr_t) frame_alloc(ONE_FRAME,
     165            FRAME_HIGHMEM | FRAME_ATOMIC | flags);
     166        if (frame) {
     167                page = km_page_alloc(PAGE_SIZE, PAGE_SIZE);
     168                ASSERT(page);   // FIXME
     169                page_table_lock(AS_KERNEL, true);
     170                page_mapping_insert(AS_KERNEL, page, frame,
     171                    PAGE_CACHEABLE | PAGE_READ | PAGE_WRITE);
     172                page_table_unlock(AS_KERNEL, true);
     173        } else {
     174                frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME,
     175                    FRAME_LOWMEM);
     176                page = PA2KA(frame);
     177        }
     178
     179        *framep = frame;
     180        return page;   
     181}
     182
     183/** Destroy a temporary page.
     184 *
     185 * This function destroys a temporary page previously created by
     186 * km_temporary_page_get(). The page destruction may be immediate or deferred.
     187 * The frame mapped by the destroyed page is not freed.
     188 *
     189 * @param[in] page      Temporary page to be destroyed.
     190 */
     191void km_temporary_page_put(uintptr_t page)
     192{
     193        ASSERT(THREAD);
     194
     195        if (km_is_non_identity(page))
     196                km_unmap_deferred(page);
     197}
    89198
    90199/** @}
  • kernel/generic/src/mm/page.c

    r321052f7 r3fe58d3c  
    202202        asize = ALIGN_UP(size, PAGE_SIZE);
    203203        align = ispwr2(size) ? size : (1U << (fnzb(size) + 1));
    204         virtaddr = km_page_alloc(asize, align);
     204        virtaddr = km_page_alloc(asize, max(PAGE_SIZE, align));
    205205
    206206        page_table_lock(AS_KERNEL, true);
Note: See TracChangeset for help on using the changeset viewer.