/* $NetBSD: darwin_commpage.c,v 1.6 2004/07/11 19:38:14 manu Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Emmanuel Dreyfus. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include __KERNEL_RCSID(0, "$NetBSD: darwin_commpage.c,v 1.6 2004/07/11 19:38:14 manu Exp $"); #include #include #include #include #include #include #include #include #include #include #ifdef __powerpc__ #include "opt_altivec.h" #endif static struct uvm_object *darwin_commpage_uao = NULL; static void darwin_commpage_init(struct darwin_commpage *); int darwin_commpage_map(p) struct proc *p; { int error; vaddr_t kvaddr; vaddr_t pvaddr; size_t memsize; /* * XXX This crashes. For now we map only one page, * to avoid the crash, but this ought to be fixed */ memsize = round_page(sizeof(struct darwin_commpage)); if (darwin_commpage_uao == NULL) { darwin_commpage_uao = uao_create(memsize, 0); kvaddr = vm_map_min(kernel_map); error = uvm_map(kernel_map, &kvaddr, memsize, darwin_commpage_uao, 0, PAGE_SIZE, UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW, UVM_INH_SHARE, UVM_ADV_RANDOM, 0)); if (error != 0) { uao_detach(darwin_commpage_uao); darwin_commpage_uao = NULL; return -1; } error = uvm_map_pageable(kernel_map, kvaddr, kvaddr + memsize, FALSE, 0); if (error != 0) { uao_detach(darwin_commpage_uao); darwin_commpage_uao = NULL; return -1; } darwin_commpage_init((struct darwin_commpage *)kvaddr); } uao_reference(darwin_commpage_uao); pvaddr = DARWIN_COMMPAGE_BASE; if ((error = uvm_map(&p->p_vmspace->vm_map, &pvaddr, memsize, darwin_commpage_uao, 0, 0, UVM_MAPFLAG(UVM_PROT_RX, UVM_PROT_RX, UVM_INH_SHARE, UVM_ADV_NORMAL, UVM_FLAG_FIXED))) != 0) { #ifdef DEBUG_DARWIN printf("uvm_map darwin_commpage failed (error %d)\n", error); #endif return -1; } #ifdef DEBUG_DARWIN printf("mapped darwin_commpage at 0x%08lx\n", (long)pvaddr); #endif return 0; } #define DCP_MEMCPY(x) { \ size_t len; \ \ len = (size_t)darwin_commpage_##x##_size; \ \ if (len > sizeof(dcp->dcp_##x)) { \ printf("darwin_commpage: %s too big (%d/%d)\n", #x, \ len, sizeof(dcp->dcp_##x)); \ } else { \ memcpy(dcp->dcp_##x, (void *)darwin_commpage_##x, len); \ } \ } void darwin_commpage_init(dcp) struct darwin_commpage *dcp; { int ncpu, name[2]; size_t sz; int error; /* * XXX Only one page is mapped yet (see higher in the file) */ bzero(dcp, sizeof(*dcp)); dcp->dcp_version = DARWIN_COMMPAGE_VERSION; name[0] = CTL_HW; name[1] = HW_NCPU; sz = sizeof(ncpu); error = old_sysctl(&name[0], 2, &ncpu, &sz, NULL, 0, NULL); if (error != 0) ncpu = 1; /* At least there should be one */ dcp->dcp_ncpu = ncpu; dcp->dcp_cap |= (ncpu << DARWIN_CAP_NCPUSHIFT); #ifdef ALTIVEC dcp->dcp_altivec = 1; dcp->dcp_cap |= DARWIN_CAP_ALTIVEC; #endif #ifdef _LP64 dcp->dcp_64bit = 1; dcp->dcp_cap |= DARWIN_CAP_64BIT; #endif #ifndef CACHELINESIZE #define CACHELINESIZE 32 /* for i386... */ #endif dcp->dcp_cachelinelen = CACHELINESIZE; #if (CACHELINESIZE == 32) dcp->dcp_cap |= DARWIN_CAP_CACHE32; #elif (CACHELINESIZE == 64) dcp->dcp_cap |= DARWIN_CAP_CACHE64; #elif (CACHELINESIZE == 128) dcp->dcp_cap |= DARWIN_CAP_CACHE128; #endif dcp->dcp_2pow52 = 4503599627370496ULL; /* 2^52 */ dcp->dcp_10pow6 = 1000000ULL; /* 10^6 */ /* * On Darwin, these are maintained up to date by the kernel */ dcp->dcp_timebase = 0; /* XXX */ dcp->dcp_timestamp = 0; /* XXX */ dcp->dcp_secpertick = hz; /* XXX Not sure */ DCP_MEMCPY(mach_absolute_time); DCP_MEMCPY(spinlock_try); DCP_MEMCPY(spinlock_lock); DCP_MEMCPY(spinlock_unlock); DCP_MEMCPY(pthread_getspecific); DCP_MEMCPY(gettimeofday); DCP_MEMCPY(sys_dcache_flush); DCP_MEMCPY(sys_icache_invalidate); DCP_MEMCPY(pthread_self); DCP_MEMCPY(spinlock_relinquish); DCP_MEMCPY(bzero); DCP_MEMCPY(bcopy); DCP_MEMCPY(memcpy); DCP_MEMCPY(bigcopy); return; }