sys_machdep.c (e31521c3dd0bf574311ff4bc504ac0fb54a9d624) | sys_machdep.c (48a09cf2760da35e089ae3e2d56578b730fc7047) |
---|---|
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 | 1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 |
34 * $Id: sys_machdep.c,v 1.21 1997/02/22 09:32:53 peter Exp $ | 34 * $Id: sys_machdep.c,v 1.22 1997/07/20 08:37:23 bde Exp $ |
35 * 36 */ 37 38#include "opt_user_ldt.h" 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/sysproto.h> 42#include <sys/proc.h> 43 44#include <vm/vm.h> 45#include <sys/lock.h> 46#include <vm/pmap.h> 47#include <vm/vm_map.h> 48#include <vm/vm_extern.h> 49 50#include <sys/user.h> 51 52#include <machine/cpu.h> 53#include <machine/sysarch.h> | 35 * 36 */ 37 38#include "opt_user_ldt.h" 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/sysproto.h> 42#include <sys/proc.h> 43 44#include <vm/vm.h> 45#include <sys/lock.h> 46#include <vm/pmap.h> 47#include <vm/vm_map.h> 48#include <vm/vm_extern.h> 49 50#include <sys/user.h> 51 52#include <machine/cpu.h> 53#include <machine/sysarch.h> |
54#include <machine/pcb_ext.h> |
|
54 55#include <vm/vm_kern.h> /* for kernel_map */ 56 57#define MAX_LD 8192 58#define LD_PER_PAGE 512 59#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1)) 60#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3) 61 62 63 64void set_user_ldt __P((struct pcb *pcb)); 65#ifdef USER_LDT 66static int i386_get_ldt __P((struct proc *, char *, int *)); 67static int i386_set_ldt __P((struct proc *, char *, int *)); 68#endif | 55 56#include <vm/vm_kern.h> /* for kernel_map */ 57 58#define MAX_LD 8192 59#define LD_PER_PAGE 512 60#define NEW_MAX_LD(num) ((num + LD_PER_PAGE) & ~(LD_PER_PAGE-1)) 61#define SIZE_FROM_LARGEST_LD(num) (NEW_MAX_LD(num) << 3) 62 63 64 65void set_user_ldt __P((struct pcb *pcb)); 66#ifdef USER_LDT 67static int i386_get_ldt __P((struct proc *, char *, int *)); 68static int i386_set_ldt __P((struct proc *, char *, int *)); 69#endif |
70#ifdef VM86 71static int i386_get_ioperm __P((struct proc *, char *, int *)); 72static int i386_set_ioperm __P((struct proc *, char *, int *)); 73int i386_extend_pcb __P((struct proc *)); 74int (*vm86_sysarch) __P((struct proc *, char *, int *)); 75#endif |
|
69 70#ifndef _SYS_SYSPROTO_H_ 71struct sysarch_args { 72 int op; 73 char *parms; 74}; 75#endif 76 --- 10 unchanged lines hidden (view full) --- 87 case I386_GET_LDT: 88 error = i386_get_ldt(p, uap->parms, retval); 89 break; 90 91 case I386_SET_LDT: 92 error = i386_set_ldt(p, uap->parms, retval); 93 break; 94#endif | 76 77#ifndef _SYS_SYSPROTO_H_ 78struct sysarch_args { 79 int op; 80 char *parms; 81}; 82#endif 83 --- 10 unchanged lines hidden (view full) --- 94 case I386_GET_LDT: 95 error = i386_get_ldt(p, uap->parms, retval); 96 break; 97 98 case I386_SET_LDT: 99 error = i386_set_ldt(p, uap->parms, retval); 100 break; 101#endif |
102#ifdef VM86 103 case I386_GET_IOPERM: 104 error = i386_get_ioperm(p, uap->parms, retval); 105 break; 106 case I386_SET_IOPERM: 107 error = i386_set_ioperm(p, uap->parms, retval); 108 break; 109 case I386_VM86: 110 if (vm86_sysarch) { 111 error = (*vm86_sysarch)(p, uap->parms, retval); 112 break; 113 } 114 /* FALL THROUGH */ 115#endif |
|
95 default: 96 error = EINVAL; 97 break; 98 } | 116 default: 117 error = EINVAL; 118 break; 119 } |
99 return(error); | 120 return (error); |
100} 101 | 121} 122 |
123#ifdef VM86 124int 125i386_extend_pcb(struct proc *p) 126{ 127 int i, offset; 128 u_long *addr; 129 struct pcb_ext *ext; 130 struct segment_descriptor sd; 131 struct soft_segment_descriptor ssd = { 132 0, /* segment base address (overwritten) */ 133 ctob(IOPAGES + 1) - 1, /* length */ 134 SDT_SYS386TSS, /* segment type */ 135 0, /* priority level */ 136 1, /* descriptor present */ 137 0, 0, 138 0, /* default 32 size */ 139 0 /* granularity */ 140 }; 141 142 ext = (struct pcb_ext *)kmem_alloc(kernel_map, ctob(IOPAGES+1)); 143 if (ext == 0) 144 return (ENOMEM); 145 p->p_addr->u_pcb.pcb_ext = ext; 146 bzero(&ext->ext_tss, sizeof(struct i386tss)); 147 ext->ext_tss.tss_esp0 = (unsigned)p->p_addr + ctob(UPAGES) - 16; 148 ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); 149 /* 150 * The last byte of the i/o map must be followed by an 0xff byte. 151 * We arbitrarily allocate 16 bytes here, to keep the starting 152 * address on a doubleword boundary. 153 */ 154 offset = PAGE_SIZE - 16; 155 ext->ext_tss.tss_ioopt = 156 (offset - ((unsigned)&ext->ext_tss - (unsigned)ext)) << 16; 157 ext->ext_iomap = (caddr_t)ext + offset; 158 ext->ext_vm86.vm86_intmap = (caddr_t)ext + offset - 32; 159 ext->ext_vm86.vm86_inited = 0; 160 161 addr = (u_long *)ext->ext_vm86.vm86_intmap; 162 for (i = 0; i < (ctob(IOPAGES) + 32 + 16) / sizeof(u_long); i++) 163 *addr++ = ~0; 164 165 ssd.ssd_base = (unsigned)&ext->ext_tss; 166 ssd.ssd_limit -= ((unsigned)&ext->ext_tss - (unsigned)ext); 167 ssdtosd(&ssd, &ext->ext_tssd); 168 169 /* switch to the new TSS after syscall completes */ 170 need_resched(); 171 172 return 0; 173} 174 175struct i386_ioperm_args { 176 u_short start; 177 u_short length; 178 u_char enable; 179}; 180 181static int 182i386_set_ioperm(p, args, retval) 183 struct proc *p; 184 char *args; 185 int *retval; 186{ 187 int i, error = 0; 188 struct i386_ioperm_args ua; 189 char *iomap; 190 191 if (error = copyin(args, &ua, sizeof(struct i386_ioperm_args))) 192 return (error); 193 194 /* Only root can do this */ 195 if (error = suser(p->p_ucred, &p->p_acflag)) 196 return (error); 197 /* 198 * XXX 199 * While this is restricted to root, we should probably figure out 200 * whether any other driver is using this i/o address, as so not to 201 * cause confusion. This probably requires a global 'usage registry'. 202 */ 203 204 if (p->p_addr->u_pcb.pcb_ext == 0) 205 if (error = i386_extend_pcb(p)) 206 return (error); 207 iomap = (char *)p->p_addr->u_pcb.pcb_ext->ext_iomap; 208 209 if ((int)(ua.start + ua.length) > 0xffff) 210 return (EINVAL); 211 212 for (i = ua.start; i < (int)(ua.start + ua.length) + 1; i++) { 213 if (ua.enable) 214 iomap[i >> 3] &= ~(1 << (i & 7)); 215 else 216 iomap[i >> 3] |= (1 << (i & 7)); 217 } 218 return (error); 219} 220 221static int 222i386_get_ioperm(p, args, retval) 223 struct proc *p; 224 char *args; 225 int *retval; 226{ 227 int i, state, error = 0; 228 struct i386_ioperm_args ua; 229 char *iomap; 230 231 if (error = copyin(args, &ua, sizeof(struct i386_ioperm_args))) 232 return (error); 233 234 if (p->p_addr->u_pcb.pcb_ext == 0) { 235 ua.length = 0; 236 goto done; 237 } 238 239 iomap = (char *)p->p_addr->u_pcb.pcb_ext->ext_iomap; 240 241 state = (iomap[i >> 3] >> (i & 7)) & 1; 242 ua.enable = !state; 243 ua.length = 1; 244 245 for (i = ua.start + 1; i < 0x10000; i++) { 246 if (state != ((iomap[i >> 3] >> (i & 7)) & 1)) 247 break; 248 ua.length++; 249 } 250 251done: 252 error = copyout(&ua, args, sizeof(struct i386_ioperm_args)); 253 return (error); 254} 255#endif /* VM86 */ 256 |
|
102#ifdef USER_LDT 103/* 104 * Update the GDT entry pointing to the LDT to point to the LDT of the 105 * current process. 106 */ 107void 108set_user_ldt(struct pcb *pcb) 109{ --- 199 unchanged lines hidden --- | 257#ifdef USER_LDT 258/* 259 * Update the GDT entry pointing to the LDT to point to the LDT of the 260 * current process. 261 */ 262void 263set_user_ldt(struct pcb *pcb) 264{ --- 199 unchanged lines hidden --- |