sys_machdep.c revision 263036
1129198Scognet/*- 2129198Scognet * Copyright (c) 1990 The Regents of the University of California. 3129198Scognet * All rights reserved. 4129198Scognet * 5129198Scognet * Redistribution and use in source and binary forms, with or without 6129198Scognet * modification, are permitted provided that the following conditions 7129198Scognet * are met: 8129198Scognet * 1. Redistributions of source code must retain the above copyright 9129198Scognet * notice, this list of conditions and the following disclaimer. 10129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 11129198Scognet * notice, this list of conditions and the following disclaimer in the 12129198Scognet * documentation and/or other materials provided with the distribution. 13263036Simp * 3. Neither the name of the University nor the names of its contributors 14129198Scognet * may be used to endorse or promote products derived from this software 15129198Scognet * without specific prior written permission. 16129198Scognet * 17129198Scognet * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18129198Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19129198Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20129198Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21129198Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22129198Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23129198Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27129198Scognet * SUCH DAMAGE. 28129198Scognet * 29129198Scognet * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 30129198Scognet */ 31129198Scognet 32129198Scognet#include <sys/cdefs.h> 33129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/sys_machdep.c 263036 2014-03-11 17:08:45Z imp $"); 34129198Scognet 35223668Sjonathan#include "opt_capsicum.h" 36219134Srwatson 37129198Scognet#include <sys/param.h> 38129198Scognet#include <sys/systm.h> 39219134Srwatson#include <sys/capability.h> 40129198Scognet#include <sys/proc.h> 41129198Scognet#include <sys/sysproto.h> 42129198Scognet#include <sys/syscall.h> 43129198Scognet#include <sys/sysent.h> 44129198Scognet 45135642Scognet#include <machine/sysarch.h> 46135642Scognet 47129198Scognet#ifndef _SYS_SYSPROTO_H_ 48129198Scognetstruct sysarch_args { 49129198Scognet int op; 50129198Scognet char *parms; 51129198Scognet}; 52129198Scognet#endif 53129198Scognet 54135642Scognet/* Prototypes */ 55135642Scognetstatic int arm32_sync_icache (struct thread *, void *); 56135642Scognetstatic int arm32_drain_writebuf(struct thread *, void *); 57135642Scognet 58135642Scognetstatic int 59135642Scognetarm32_sync_icache(struct thread *td, void *args) 60135642Scognet{ 61135642Scognet struct arm_sync_icache_args ua; 62135642Scognet int error; 63135642Scognet 64135642Scognet if ((error = copyin(args, &ua, sizeof(ua))) != 0) 65135642Scognet return (error); 66135642Scognet 67135642Scognet cpu_icache_sync_range(ua.addr, ua.len); 68135642Scognet 69135642Scognet td->td_retval[0] = 0; 70166695Skevlo return (0); 71135642Scognet} 72135642Scognet 73135642Scognetstatic int 74135642Scognetarm32_drain_writebuf(struct thread *td, void *args) 75135642Scognet{ 76135642Scognet /* No args. */ 77135642Scognet 78135642Scognet td->td_retval[0] = 0; 79135642Scognet cpu_drain_writebuf(); 80166695Skevlo return (0); 81135642Scognet} 82135642Scognet 83142519Scognetstatic int 84142519Scognetarm32_set_tp(struct thread *td, void *args) 85142519Scognet{ 86142519Scognet 87239268Sgonzo if (td != curthread) 88239268Sgonzo td->td_md.md_tp = (register_t)args; 89239268Sgonzo else 90239268Sgonzo#ifndef ARM_TP_ADDRESS 91239268Sgonzo set_tls(args); 92239268Sgonzo#else 93239268Sgonzo *(register_t *)ARM_TP_ADDRESS = (register_t)args; 94239268Sgonzo#endif 95142519Scognet return (0); 96142519Scognet} 97142519Scognet 98142519Scognetstatic int 99142519Scognetarm32_get_tp(struct thread *td, void *args) 100142519Scognet{ 101142519Scognet 102239268Sgonzo if (td != curthread) 103239268Sgonzo td->td_retval[0] = td->td_md.md_tp; 104239268Sgonzo else 105239268Sgonzo#ifndef ARM_TP_ADDRESS 106239268Sgonzo td->td_retval[0] = (register_t)get_tls(); 107239268Sgonzo#else 108239268Sgonzo td->td_retval[0] = *(register_t *)ARM_TP_ADDRESS; 109239268Sgonzo#endif 110142519Scognet return (0); 111142519Scognet} 112142519Scognet 113129198Scognetint 114129198Scognetsysarch(td, uap) 115129198Scognet struct thread *td; 116129198Scognet register struct sysarch_args *uap; 117129198Scognet{ 118135642Scognet int error; 119135642Scognet 120223668Sjonathan#ifdef CAPABILITY_MODE 121219134Srwatson /* 122223692Sjonathan * When adding new operations, add a new case statement here to 123223692Sjonathan * explicitly indicate whether or not the operation is safe to 124223692Sjonathan * perform in capability mode. 125219134Srwatson */ 126219134Srwatson if (IN_CAPABILITY_MODE(td)) { 127219134Srwatson switch (uap->op) { 128223692Sjonathan case ARM_SYNC_ICACHE: 129223692Sjonathan case ARM_DRAIN_WRITEBUF: 130223692Sjonathan case ARM_SET_TP: 131223692Sjonathan case ARM_GET_TP: 132223692Sjonathan break; 133219134Srwatson 134223692Sjonathan default: 135226498Sdes#ifdef KTRACE 136226498Sdes if (KTRPOINT(td, KTR_CAPFAIL)) 137255677Spjd ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL); 138226498Sdes#endif 139223692Sjonathan return (ECAPMODE); 140219134Srwatson } 141219134Srwatson } 142219134Srwatson#endif 143219134Srwatson 144135642Scognet switch (uap->op) { 145236991Simp case ARM_SYNC_ICACHE: 146135642Scognet error = arm32_sync_icache(td, uap->parms); 147135642Scognet break; 148236991Simp case ARM_DRAIN_WRITEBUF: 149135642Scognet error = arm32_drain_writebuf(td, uap->parms); 150135642Scognet break; 151142519Scognet case ARM_SET_TP: 152142519Scognet error = arm32_set_tp(td, uap->parms); 153142519Scognet break; 154142519Scognet case ARM_GET_TP: 155142519Scognet error = arm32_get_tp(td, uap->parms); 156142519Scognet break; 157135642Scognet default: 158135642Scognet error = EINVAL; 159135642Scognet break; 160135642Scognet } 161135642Scognet return (error); 162129198Scognet} 163