The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/osfmk/i386/commpage/commpage.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2003-2008 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 
   29 /*
   30  *      Here's what to do if you want to add a new routine to the comm page:
   31  *
   32  *              1. Add a definition for it's address in osfmk/i386/cpu_capabilities.h,
   33  *                 being careful to reserve room for future expansion.
   34  *
   35  *              2. Write one or more versions of the routine, each with it's own
   36  *                 commpage_descriptor.  The tricky part is getting the "special",
   37  *                 "musthave", and "canthave" fields right, so that exactly one
   38  *                 version of the routine is selected for every machine.
   39  *                 The source files should be in osfmk/i386/commpage/.
   40  *
   41  *              3. Add a ptr to your new commpage_descriptor(s) in the "routines"
   42  *                 array in osfmk/i386/commpage/commpage_asm.s.  There are two
   43  *                 arrays, one for the 32-bit and one for the 64-bit commpage.
   44  *
   45  *              4. Write the code in Libc to use the new routine.
   46  */
   47 
   48 #include <mach/mach_types.h>
   49 #include <mach/machine.h>
   50 #include <mach/vm_map.h>
   51 #include <mach/mach_vm.h>
   52 #include <i386/tsc.h>
   53 #include <i386/rtclock.h>
   54 #include <i386/cpu_data.h>
   55 #include <i386/machine_routines.h>
   56 #include <i386/misc_protos.h>
   57 #include <machine/cpu_capabilities.h>
   58 #include <machine/commpage.h>
   59 #include <machine/pmap.h>
   60 #include <vm/vm_kern.h>
   61 #include <vm/vm_map.h>
   62 
   63 #include <ipc/ipc_port.h>
   64 
   65 #include <kern/page_decrypt.h>
   66 
   67 /* the lists of commpage routines are in commpage_asm.s  */
   68 extern  commpage_descriptor*    commpage_32_routines[];
   69 extern  commpage_descriptor*    commpage_64_routines[];
   70 
   71 /* translated commpage descriptors from commpage_sigs.c  */
   72 extern  commpage_descriptor sigdata_descriptor;
   73 extern  commpage_descriptor *ba_descriptors[];
   74 
   75 extern vm_map_t commpage32_map; // the shared submap, set up in vm init
   76 extern vm_map_t commpage64_map; // the shared submap, set up in vm init
   77 
   78 char    *commPagePtr32 = NULL;          // virtual addr in kernel map of 32-bit commpage
   79 char    *commPagePtr64 = NULL;          // ...and of 64-bit commpage
   80 int     _cpu_capabilities = 0;          // define the capability vector
   81 
   82 int     noVMX = 0;              /* if true, do not set kHasAltivec in ppc _cpu_capabilities */
   83 
   84 typedef uint32_t commpage_address_t;
   85 
   86 static commpage_address_t       next;                   // next available address in comm page
   87 static commpage_address_t       cur_routine;            // comm page address of "current" routine
   88 static boolean_t                matched;                // true if we've found a match for "current" routine
   89 
   90 static char    *commPagePtr;            // virtual addr in kernel map of commpage we are working on
   91 static commpage_address_t       commPageBaseOffset; // subtract from 32-bit runtime address to get offset in virtual commpage in kernel map
   92 
   93 static  commpage_time_data      *time_data32 = NULL;
   94 static  commpage_time_data      *time_data64 = NULL;
   95 
   96 /* Allocate the commpage and add to the shared submap created by vm:
   97  *      1. allocate a page in the kernel map (RW)
   98  *      2. wire it down
   99  *      3. make a memory entry out of it
  100  *      4. map that entry into the shared comm region map (R-only)
  101  */
  102 
  103 static  void*
  104 commpage_allocate( 
  105         vm_map_t        submap,                 // commpage32_map or commpage_map64
  106         size_t          area_used )             // _COMM_PAGE32_AREA_USED or _COMM_PAGE64_AREA_USED
  107 {
  108         vm_offset_t     kernel_addr = 0;        // address of commpage in kernel map
  109         vm_offset_t     zero = 0;
  110         vm_size_t       size = area_used;       // size actually populated
  111         vm_map_entry_t  entry;
  112         ipc_port_t      handle;
  113 
  114         if (submap == NULL)
  115                 panic("commpage submap is null");
  116 
  117         if (vm_map(kernel_map,&kernel_addr,area_used,0,VM_FLAGS_ANYWHERE,NULL,0,FALSE,VM_PROT_ALL,VM_PROT_ALL,VM_INHERIT_NONE))
  118                 panic("cannot allocate commpage");
  119 
  120         if (vm_map_wire(kernel_map,kernel_addr,kernel_addr+area_used,VM_PROT_DEFAULT,FALSE))
  121                 panic("cannot wire commpage");
  122 
  123         /* 
  124          * Now that the object is created and wired into the kernel map, mark it so that no delay
  125          * copy-on-write will ever be performed on it as a result of mapping it into user-space.
  126          * If such a delayed copy ever occurred, we could remove the kernel's wired mapping - and
  127          * that would be a real disaster.
  128          *
  129          * JMM - What we really need is a way to create it like this in the first place.
  130          */
  131         if (!vm_map_lookup_entry( kernel_map, vm_map_trunc_page(kernel_addr), &entry) || entry->is_sub_map)
  132                 panic("cannot find commpage entry");
  133         entry->object.vm_object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
  134 
  135         if (mach_make_memory_entry( kernel_map,         // target map
  136                                     &size,              // size 
  137                                     kernel_addr,        // offset (address in kernel map)
  138                                     VM_PROT_ALL,        // map it RWX
  139                                     &handle,            // this is the object handle we get
  140                                     NULL ))             // parent_entry (what is this?)
  141                 panic("cannot make entry for commpage");
  142 
  143         if (vm_map_64(  submap,                         // target map (shared submap)
  144                         &zero,                          // address (map into 1st page in submap)
  145                         area_used,                      // size
  146                         0,                              // mask
  147                         VM_FLAGS_FIXED,                 // flags (it must be 1st page in submap)
  148                         handle,                         // port is the memory entry we just made
  149                         0,                              // offset (map 1st page in memory entry)
  150                         FALSE,                          // copy
  151                         VM_PROT_READ|VM_PROT_EXECUTE,   // cur_protection (R-only in user map)
  152                         VM_PROT_READ|VM_PROT_EXECUTE,   // max_protection
  153                         VM_INHERIT_SHARE ))             // inheritance
  154                 panic("cannot map commpage");
  155 
  156         ipc_port_release(handle);
  157 
  158         return (void*)(intptr_t)kernel_addr;                     // return address in kernel map
  159 }
  160 
  161 /* Get address (in kernel map) of a commpage field. */
  162 
  163 static void*
  164 commpage_addr_of(
  165     commpage_address_t     addr_at_runtime )
  166 {
  167         return  (void*) ((uintptr_t)commPagePtr + (addr_at_runtime - commPageBaseOffset));
  168 }
  169 
  170 /* Determine number of CPUs on this system.  We cannot rely on
  171  * machine_info.max_cpus this early in the boot.
  172  */
  173 static int
  174 commpage_cpus( void )
  175 {
  176         int cpus;
  177 
  178         cpus = ml_get_max_cpus();                   // NB: this call can block
  179 
  180         if (cpus == 0)
  181                 panic("commpage cpus==0");
  182         if (cpus > 0xFF)
  183                 cpus = 0xFF;
  184 
  185         return cpus;
  186 }
  187 
  188 /* Initialize kernel version of _cpu_capabilities vector (used by KEXTs.) */
  189 
  190 static void
  191 commpage_init_cpu_capabilities( void )
  192 {
  193         int bits;
  194         int cpus;
  195         ml_cpu_info_t cpu_info;
  196 
  197         bits = 0;
  198         ml_cpu_get_info(&cpu_info);
  199         
  200         switch (cpu_info.vector_unit) {
  201                 case 8:
  202                         bits |= kHasSSE4_2;
  203                         /* fall thru */
  204                 case 7:
  205                         bits |= kHasSSE4_1;
  206                         /* fall thru */
  207                 case 6:
  208                         bits |= kHasSupplementalSSE3;
  209                         /* fall thru */
  210                 case 5:
  211                         bits |= kHasSSE3;
  212                         /* fall thru */
  213                 case 4:
  214                         bits |= kHasSSE2;
  215                         /* fall thru */
  216                 case 3:
  217                         bits |= kHasSSE;
  218                         /* fall thru */
  219                 case 2:
  220                         bits |= kHasMMX;
  221                 default:
  222                         break;
  223         }
  224         switch (cpu_info.cache_line_size) {
  225                 case 128:
  226                         bits |= kCache128;
  227                         break;
  228                 case 64:
  229                         bits |= kCache64;
  230                         break;
  231                 case 32:
  232                         bits |= kCache32;
  233                         break;
  234                 default:
  235                         break;
  236         }
  237         cpus = commpage_cpus();                 // how many CPUs do we have
  238 
  239         if (cpus == 1)
  240                 bits |= kUP;
  241 
  242         bits |= (cpus << kNumCPUsShift);
  243 
  244         bits |= kFastThreadLocalStorage;        // we use %gs for TLS
  245 
  246         if (cpu_mode_is64bit())                 // k64Bit means processor is 64-bit capable
  247                 bits |= k64Bit;
  248 
  249         if (tscFreq <= SLOW_TSC_THRESHOLD)      /* is TSC too slow for _commpage_nanotime?  */
  250                 bits |= kSlow;
  251 
  252         _cpu_capabilities = bits;               // set kernel version for use by drivers etc
  253 }
  254 
  255 int
  256 _get_cpu_capabilities(void)
  257 {
  258         return _cpu_capabilities;
  259 }
  260 
  261 /* Copy data into commpage. */
  262 
  263 static void
  264 commpage_stuff(
  265     commpage_address_t  address,
  266     const void  *source,
  267     int         length  )
  268 {    
  269     void        *dest = commpage_addr_of(address);
  270     
  271     if (address < next)
  272         panic("commpage overlap at address 0x%p, 0x%x < 0x%x", dest, address, next);
  273     
  274     bcopy(source,dest,length);
  275     
  276     next = address + length;
  277 }
  278 
  279 static void
  280 commpage_stuff_swap(
  281         commpage_address_t      address,
  282         void    *source,
  283         int     length,
  284         int     legacy )
  285 {
  286         if ( legacy ) {
  287                 void *dest = commpage_addr_of(address);
  288                 dest = (void *)((uintptr_t) dest + _COMM_PAGE_SIGS_OFFSET);
  289                 switch (length) {
  290                         case 2:
  291                                 OSWriteSwapInt16(dest, 0, *(uint16_t *)source);
  292                                 break;
  293                         case 4:
  294                                 OSWriteSwapInt32(dest, 0, *(uint32_t *)source);
  295                                 break;
  296                         case 8:
  297                                 OSWriteSwapInt64(dest, 0, *(uint64_t *)source);
  298                                 break;
  299                 }
  300         }
  301 }
  302 
  303 static void
  304 commpage_stuff2(
  305         commpage_address_t      address,
  306         void    *source,
  307         int     length,
  308         int     legacy )
  309 {
  310         commpage_stuff_swap(address, source, length, legacy);
  311         commpage_stuff(address, source, length);
  312 }
  313 
  314 /* Copy a routine into comm page if it matches running machine.
  315  */
  316 static void
  317 commpage_stuff_routine(
  318     commpage_descriptor *rd     )
  319 {
  320     uint32_t            must,cant;
  321     
  322     if (rd->commpage_address != cur_routine) {
  323         if ((cur_routine!=0) && (matched==0))
  324             panic("commpage no match for last, next address %08x", rd->commpage_address);
  325         cur_routine = rd->commpage_address;
  326         matched = 0;
  327     }
  328     
  329     must = _cpu_capabilities & rd->musthave;
  330     cant = _cpu_capabilities & rd->canthave;
  331     
  332     if ((must == rd->musthave) && (cant == 0)) {
  333         if (matched)
  334             panic("commpage multiple matches for address %08x", rd->commpage_address);
  335         matched = 1;
  336         
  337         commpage_stuff(rd->commpage_address,rd->code_address,rd->code_length);
  338         }
  339 }
  340 
  341 /* Fill in the 32- or 64-bit commpage.  Called once for each.
  342  * The 32-bit ("legacy") commpage has a bunch of stuff added to it
  343  * for translated processes, some of which is byte-swapped.
  344  */
  345 
  346 static void
  347 commpage_populate_one( 
  348         vm_map_t        submap,         // commpage32_map or compage64_map
  349         char **         kernAddressPtr, // &commPagePtr32 or &commPagePtr64
  350         size_t          area_used,      // _COMM_PAGE32_AREA_USED or _COMM_PAGE64_AREA_USED
  351         commpage_address_t base_offset, // will become commPageBaseOffset
  352         commpage_descriptor** commpage_routines, // list of routine ptrs for this commpage
  353         boolean_t       legacy,         // true if 32-bit commpage
  354         commpage_time_data** time_data, // &time_data32 or &time_data64
  355         const char*     signature )     // "commpage 32-bit" or "commpage 64-bit"
  356 {
  357         short   c2;
  358         int     c4;
  359         static double   two52 = 1048576.0 * 1048576.0 * 4096.0; // 2**52
  360         static double   ten6 = 1000000.0;                       // 10**6
  361         commpage_descriptor **rd;
  362         short   version = _COMM_PAGE_THIS_VERSION;
  363         int             swapcaps;
  364 
  365         next = 0;
  366         cur_routine = 0;
  367         commPagePtr = (char *)commpage_allocate( submap, (vm_size_t) area_used );
  368         *kernAddressPtr = commPagePtr;                          // save address either in commPagePtr32 or 64
  369         commPageBaseOffset = base_offset;
  370 
  371         *time_data = commpage_addr_of( _COMM_PAGE_TIME_DATA_START );
  372 
  373         /* Stuff in the constants.  We move things into the comm page in strictly
  374         * ascending order, so we can check for overlap and panic if so.
  375         */
  376         commpage_stuff(_COMM_PAGE_SIGNATURE,signature,(int)strlen(signature));
  377         commpage_stuff2(_COMM_PAGE_VERSION,&version,sizeof(short),legacy);
  378         commpage_stuff(_COMM_PAGE_CPU_CAPABILITIES,&_cpu_capabilities,sizeof(int));
  379 
  380         /* excuse our magic constants, we cannot include ppc/cpu_capabilities.h */
  381         /* always set kCache32 and kDcbaAvailable */
  382         swapcaps =  0x44;
  383         if ( _cpu_capabilities & kUP )
  384                 swapcaps |= (kUP + (1 << kNumCPUsShift));
  385         else
  386                 swapcaps |= 2 << kNumCPUsShift; /* limit #cpus to 2 */
  387         if ( ! noVMX )          /* if rosetta will be emulating altivec... */
  388                 swapcaps |= 0x101;      /* ...then set kHasAltivec and kDataStreamsAvailable too */
  389         commpage_stuff_swap(_COMM_PAGE_CPU_CAPABILITIES, &swapcaps, sizeof(int), legacy);
  390         c2 = 32;
  391         commpage_stuff_swap(_COMM_PAGE_CACHE_LINESIZE,&c2,2,legacy);
  392 
  393         if (_cpu_capabilities & kCache32)
  394                 c2 = 32;
  395         else if (_cpu_capabilities & kCache64)
  396                 c2 = 64;
  397         else if (_cpu_capabilities & kCache128)
  398                 c2 = 128;
  399         commpage_stuff(_COMM_PAGE_CACHE_LINESIZE,&c2,2);
  400         
  401         c4 = MP_SPIN_TRIES;
  402         commpage_stuff(_COMM_PAGE_SPIN_COUNT,&c4,4);
  403 
  404         if ( legacy ) {
  405                 commpage_stuff2(_COMM_PAGE_2_TO_52,&two52,8,legacy);
  406                 commpage_stuff2(_COMM_PAGE_10_TO_6,&ten6,8,legacy);
  407         }
  408 
  409         for( rd = commpage_routines; *rd != NULL ; rd++ )
  410                 commpage_stuff_routine(*rd);
  411 
  412         if (!matched)
  413                 panic("commpage no match on last routine");
  414 
  415         if (next > _COMM_PAGE_END)
  416                 panic("commpage overflow: next = 0x%08x, commPagePtr = 0x%p", next, commPagePtr);
  417 
  418         if ( legacy ) {
  419                 next = 0;
  420                 for( rd = ba_descriptors; *rd != NULL ; rd++ )
  421                         commpage_stuff_routine(*rd);
  422 
  423                 next = 0;
  424                 commpage_stuff_routine(&sigdata_descriptor);
  425         }       
  426 }
  427 
  428 
  429 /* Fill in commpages: called once, during kernel initialization, from the
  430  * startup thread before user-mode code is running.
  431  *
  432  * See the top of this file for a list of what you have to do to add
  433  * a new routine to the commpage.
  434  */  
  435 
  436 void
  437 commpage_populate( void )
  438 {
  439         commpage_init_cpu_capabilities();
  440         
  441         commpage_populate_one(  commpage32_map, 
  442                                 &commPagePtr32,
  443                                 _COMM_PAGE32_AREA_USED,
  444                                 _COMM_PAGE32_BASE_ADDRESS,
  445                                 commpage_32_routines, 
  446                                 TRUE,                   /* legacy (32-bit) commpage */
  447                                 &time_data32,
  448                                 "commpage 32-bit");
  449 #ifndef __LP64__
  450         pmap_commpage32_init((vm_offset_t) commPagePtr32, _COMM_PAGE32_BASE_ADDRESS, 
  451                            _COMM_PAGE32_AREA_USED/INTEL_PGBYTES);
  452 #endif                     
  453         time_data64 = time_data32;                      /* if no 64-bit commpage, point to 32-bit */
  454 
  455         if (_cpu_capabilities & k64Bit) {
  456                 commpage_populate_one(  commpage64_map, 
  457                                         &commPagePtr64,
  458                                         _COMM_PAGE64_AREA_USED,
  459                                         _COMM_PAGE32_START_ADDRESS, /* commpage address are relative to 32-bit commpage placement */
  460                                         commpage_64_routines, 
  461                                         FALSE,          /* not a legacy commpage */
  462                                         &time_data64,
  463                                         "commpage 64-bit");
  464 #ifndef __LP64__
  465                 pmap_commpage64_init((vm_offset_t) commPagePtr64, _COMM_PAGE64_BASE_ADDRESS, 
  466                                    _COMM_PAGE64_AREA_USED/INTEL_PGBYTES);
  467 #endif
  468         }
  469 
  470         rtc_nanotime_init_commpage();
  471 }
  472 
  473 
  474 /* Update commpage nanotime information.  Note that we interleave
  475  * setting the 32- and 64-bit commpages, in order to keep nanotime more
  476  * nearly in sync between the two environments.
  477  *
  478  * This routine must be serialized by some external means, ie a lock.
  479  */
  480 
  481 void
  482 commpage_set_nanotime(
  483         uint64_t        tsc_base,
  484         uint64_t        ns_base,
  485         uint32_t        scale,
  486         uint32_t        shift )
  487 {
  488         commpage_time_data      *p32 = time_data32;
  489         commpage_time_data      *p64 = time_data64;
  490         static uint32_t generation = 0;
  491         uint32_t        next_gen;
  492         
  493         if (p32 == NULL)                /* have commpages been allocated yet? */
  494                 return;
  495                 
  496         if ( generation != p32->nt_generation )
  497                 panic("nanotime trouble 1");    /* possibly not serialized */
  498         if ( ns_base < p32->nt_ns_base )
  499                 panic("nanotime trouble 2");
  500         if ((shift != 32) && ((_cpu_capabilities & kSlow)==0) )
  501                 panic("nanotime trouble 3");
  502                 
  503         next_gen = ++generation;
  504         if (next_gen == 0)
  505                 next_gen = ++generation;
  506         
  507         p32->nt_generation = 0;         /* mark invalid, so commpage won't try to use it */
  508         p64->nt_generation = 0;
  509         
  510         p32->nt_tsc_base = tsc_base;
  511         p64->nt_tsc_base = tsc_base;
  512         
  513         p32->nt_ns_base = ns_base;
  514         p64->nt_ns_base = ns_base;
  515         
  516         p32->nt_scale = scale;
  517         p64->nt_scale = scale;
  518         
  519         p32->nt_shift = shift;
  520         p64->nt_shift = shift;
  521         
  522         p32->nt_generation = next_gen;  /* mark data as valid */
  523         p64->nt_generation = next_gen;
  524 }
  525 
  526 
  527 /* Disable commpage gettimeofday(), forcing commpage to call through to the kernel.  */
  528 
  529 void
  530 commpage_disable_timestamp( void )
  531 {
  532         time_data32->gtod_generation = 0;
  533         time_data64->gtod_generation = 0;
  534 }
  535 
  536 
  537 /* Update commpage gettimeofday() information.  As with nanotime(), we interleave
  538  * updates to the 32- and 64-bit commpage, in order to keep time more nearly in sync 
  539  * between the two environments.
  540  *
  541  * This routine must be serializeed by some external means, ie a lock.
  542  */
  543  
  544  void
  545  commpage_set_timestamp(
  546         uint64_t        abstime,
  547         uint64_t        secs )
  548 {
  549         commpage_time_data      *p32 = time_data32;
  550         commpage_time_data      *p64 = time_data64;
  551         static uint32_t generation = 0;
  552         uint32_t        next_gen;
  553         
  554         next_gen = ++generation;
  555         if (next_gen == 0)
  556                 next_gen = ++generation;
  557         
  558         p32->gtod_generation = 0;               /* mark invalid, so commpage won't try to use it */
  559         p64->gtod_generation = 0;
  560         
  561         p32->gtod_ns_base = abstime;
  562         p64->gtod_ns_base = abstime;
  563         
  564         p32->gtod_sec_base = secs;
  565         p64->gtod_sec_base = secs;
  566         
  567         p32->gtod_generation = next_gen;        /* mark data as valid */
  568         p64->gtod_generation = next_gen;
  569 }
  570 
  571 
  572 /* Update _COMM_PAGE_MEMORY_PRESSURE.  Called periodically from vm's compute_memory_pressure()  */
  573 
  574 void
  575 commpage_set_memory_pressure(
  576         unsigned int    pressure )
  577 {
  578         char        *cp;
  579         uint32_t    *ip;
  580         
  581         cp = commPagePtr32;
  582         if ( cp ) {
  583                 cp += (_COMM_PAGE_MEMORY_PRESSURE - _COMM_PAGE32_BASE_ADDRESS);
  584                 ip = (uint32_t*) cp;
  585                 *ip = (uint32_t) pressure;
  586         }
  587         
  588         cp = commPagePtr64;
  589         if ( cp ) {
  590                 cp += (_COMM_PAGE_MEMORY_PRESSURE - _COMM_PAGE32_START_ADDRESS);
  591                 ip = (uint32_t*) cp;
  592                 *ip = (uint32_t) pressure;
  593         }
  594 
  595 }
  596 
  597 
  598 /* Update _COMM_PAGE_SPIN_COUNT.  We might want to reduce when running on a battery, etc. */
  599 
  600 void
  601 commpage_set_spin_count(
  602         unsigned int    count )
  603 {
  604         char        *cp;
  605         uint32_t    *ip;
  606         
  607         if (count == 0)     /* we test for 0 after decrement, not before */
  608             count = 1;
  609             
  610         cp = commPagePtr32;
  611         if ( cp ) {
  612                 cp += (_COMM_PAGE_SPIN_COUNT - _COMM_PAGE32_BASE_ADDRESS);
  613                 ip = (uint32_t*) cp;
  614                 *ip = (uint32_t) count;
  615         }
  616         
  617         cp = commPagePtr64;
  618         if ( cp ) {
  619                 cp += (_COMM_PAGE_SPIN_COUNT - _COMM_PAGE32_START_ADDRESS);
  620                 ip = (uint32_t*) cp;
  621                 *ip = (uint32_t) count;
  622         }
  623 
  624 }
  625 
  626 
  627 /* Check to see if a given address is in the Preemption Free Zone (PFZ) */
  628 
  629 uint32_t
  630 commpage_is_in_pfz32(uint32_t addr32)
  631 {
  632         if ( (addr32 >= _COMM_PAGE_PFZ_START) && (addr32 < _COMM_PAGE_PFZ_END)) {
  633                 return 1;
  634         }
  635         else
  636                 return 0;
  637 }
  638 
  639 uint32_t
  640 commpage_is_in_pfz64(addr64_t addr64)
  641 {
  642         if ( (addr64 >= _COMM_PAGE_32_TO_64(_COMM_PAGE_PFZ_START))
  643              && (addr64 <  _COMM_PAGE_32_TO_64(_COMM_PAGE_PFZ_END))) {
  644                 return 1;
  645         }
  646         else
  647                 return 0;
  648 }
  649 

Cache object: 87ba3939f81ad19657069cfecdddaaf3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.