Annotation of OSKit-Mach/oskit/osenv_mem.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999, 2000 University of Utah and the Flux Group.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This file is part of the Flux OSKit.  The OSKit is free software, also known
                      6:  * as "open source;" you can redistribute it and/or modify it under the terms
                      7:  * of the GNU General Public License (GPL), version 2, as published by the Free
                      8:  * Software Foundation (FSF).  To explore alternate licensing terms, contact
                      9:  * the University of Utah at [email protected] or +1-801-585-3271.
                     10:  *
                     11:  * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
                     12:  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
                     13:  * FOR A PARTICULAR PURPOSE.  See the GPL for more details.  You should have
                     14:  * received a copy of the GPL along with the OSKit; see the file COPYING.  If
                     15:  * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
                     16:  */
                     17: 
                     18: #include <oskit/com.h>
                     19: #include <oskit/com/mem.h>
                     20: #include <oskit/com/services.h>
                     21: #include <oskit/dev/dev.h>
                     22: #include <oskit/dev/osenv_mem.h>
                     23: 
                     24: #include <oskit/lmm.h>
                     25: #include <oskit/machine/base_vm.h>
                     26: #include <oskit/machine/physmem.h>
                     27: #include <oskit/machine/phys_lmm.h>
                     28: 
                     29: #include <string.h>
                     30: 
                     31: #include <cpus.h>
                     32: #include "lock.h"
                     33: #include "kalloc.h"
                     34: #include "zalloc.h"
                     35: #include "assert.h"
                     36: #include <machine/spl.h>
                     37: 
                     38: #include <vm/vm_kern.h>
                     39: 
                     40: #include "ds_oskit.h"
                     41: 
                     42: #define in_oskit_interrupt     (nested_pic_mask != 0)
                     43: extern unsigned int nested_pic_mask; /* osenv_irq.c */
                     44: 
                     45: decl_simple_lock_data(, phys_lmm_lock)
                     46: decl_simple_lock_data(extern, vm_page_queue_free_lock)
                     47: 
                     48: extern int vm_page_unqueued_count; /* vm_resident.c */
                     49: extern zone_t vm_page_zone;
                     50: extern vm_offset_t virtual_space_start;
                     51: extern vm_offset_t virtual_space_end;
                     52: 
                     53: int lmm_wants_pages;
                     54: 
                     55: #define debug_protect_page(p)  ((void)(p))
                     56: #define debug_unprotect_page(p)        ((void)(p))
                     57: 
                     58: 
                     59: /* Update the VM system's counts of free pages in the LMM.
                     60:    Called at sploskit with phys_lmm_lock held.  */
                     61: static void
                     62: update_counts (void)
                     63: {
                     64:   vm_page_unqueued_count = atop (lmm_avail (&malloc_lmm, 0));
                     65: }
                     66: 
                     67: 
                     68: void *
                     69: alloc_for_oskit (oskit_size_t size, osenv_memflags_t flags, unsigned align)
                     70: {
                     71:   kern_return_t kr;
                     72:   lmm_flags_t lmm_flags;
                     73: 
                     74:   assert (align <= size);
                     75: 
                     76:   if (flags & OSENV_AUTO_SIZE)
                     77:     {
                     78:       oskit_size_t *p;
                     79:       size += sizeof (oskit_size_t);
                     80:       if (align > sizeof (oskit_size_t))
                     81:        panic ("autosize + align %u", align);
                     82:        /* XXX how would I recover the beginning of the block in free?
                     83:        size += align - sizeof (oskit_size_t);
                     84:        */
                     85:       else
                     86:        align = sizeof (oskit_size_t);
                     87:       p = alloc_for_oskit (size, flags &~ OSENV_AUTO_SIZE, align);
                     88:       if (p == 0)
                     89:        return 0;
                     90:       p = (void *) (((oskit_addr_t) (p + 1) + align - 1) &~ (align - 1));
                     91:       p[-1] = size;
                     92:       return p;
                     93:     }
                     94: 
                     95:   lmm_flags = (((flags & OSENV_ISADMA_MEM) ? LMMF_16MB : 0)
                     96:               | ((flags & OSENV_X861MB_MEM) ? LMMF_1MB : 0));
                     97: 
                     98:   if (lmm_flags != 0)
                     99:     assert (flags & OSENV_VIRT_EQ_PHYS);
                    100: 
                    101:   if (mach_osenv == 0)
                    102:     /* This is early oskit startup code before the kernel is set up.
                    103:        Always go directly to physical memory.  */
                    104:     flags |= OSENV_VIRT_EQ_PHYS|OSENV_PHYS_WIRED|OSENV_PHYS_CONTIG;
                    105: 
                    106:   if (in_oskit_interrupt)
                    107:     /* The oskit documentation says an interrupt caller must set the flag.  */
                    108:     assert (flags & OSENV_NONBLOCKING);
                    109: 
                    110:   if (!(flags & (OSENV_NONBLOCKING|OSENV_PHYS_WIRED)))
                    111:     {
                    112:       /* Unwired virtual memory will do.  */
                    113: 
                    114:       if (size < PAGE_SIZE)
                    115:        /* For less than a page we don't want to waste partial pages,
                    116:           and we don't want to bother with a second-tier allocator
                    117:           for virtual memory, so just give him wired memory.  */
                    118:        return (void *) kalloc (size);
                    119:       else
                    120:        {
                    121:          vm_offset_t addr;
                    122:          kr = kmem_alloc_pageable (kernel_map, &addr, size);
                    123:          return kr ? 0 : (void *) addr;
                    124:        }
                    125:     }
                    126: 
                    127:   if (!(flags & (OSENV_VIRT_EQ_PHYS|OSENV_NONBLOCKING))
                    128:       && (!(flags & OSENV_PHYS_CONTIG) || size <= PAGE_SIZE))
                    129:     {
                    130:       /* Wired virtual memory will do.  */
                    131:       return (void *) kalloc (size);
                    132:     }
                    133: 
                    134:   /* We need physically contiguous memory.  This we get directly from the
                    135:      lmm, which might also be used by vm_page_grab.  All users of the lmm
                    136:      must go to sploskit or above and take the phys_lmm_lock.  This blocks
                    137:      out any interrupts that might go to the oskit (and get us here).  */
                    138:   while (1)
                    139:     {
                    140:       spl_t s;
                    141:       void *block;
                    142: 
                    143:       s = sploskit ();
                    144:       simple_lock (&phys_lmm_lock);
                    145: 
                    146:       if (align)
                    147:        block = lmm_alloc_aligned (&malloc_lmm, size, lmm_flags,
                    148:                                   ffs (align) - 1, 0);
                    149:       else
                    150:        block = lmm_alloc (&malloc_lmm, size, lmm_flags);
                    151: 
                    152:       update_counts ();
                    153: 
                    154:       simple_unlock (&phys_lmm_lock);
                    155:       splx (s);
                    156: 
                    157:       if (block)
                    158:        return block;
                    159: 
                    160:       if (flags & OSENV_NONBLOCKING)
                    161:        return 0;
                    162: 
                    163:       /* There is no space in the lmm.  There may well be pages available on
                    164:         the VM system's free list.  If we're sure we are not being called
                    165:         from an interrupt handler here, which we should be guaranteed by
                    166:         checking for OSENV_NONBLOCKING, then we can just access the free
                    167:         list directly here (vm_page_grab).  Another approach is to just wake
                    168:         up the pageout daemon to have it find some pages for the lmm and
                    169:         then block until it wakes us up.  lmm_wants_pages accumulates the
                    170:         number of pages wanted by blocked threads like ourselves.
                    171:         consider_lmm_collect will produce some memory, set lmm_want_pages to
                    172:         zero, and wake up all blocked threads to retry their allocations.  */
                    173:       lmm_wants_pages += atop (round_page (size));
                    174:       thread_wakeup_one ((event_t)&vm_page_queue_free_count);
                    175:       assert_wait ((event_t)&lmm_wants_pages, FALSE);
                    176:       thread_block (0);
                    177:       /* The pageout daemon woke us up (see consider_lmm_collect)
                    178:         after putting some memory back into the LMM for us.
                    179:         XXX make sure we don't loop in livelock? */
                    180:     }
                    181: }
                    182: 
                    183: 
                    184: void
                    185: free_for_oskit (void *block, osenv_memflags_t flags, oskit_size_t size)
                    186: {
                    187:   if (flags & OSENV_AUTO_SIZE)
                    188:     {
                    189:       oskit_size_t *p = block;
                    190:       size = *--p;
                    191:       block = p;
                    192:     }
                    193: 
                    194:   if (mach_osenv == 0)
                    195:     /* This is early oskit startup code before the kernel is set up.
                    196:        Always go directly to physical memory.  */
                    197:     flags |= OSENV_VIRT_EQ_PHYS|OSENV_PHYS_WIRED|OSENV_PHYS_CONTIG;
                    198: 
                    199: #if 0
                    200:   if (in_oskit_interrupt)
                    201:     /* The oskit documentation says an interrupt caller must set the flag.  */
                    202:     assert (flags & OSENV_NONBLOCKING);
                    203: #endif /* ... but oskit/linux/shared/s_kmem.c doesn't.  */
                    204: 
                    205:   if ((oskit_addr_t) block < phys_mem_max)
                    206:     {
                    207:       /* We got physical memory directly from the lmm.  */
                    208:       spl_t s;
                    209: 
                    210:       s = sploskit ();
                    211:       simple_lock (&phys_lmm_lock);
                    212: 
                    213:       lmm_free (&malloc_lmm, block, size);
                    214:       update_counts ();
                    215: 
                    216:       simple_unlock (&phys_lmm_lock);
                    217:       splx (s);
                    218:     }
                    219:   else
                    220:     {
                    221:       if (in_oskit_interrupt)
                    222:        {
                    223:          /* This should be impossible if the caller (oskit) is consistent
                    224:             in its use of OSENV_NONBLOCKING for allocations and
                    225:             deallocations.  alloc_for_oskit will always get physical
                    226:             memory when called with the flag set.  */
                    227:          panic ("free_for_oskit of virtual memory from interrupt level");
                    228:          /* If this ever happens, make a little free list and have the
                    229:             pageout daemon run over it doing kfree.  */
                    230:        }
                    231:       else
                    232:        kfree ((vm_offset_t) block, size);
                    233:     }
                    234: }
                    235: 
                    236: 
                    237: /*** Entry points from the VM system.  ***/
                    238: 
                    239: 
                    240: /* Called only from vm_page_bootstrap, only for estimate.  */
                    241: unsigned int pmap_free_pages()
                    242: {
                    243:        return atop (lmm_avail (&malloc_lmm, 0));
                    244: }
                    245: 
                    246: 
                    247: /* This is called from pmap_bootstrap for kernel page table pages, and from
                    248:    pmap_steal_memory for physical pages to back kernel virtual memory
                    249:    allocated in early Mach startup.  */
                    250: vm_offset_t
                    251: pmap_grab_page (void)
                    252: {
                    253:   void *page = lmm_alloc_page (&malloc_lmm, 0);
                    254:   if (page == 0)
                    255:     panic ("Not enough memory to initialize Mach");
                    256:   return (vm_offset_t) page;
                    257: }
                    258: 
                    259: int
                    260: init_alloc (vm_size_t size, vm_offset_t *p)
                    261: {
                    262:   void *block = lmm_alloc (&malloc_lmm, size, 0);
                    263:   if (block == 0)
                    264:     return 0;
                    265:   *p = (vm_offset_t) block;
                    266:   return 1;
                    267: }
                    268: 
                    269: 
                    270: /* in zalloc.c XXX */
                    271: extern vm_offset_t     zdata;
                    272: extern vm_size_t       zdata_size;
                    273: 
                    274: 
                    275: void pmap_startup(
                    276:        vm_offset_t *startp,
                    277:        vm_offset_t *endp)
                    278: {
                    279:        unsigned int i, npages, initial_pages;
                    280:        vm_page_t pages;
                    281: 
                    282:        /* Calculate how many pages can possibly go into the VM pool,
                    283:           taking into account the space required for each page's own
                    284:           vm_page_t structure.  */
                    285:        npages = ((lmm_avail (&malloc_lmm, 0) - round_page(zdata_size)) /
                    286:                  (PAGE_SIZE + sizeof *pages));
                    287: 
                    288:        /* We will allocate a quarter of the pages to start with.
                    289:           That ought to be plenty enough to get the kernel up and running.
                    290:           Once the pageout daemon has started, it will equalize the
                    291:           free page queue and LMM free pool sizes.  */
                    292:        initial_pages = npages / 4;
                    293: 
                    294:        /* Steal some memory for the zone system, including enough
                    295:           to cover the initial vm_page structures we will steal.  */
                    296:        zdata_size = (round_page (virtual_space_start + zdata_size +
                    297:                                 initial_pages * sizeof *pages)
                    298:                      - virtual_space_start);
                    299:        zdata = pmap_steal_memory (zdata_size);
                    300: 
                    301:        /* Steal vm_page structures from the zone system,
                    302:           and physical pages from the LMM.  */
                    303:        pages = (void *) zdata;
                    304:        for (i = 0; i < initial_pages; ++i)
                    305:          {
                    306:            vm_page_t mem = pages++;
                    307:            void *page = lmm_alloc_page (&malloc_lmm, 0);
                    308:            vm_page_init (mem, (vm_offset_t) page);
                    309:            debug_protect_page (page);
                    310:            vm_page_release (mem, FALSE);
                    311:          }
                    312: 
                    313:        /* Account for the memory swiped for vm_page structures,
                    314:           and return the rest of the stolen memory to the zone system.  */
                    315:        zdata_size = zdata + zdata_size - (vm_offset_t) pages;
                    316:        zdata = (vm_offset_t) pages;
                    317: 
                    318:        /* Set the initial record of the number of pages available in the
                    319:           LMM to a deliberate lie.  This value will be used to set paging
                    320:           algorithm parameters that should be based on what things look
                    321:           like with all available physical pages in the VM pool.  So here
                    322:           we use the calculation that takes into account the overhead of
                    323:           vm_page_t structures that we will have to consume to put pages
                    324:           into the pool.  Counting the free pages in the LMM will show
                    325:           more pages available than we admit, since we haven't allocated
                    326:           all of those structures up front.  As soon as the pageout daemon
                    327:           gets started up, it will recalculate from the LMM.  */
                    328:        vm_page_unqueued_count = npages - initial_pages;
                    329: 
                    330: 
                    331:        /*
                    332:         *      We have to re-align virtual_space_start,
                    333:         *      because pmap_steal_memory has been using it.
                    334:         */
                    335: 
                    336:        virtual_space_start = round_page(virtual_space_start);
                    337: 
                    338:        *startp = virtual_space_start;
                    339:        *endp = virtual_space_end;
                    340: }
                    341: 
                    342: 
                    343: void
                    344: vm_page_grab_oskit_page (void)
                    345: {
                    346:   void *page;
                    347:   vm_page_t m;
                    348: 
                    349:   do
                    350:     {
                    351:       spl_t s = sploskit ();
                    352:       simple_lock (&phys_lmm_lock);
                    353: 
                    354:       page = lmm_alloc_page (&malloc_lmm, 0);
                    355: 
                    356:       update_counts ();
                    357: 
                    358:       debug_protect_page (page);
                    359:       simple_unlock (&phys_lmm_lock);
                    360:       splx (s);
                    361: 
                    362:       if (page == 0)
                    363:        panic (__FUNCTION__);
                    364: 
                    365:       m = (vm_page_t) zget(vm_page_zone);
                    366:       if (m == VM_PAGE_NULL)
                    367:        {
                    368:          /* The zone is out of space.  A normal zalloc would call
                    369:             kmem_alloc_wired and wind up recursing down to here trying to
                    370:             get a page.  So instead we just stuff a physical page directly
                    371:             into the zone, and loop for a new one to satisfy our caller.  */
                    372:          debug_unprotect_page (page);
                    373:          zcram(vm_page_zone, (vm_offset_t) page, PAGE_SIZE);
                    374:        }
                    375:     } while (m == VM_PAGE_NULL);
                    376: 
                    377:   vm_page_init(m, (vm_offset_t) page);
                    378:   vm_page_release(m, FALSE);
                    379: }
                    380: 
                    381: 
                    382: #define PAGE_BATCH 32
                    383: 
                    384: /* Called by the pageout daemon to see if the vm_page_free_queue
                    385:    and the LMM want to tango.  */
                    386: 
                    387: void
                    388: consider_lmm_collect (void)
                    389: {
                    390:   spl_t s;
                    391:   unsigned int need;
                    392: 
                    393:   /* First check if the LMM needs pages back for alloc_for_oskit calls.  */
                    394:   if (vm_page_unqueued_count < lmm_wants_pages
                    395:       || vm_page_queue_free_count > 8 * vm_page_unqueued_count)        /* random */
                    396:     {
                    397:       /* The LMM needs some physical pages back from the VM pool.  */
                    398:       need = lmm_wants_pages > PAGE_BATCH ? lmm_wants_pages : PAGE_BATCH;
                    399: 
                    400:       while (need > 0)
                    401:        {
                    402:          unsigned int batch = need > PAGE_BATCH ? PAGE_BATCH : need;
                    403:          void *pages[PAGE_BATCH];
                    404:          unsigned int i;
                    405: 
                    406:          for (i = 0; i < batch; ++i)
                    407:            {
                    408:              vm_page_t mem = vm_page_grab (FALSE);
                    409:              if (mem == VM_PAGE_NULL)
                    410:                break;
                    411:              pages[i] = (void *) mem->phys_addr;
                    412:              zfree (vm_page_zone, (vm_offset_t) mem);
                    413:              debug_unprotect_page (pages[i]);
                    414:            }
                    415: 
                    416:          s = sploskit ();
                    417:          simple_lock (&phys_lmm_lock);
                    418: 
                    419:          while (i-- > 0)
                    420:            lmm_free_page (&malloc_lmm, (void *) pages[i]);
                    421: 
                    422:          update_counts ();
                    423: 
                    424:          simple_unlock (&phys_lmm_lock);
                    425:          splx (s);
                    426: 
                    427:          if (i < batch)
                    428:            break;
                    429:          need -= batch;
                    430:        }
                    431:     }
                    432: 
                    433:   /* If lmm_wants_pages is set, then some threads are blocked in
                    434:      alloc_for_oskit.  This might still be the case even if the memory was
                    435:      released to the LMM before we ran so that we didn't do anything above.
                    436:      We need to wake the blocked threads so they will all retry their
                    437:      allocations.  */
                    438:   if (lmm_wants_pages != 0)
                    439:     {
                    440:       lmm_wants_pages = 0;
                    441:       thread_wakeup ((event_t)&lmm_wants_pages);
                    442:     }
                    443: 
                    444:   /* Any time the VM pool has fewer free pages than the LMM does,
                    445:      we give it half the LMM's free pages.  */
                    446: 
                    447:   if (vm_page_queue_free_count < vm_page_unqueued_count)
                    448:     {
                    449:       s = sploskit ();
                    450:       simple_lock (&phys_lmm_lock);
                    451: 
                    452:       need = vm_page_unqueued_count / 2;
                    453: 
                    454:       /* We allocate only a single page at a time from the LMM, since we
                    455:         don't need contiguous pages, and would rather use up fragmented
                    456:         pages so as to leave the contiguous regions for those who need them.
                    457: 
                    458:         We must go to sploskit to call into the LMM, but back up to spl0 to
                    459:         deliver the new pages to the VM system.  We don't want to do this
                    460:         for every single page allocation from the LMM, so we allocate
                    461:         individual pages from the LMM in batches of PAGE_BATCH pages and
                    462:         then reenable interrupts to deliver those pages before going back
                    463:         for more.  */
                    464: 
                    465:       while (need > 0)
                    466:        {
                    467:          unsigned int batch = need > PAGE_BATCH ? PAGE_BATCH : need;
                    468:          void *pages[PAGE_BATCH];
                    469:          unsigned int i;
                    470: 
                    471:          for (i = 0; i < batch; ++i)
                    472:            {
                    473:              /* This allocation should never fail, since we keep track
                    474:                 of the number of pages available in the lmm.  */
                    475:              pages[i] = lmm_alloc_page (&malloc_lmm, 0);
                    476:              if (pages[i] == 0)
                    477:                panic ("LMM unexpectedly out of physical pages");
                    478:              debug_protect_page (pages[i]);
                    479:            }
                    480: 
                    481:          update_counts ();
                    482: 
                    483:          simple_unlock (&phys_lmm_lock);
                    484:          splx (s);
                    485: 
                    486:          while (i-- > 0)
                    487:            vm_page_create ((vm_offset_t) pages[i],
                    488:                            (vm_offset_t) pages[i] + PAGE_SIZE);
                    489: 
                    490:          need -= batch;
                    491:          if (need == 0)
                    492:            break;
                    493: 
                    494:          s = sploskit ();
                    495:          simple_lock (&phys_lmm_lock);
                    496:        }
                    497:     }
                    498: }
                    499: 
                    500: 
                    501: /*** oskit_osenv_mem_t COM object implementation ***/
                    502: 
                    503: 
                    504: /*
                    505:  * There is one and only one memory interface in this implementation.
                    506:  */
                    507: static struct oskit_osenv_mem_ops      osenv_mem_ops;
                    508: static struct oskit_osenv_mem          osenv_mem_object = {&osenv_mem_ops};
                    509: 
                    510: static OSKIT_COMDECL
                    511: mem_query(oskit_osenv_mem_t *s, const oskit_iid_t *iid, void **out_ihandle)
                    512: {
                    513:         if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 ||
                    514:             memcmp(iid, &oskit_osenv_mem_iid, sizeof(*iid)) == 0) {
                    515:                 *out_ihandle = s;
                    516:                 return 0;
                    517:         }
                    518: 
                    519:         *out_ihandle = 0;
                    520:         return OSKIT_E_NOINTERFACE;
                    521: };
                    522: 
                    523: static OSKIT_COMDECL_U
                    524: mem_addref(oskit_osenv_mem_t *s)
                    525: {
                    526:        /* Only one object */
                    527:        return 1;
                    528: }
                    529: 
                    530: static OSKIT_COMDECL_U
                    531: mem_release(oskit_osenv_mem_t *s)
                    532: {
                    533:        /* Only one object */
                    534:        return 1;
                    535: }
                    536: 
                    537: static void * OSKIT_COMCALL
                    538: mem_alloc(oskit_osenv_mem_t *o, oskit_size_t size,
                    539:          osenv_memflags_t flags, unsigned align)
                    540: {
                    541:   return alloc_for_oskit (size, flags, align);
                    542: }
                    543: 
                    544: static OSKIT_COMDECL_V
                    545: mem_free(oskit_osenv_mem_t *o, void *block,
                    546:         osenv_memflags_t flags, oskit_size_t size)
                    547: {
                    548:   free_for_oskit (block, flags, size);
                    549: }
                    550: 
                    551: static oskit_addr_t OSKIT_COMCALL
                    552: mem_getphys(oskit_osenv_mem_t *o, oskit_addr_t va)
                    553: {
                    554:   /* We can only use kvtophys for memory allocated with OSENV_PHYS_CONTIG.
                    555:      But at least some code (e.g. eepro100 driver) will call us with an
                    556:      address on a kernel stack and expect to get a physical address from that.
                    557:      Checking the kernel pmap is a little heavy but should be correct in
                    558:      all cases.  */
                    559:   return pmap_extract (kernel_pmap, va);
                    560: }
                    561: 
                    562: static oskit_addr_t OSKIT_COMCALL
                    563: mem_getvirt(oskit_osenv_mem_t *o, oskit_addr_t pa)
                    564: {
                    565:        return ((oskit_addr_t)phystokv(pa));
                    566: }
                    567: 
                    568: static oskit_addr_t OSKIT_COMCALL
                    569: mem_physmax(oskit_osenv_mem_t *o)
                    570: {
                    571:        return phys_mem_max;
                    572: }
                    573: 
                    574: static OSKIT_COMDECL_U
                    575: mem_mapphys(oskit_osenv_mem_t *o, oskit_addr_t pa,
                    576:            oskit_size_t size, void **addr, int flags)
                    577: {
                    578:   kern_return_t kr;
                    579:   vm_offset_t kva;
                    580: 
                    581:   if (trunc_page (pa) != 0 &&
                    582:       trunc_page (pa) >= trunc_page (phys_mem_min) &&
                    583:       round_page (pa + size) < round_page (phys_mem_max))
                    584:     {
                    585:       /* Direct mapping already covers it.  */
                    586:       *addr = (void *) phystokv (pa);
                    587:       return 0;
                    588:     }
                    589: 
                    590:   kr = kmem_alloc_pageable (kernel_map, &kva, round_page (size));
                    591:   if (kr)
                    592:     return OSKIT_E_OUTOFMEMORY;
                    593: 
                    594:   pmap_map (kva, trunc_page (pa), round_page (pa + size),
                    595:            VM_PROT_READ | VM_PROT_WRITE);
                    596: 
                    597:   *addr = (char *) kva + (pa & PAGE_MASK);
                    598:   return 0;
                    599: }
                    600: 
                    601: #if NCPUS > 1
                    602: /* This function is used as a callback from smp_init_paging.  */
                    603: oskit_addr_t
                    604: smp_map_range (oskit_addr_t start, oskit_size_t size)
                    605: {
                    606:   oskit_error_t err = mem_mapphys (0, start, size, (void **)&start, 0);
                    607:   return err ? 0 : start;
                    608: }
                    609: #endif
                    610: 
                    611: 
                    612: static struct oskit_osenv_mem_ops osenv_mem_ops = {
                    613:        mem_query,
                    614:        mem_addref,
                    615:        mem_release,
                    616:        mem_alloc,
                    617:        mem_free,
                    618:        mem_getphys,
                    619:        mem_getvirt,
                    620:        mem_physmax,
                    621:        mem_mapphys,
                    622: };
                    623: 
                    624: /*
                    625:  * Return a reference to the one and only memory interface object.
                    626:  */
                    627: oskit_osenv_mem_t *
                    628: oskit_create_osenv_mem(void)
                    629: {
                    630:        return &osenv_mem_object;
                    631: }
                    632: 
                    633: 
                    634: /*** oskit_mem_t COM object implementation ***/
                    635: 
                    636: 
                    637: /* the COM object */
                    638: static struct oskit_mem_ops mem_ops;
                    639: static oskit_mem_t     oskit_mem  = { &mem_ops };
                    640: 
                    641: 
                    642: static OSKIT_COMDECL
                    643: mem2_query(oskit_mem_t *m, const oskit_iid_t *iid, void **out_ihandle)
                    644: {
                    645:         if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 ||
                    646:             memcmp(iid, &oskit_mem_iid, sizeof(*iid)) == 0) {
                    647:                 *out_ihandle = m;
                    648:                 return 0;
                    649:         }
                    650: 
                    651:         *out_ihandle = 0;
                    652:         return OSKIT_E_NOINTERFACE;
                    653: };
                    654: 
                    655: static OSKIT_COMDECL_U
                    656: mem2_addref(oskit_mem_t *m)
                    657: {
                    658:        /* No reference counting; only one of them */
                    659:        return 1;
                    660: }
                    661: 
                    662: static OSKIT_COMDECL_U
                    663: mem2_release(oskit_mem_t *m)
                    664: {
                    665:        /* No reference counting; only one of them */
                    666:        return 1;
                    667: }
                    668: 
                    669: static void * OSKIT_COMCALL
                    670: mem2_alloc(oskit_mem_t *m, oskit_u32_t size, oskit_u32_t flags)
                    671: {
                    672:   return alloc_for_oskit (size, flags, 0);
                    673: }
                    674: 
                    675: static void * OSKIT_COMCALL
                    676: mem2_realloc(oskit_mem_t *m, void *ptr,
                    677:            oskit_u32_t oldsize, oskit_u32_t newsize, oskit_u32_t flags)
                    678: {
                    679:   if (flags & OSKIT_MEM_AUTO_SIZE)
                    680:     {
                    681:       oskit_size_t *op = ptr, *new;
                    682:       oldsize = *--op;
                    683:       newsize += sizeof (oskit_size_t);
                    684:       new = alloc_for_oskit (newsize, flags, 0);
                    685:       if (new)
                    686:        {
                    687:          *new++ = newsize;
                    688:          memcpy (new, ptr, oldsize - sizeof (oskit_size_t));
                    689:          free_for_oskit (op, flags, oldsize);
                    690:        }
                    691:       return new;
                    692:     }
                    693:   else
                    694:     {
                    695:       void *new = alloc_for_oskit (newsize, flags, 0);
                    696:       if (new)
                    697:        {
                    698:          memcpy (new, ptr, oldsize);
                    699:          free_for_oskit (ptr, flags, oldsize);
                    700:        }
                    701:       return new;
                    702:     }
                    703: }
                    704: 
                    705: static void *OSKIT_COMCALL
                    706: mem2_alloc_aligned(oskit_mem_t *m,
                    707:                  oskit_u32_t size, oskit_u32_t flags, oskit_u32_t align)
                    708: {
                    709:   return alloc_for_oskit (size, flags, align);
                    710: }
                    711: 
                    712: static void OSKIT_COMCALL
                    713: mem2_free(oskit_mem_t *m, void *ptr, oskit_u32_t size, oskit_u32_t flags)
                    714: {
                    715:   if (ptr)
                    716:     free_for_oskit (ptr, flags, size);
                    717: }
                    718: 
                    719: static oskit_u32_t OSKIT_COMCALL
                    720: mem2_getsize(oskit_mem_t *m, void *ptr)
                    721: {
                    722:        if (ptr) {
                    723:                oskit_u32_t *chunk = (oskit_u32_t *)ptr - 1;
                    724: 
                    725:                return *chunk;
                    726:        }
                    727:        return 0;
                    728: }
                    729: 
                    730: static void *OSKIT_COMCALL
                    731: mem2_alloc_gen(oskit_mem_t *m,
                    732:              oskit_u32_t size, oskit_u32_t flags,
                    733:              oskit_u32_t align_bits, oskit_u32_t align_ofs)
                    734: {
                    735:   if (align_ofs != 0)
                    736:     panic ("alloc with align_bits=%u align_ofs=%u",
                    737:           align_bits, align_ofs);
                    738:   return alloc_for_oskit (size, flags, 1 << align_bits);
                    739: }
                    740: 
                    741: static oskit_size_t OSKIT_COMCALL
                    742: mem2_avail(oskit_mem_t *m, oskit_u32_t flags)
                    743: {
                    744:   panic ("mem_avail");
                    745: }
                    746: 
                    747: static OSKIT_COMDECL_V
                    748: mem2_dump(oskit_mem_t *m)
                    749: {
                    750:   panic ("mem_dump");
                    751: }
                    752: 
                    753: static struct oskit_mem_ops mem_ops = {
                    754:        mem2_query,
                    755:        mem2_addref,
                    756:        mem2_release,
                    757:        mem2_alloc,
                    758:        mem2_realloc,
                    759:        mem2_alloc_aligned,
                    760:        mem2_free,
                    761:        mem2_getsize,
                    762:        mem2_alloc_gen,
                    763:        mem2_avail,
                    764:        mem2_dump,
                    765: };
                    766: 
                    767: /*
                    768:  * Not a lot to do in this impl.
                    769:  */
                    770: oskit_mem_t *
                    771: oskit_mem_init(void)
                    772: {
                    773:        return &oskit_mem;
                    774: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.