Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/km.c

    rc868e2d rf7f47a7  
    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/** @}
Note: See TracChangeset for help on using the changeset viewer.