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 ---