1/*- 2 * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com> 3 * Copyright (C) 2006 Semihalf, Rafal Jaworowski <raj@semihalf.com> 4 * All rights reserved. 5 * 6 * Adapted for Freescale's e500 core CPUs. 7 * sf_buf implementation was derived from sys/arm/arm/vm_machdep. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * from: $FreeBSD$ 30 */ 31/*- 32 * Copyright (c) 1982, 1986 The Regents of the University of California. 33 * Copyright (c) 1989, 1990 William Jolitz 34 * Copyright (c) 1994 John Dyson 35 * All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department, and William Jolitz. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. All advertising materials mentioning features or use of this software 50 * must display the following acknowledgement: 51 * This product includes software developed by the University of 52 * California, Berkeley and its contributors. 53 * 4. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 70 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 71 */ 72/*- 73 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 74 * All rights reserved. 75 * 76 * Author: Chris G. Demetriou 77 * 78 * Permission to use, copy, modify and distribute this software and 79 * its documentation is hereby granted, provided that both the copyright 80 * notice and this permission notice appear in all copies of the 81 * software, derivative works or modified versions, and any portions 82 * thereof, and that both notices appear in supporting documentation. 83 * 84 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 85 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 86 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 87 * 88 * Carnegie Mellon requests users of this software to return to 89 * 90 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 91 * School of Computer Science 92 * Carnegie Mellon University 93 * Pittsburgh PA 15213-3890 94 * 95 * any improvements or extensions that they make and grant Carnegie the 96 * rights to redistribute these changes. 97 */ 98 99#include <sys/cdefs.h> 100__FBSDID("$FreeBSD$"); 101 102#include <sys/param.h> 103#include <sys/systm.h> 104#include <sys/proc.h> 105#include <sys/malloc.h> 106#include <sys/bio.h> 107#include <sys/buf.h> 108#include <sys/ktr.h> 109#include <sys/lock.h> 110#include <sys/mutex.h> 111#include <sys/vnode.h> 112#include <sys/vmmeter.h> 113#include <sys/kernel.h> 114#include <sys/mbuf.h> 115#include <sys/sf_buf.h> 116#include <sys/syscall.h> 117#include <sys/sysctl.h> 118#include <sys/sysent.h> 119#include <sys/unistd.h> 120 121#include <machine/clock.h> 122#include <machine/cpu.h> 123#include <machine/frame.h> 124#include <machine/md_var.h> 125#include <machine/pcb.h> 126#include <machine/spr.h> 127#include <machine/platform.h> 128 129#include <vm/vm.h> 130#include <vm/vm_param.h> 131#include <vm/vm_kern.h> 132#include <vm/vm_page.h> 133#include <vm/vm_map.h> 134#include <vm/vm_extern.h> 135 136#ifndef NSFBUFS 137#define NSFBUFS (512 + maxusers * 16) 138#endif 139 140static int nsfbufs; 141static int nsfbufspeak; 142static int nsfbufsused; 143 144SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0, 145 "Maximum number of sendfile(2) sf_bufs available"); 146SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0, 147 "Number of sendfile(2) sf_bufs at peak usage"); 148SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0, 149 "Number of sendfile(2) sf_bufs in use"); 150 151static void sf_buf_init(void *arg); 152SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); 153 154LIST_HEAD(sf_head, sf_buf); 155 156/* A hash table of active sendfile(2) buffers */ 157static struct sf_head *sf_buf_active; 158static u_long sf_buf_hashmask; 159 160#define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask) 161 162static TAILQ_HEAD(, sf_buf) sf_buf_freelist; 163static u_int sf_buf_alloc_want; 164 165/* 166 * A lock used to synchronize access to the hash table and free list 167 */ 168static struct mtx sf_buf_lock; 169 170/* 171 * Finish a fork operation, with process p2 nearly set up. 172 * Copy and update the pcb, set up the stack so that the child 173 * ready to run and return to user mode. 174 */ 175void 176cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) 177{ 178 struct proc *p1; 179 struct trapframe *tf; 180 struct callframe *cf; 181 struct pcb *pcb; 182 183 KASSERT(td1 == curthread || td1 == &thread0, 184 ("cpu_fork: p1 not curproc and not proc0")); 185 CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, 186 (u_int)p2, flags); 187 188 if ((flags & RFPROC) == 0) 189 return; 190 191 p1 = td1->td_proc; 192 193 pcb = (struct pcb *)((td2->td_kstack + 194 td2->td_kstack_pages * PAGE_SIZE - sizeof(struct pcb)) & ~0x3fU); 195 td2->td_pcb = pcb; 196 197 /* Copy the pcb */ 198 bcopy(td1->td_pcb, pcb, sizeof(struct pcb)); 199 200 /* 201 * Create a fresh stack for the new process. 202 * Copy the trap frame for the return to user mode as if from a 203 * syscall. This copies most of the user mode register values. 204 */ 205 tf = (struct trapframe *)pcb - 1; 206 bcopy(td1->td_frame, tf, sizeof(*tf)); 207 208 /* Set up trap frame. */ 209 tf->fixreg[FIRSTARG] = 0; 210 tf->fixreg[FIRSTARG + 1] = 0; 211 tf->cr &= ~0x10000000; 212 213 td2->td_frame = tf; 214 215 cf = (struct callframe *)tf - 1; 216 memset(cf, 0, sizeof(struct callframe)); 217 cf->cf_func = (register_t)fork_return; 218 cf->cf_arg0 = (register_t)td2; 219 cf->cf_arg1 = (register_t)tf; 220 221 pcb->pcb_sp = (register_t)cf; 222 pcb->pcb_lr = (register_t)fork_trampoline; 223 224 /* Setup to release sched_lock in fork_exit(). */ 225 td2->td_md.md_spinlock_count = 1; 226 td2->td_md.md_saved_msr = PSL_KERNSET; 227 228 /* 229 * Now cpu_switch() can schedule the new process. 230 */ 231} 232 233/* 234 * Intercept the return address from a freshly forked process that has NOT 235 * been scheduled yet. 236 * 237 * This is needed to make kernel threads stay in kernel mode. 238 */ 239void 240cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg) 241{ 242 struct callframe *cf; 243 244 CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x", 245 (u_int)td, (u_int)func, (u_int)arg); 246 247 cf = (struct callframe *)td->td_pcb->pcb_sp; 248 249 cf->cf_func = (register_t)func; 250 cf->cf_arg0 = (register_t)arg; 251} 252 253void 254cpu_exit(struct thread *td) 255{ 256 257} 258 259/* 260 * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) 261 */ 262static void 263sf_buf_init(void *arg) 264{ 265 struct sf_buf *sf_bufs; 266 vm_offset_t sf_base; 267 int i; 268 269 nsfbufs = NSFBUFS; 270 TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs); 271 272 sf_buf_active = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask); 273 TAILQ_INIT(&sf_buf_freelist); 274 sf_base = kva_alloc(nsfbufs * PAGE_SIZE); 275 sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT | M_ZERO); 276 277 for (i = 0; i < nsfbufs; i++) { 278 sf_bufs[i].kva = sf_base + i * PAGE_SIZE; 279 TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry); 280 } 281 sf_buf_alloc_want = 0; 282 mtx_init(&sf_buf_lock, "sf_buf", NULL, MTX_DEF); 283} 284 285/* 286 * Get an sf_buf from the freelist. Will block if none are available. 287 */ 288struct sf_buf * 289sf_buf_alloc(struct vm_page *m, int flags) 290{ 291 struct sf_head *hash_list; 292 struct sf_buf *sf; 293 int error; 294 295 hash_list = &sf_buf_active[SF_BUF_HASH(m)]; 296 mtx_lock(&sf_buf_lock); 297 LIST_FOREACH(sf, hash_list, list_entry) { 298 if (sf->m == m) { 299 sf->ref_count++; 300 if (sf->ref_count == 1) { 301 TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); 302 nsfbufsused++; 303 nsfbufspeak = imax(nsfbufspeak, nsfbufsused); 304 } 305 goto done; 306 } 307 } 308 309 while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) { 310 if (flags & SFB_NOWAIT) 311 goto done; 312 313 sf_buf_alloc_want++; 314 SFSTAT_INC(sf_allocwait); 315 error = msleep(&sf_buf_freelist, &sf_buf_lock, 316 (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); 317 sf_buf_alloc_want--; 318 319 /* 320 * If we got a signal, don't risk going back to sleep. 321 */ 322 if (error) 323 goto done; 324 } 325 326 TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); 327 if (sf->m != NULL) 328 LIST_REMOVE(sf, list_entry); 329 330 LIST_INSERT_HEAD(hash_list, sf, list_entry); 331 sf->ref_count = 1; 332 sf->m = m; 333 nsfbufsused++; 334 nsfbufspeak = imax(nsfbufspeak, nsfbufsused); 335 pmap_qenter(sf->kva, &sf->m, 1); 336done: 337 mtx_unlock(&sf_buf_lock); 338 return (sf); 339} 340 341/* 342 * Detach mapped page and release resources back to the system. 343 * 344 * Remove a reference from the given sf_buf, adding it to the free 345 * list when its reference count reaches zero. A freed sf_buf still, 346 * however, retains its virtual-to-physical mapping until it is 347 * recycled or reactivated by sf_buf_alloc(9). 348 */ 349void 350sf_buf_free(struct sf_buf *sf) 351{ 352 353 mtx_lock(&sf_buf_lock); 354 sf->ref_count--; 355 if (sf->ref_count == 0) { 356 TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry); 357 nsfbufsused--; 358 359 if (sf_buf_alloc_want > 0) 360 wakeup(&sf_buf_freelist); 361 } 362 mtx_unlock(&sf_buf_lock); 363} 364 365/* 366 * Software interrupt handler for queued VM system processing. 367 */ 368void 369swi_vm(void *dummy) 370{ 371 372 if (busdma_swi_pending != 0) 373 busdma_swi(); 374} 375 376/* 377 * Tell whether this address is in some physical memory region. 378 * Currently used by the kernel coredump code in order to avoid 379 * dumping the ``ISA memory hole'' which could cause indefinite hangs, 380 * or other unpredictable behaviour. 381 */ 382int 383is_physical_memory(vm_offset_t addr) 384{ 385 386 /* 387 * stuff other tests for known memory-mapped devices (PCI?) 388 * here 389 */ 390 return (1); 391} 392 393/* 394 * CPU threading functions related to VM. 395 */ 396 397void 398cpu_thread_swapin(struct thread *td) 399{ 400 401} 402 403void 404cpu_thread_swapout(struct thread *td) 405{ 406 407} 408 409