1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/errno.h> 32 #include <sys/segments.h> 33 #include <sys/archsystm.h> 34 #include <sys/proc.h> 35 #include <sys/sysi86.h> 36 #include <sys/cmn_err.h> 37 #include <sys/lx_ldt.h> 38 39 /* 40 * Read the ldt_info structure in from the Linux app, convert it to an ssd 41 * structure, and then call setdscr() to do all the heavy lifting. 42 */ 43 static int 44 write_ldt(void *data, ulong_t count) 45 { 46 user_desc_t usd; 47 struct ssd ssd; 48 struct ldt_info ldt_inf; 49 proc_t *pp = curthread->t_procp; 50 int err; 51 52 if (count != sizeof (ldt_inf)) 53 return (set_errno(EINVAL)); 54 55 if (copyin(data, &ldt_inf, sizeof (ldt_inf))) 56 return (set_errno(EFAULT)); 57 58 if (ldt_inf.entry_number >= MAXNLDT) 59 return (set_errno(EINVAL)); 60 61 LDT_INFO_TO_DESC(&ldt_inf, &usd); 62 usd_to_ssd(&usd, &ssd, SEL_LDT(ldt_inf.entry_number)); 63 64 /* 65 * Get everyone into a safe state before changing the LDT. 66 */ 67 if (!holdlwps(SHOLDFORK1)) 68 return (set_errno(EINTR)); 69 70 err = setdscr(&ssd); 71 72 /* 73 * Release the hounds! 74 */ 75 mutex_enter(&pp->p_lock); 76 continuelwps(pp); 77 mutex_exit(&pp->p_lock); 78 79 return (err ? set_errno(err) : 0); 80 } 81 82 static int 83 read_ldt(void *uptr, ulong_t count) 84 { 85 proc_t *pp = curproc; 86 int bytes; 87 88 if (pp->p_ldt == NULL) 89 return (0); 90 91 bytes = (pp->p_ldtlimit + 1) * sizeof (user_desc_t); 92 if (bytes > count) 93 bytes = count; 94 95 if (copyout(pp->p_ldt, uptr, bytes)) 96 return (set_errno(EFAULT)); 97 98 return (bytes); 99 } 100 101 long 102 lx_modify_ldt(int op, void *data, ulong_t count) 103 { 104 int rval; 105 106 switch (op) { 107 case 0: 108 rval = read_ldt(data, count); 109 break; 110 111 case 1: 112 rval = write_ldt(data, count); 113 break; 114 115 default: 116 rval = set_errno(ENOSYS); 117 break; 118 } 119 120 return (rval); 121 }