1
2
3
4
5
6#include <linux/errno.h>
7#include <linux/sched.h>
8#include <linux/kernel.h>
9#include <linux/signal.h>
10#include <linux/string.h>
11#include <linux/ptrace.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
14#include <linux/smp_lock.h>
15#include <linux/highmem.h>
16
17#include <asm/uaccess.h>
18#include <asm/pgalloc.h>
19#include <asm/io.h>
20#include <asm/tlbflush.h>
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#define KVM86 ((struct kernel_vm86_struct *)regs)
39#define VMPI KVM86->vm86plus
40
41
42
43
44
45#define AL(regs) (((unsigned char *)&((regs)->eax))[0])
46#define AH(regs) (((unsigned char *)&((regs)->eax))[1])
47#define IP(regs) (*(unsigned short *)&((regs)->eip))
48#define SP(regs) (*(unsigned short *)&((regs)->esp))
49
50
51
52
53#define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
54#define VEFLAGS (current->thread.v86flags)
55
56#define set_flags(X,new,mask) \
57((X) = ((X) & ~(mask)) | ((new) & (mask)))
58
59#define SAFE_MASK (0xDD5)
60#define RETURN_MASK (0xDFF)
61
62#define VM86_REGS_PART2 orig_eax
63#define VM86_REGS_SIZE1 \
64 ( (unsigned)( & (((struct kernel_vm86_regs *)0)->VM86_REGS_PART2) ) )
65#define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1)
66
67struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
68struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
69{
70 struct tss_struct *tss;
71 struct pt_regs *ret;
72 unsigned long tmp;
73
74 if (!current->thread.vm86_info) {
75 printk("no vm86_info: BAD\n");
76 do_exit(SIGSEGV);
77 }
78 set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);
79 tmp = copy_to_user(¤t->thread.vm86_info->regs,regs, VM86_REGS_SIZE1);
80 tmp += copy_to_user(¤t->thread.vm86_info->regs.VM86_REGS_PART2,
81 ®s->VM86_REGS_PART2, VM86_REGS_SIZE2);
82 tmp += put_user(current->thread.screen_bitmap,¤t->thread.vm86_info->screen_bitmap);
83 if (tmp) {
84 printk("vm86: could not access userspace vm86_info\n");
85 do_exit(SIGSEGV);
86 }
87 tss = init_tss + smp_processor_id();
88 tss->esp0 = current->thread.esp0 = current->thread.saved_esp0;
89 current->thread.saved_esp0 = 0;
90 ret = KVM86->regs32;
91 return ret;
92}
93
94static void mark_screen_rdonly(struct task_struct * tsk)
95{
96 pgd_t *pgd;
97 pmd_t *pmd;
98 pte_t *pte, *mapped;
99 int i;
100
101 pgd = pgd_offset(tsk->mm, 0xA0000);
102 if (pgd_none(*pgd))
103 return;
104 if (pgd_bad(*pgd)) {
105 pgd_ERROR(*pgd);
106 pgd_clear(pgd);
107 return;
108 }
109 pmd = pmd_offset(pgd, 0xA0000);
110 if (pmd_none(*pmd))
111 return;
112 if (pmd_bad(*pmd)) {
113 pmd_ERROR(*pmd);
114 pmd_clear(pmd);
115 return;
116 }
117 preempt_disable();
118 pte = mapped = pte_offset_map(pmd, 0xA0000);
119 for (i = 0; i < 32; i++) {
120 if (pte_present(*pte))
121 set_pte(pte, pte_wrprotect(*pte));
122 pte++;
123 }
124 pte_unmap(mapped);
125 preempt_enable();
126 flush_tlb();
127}
128
129
130
131static int do_vm86_irq_handling(int subfunction, int irqnumber);
132static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
133
134asmlinkage int sys_vm86old(struct vm86_struct * v86)
135{
136 struct kernel_vm86_struct info;
137
138
139
140
141 struct task_struct *tsk;
142 int tmp, ret = -EPERM;
143
144 tsk = current;
145 if (tsk->thread.saved_esp0)
146 goto out;
147 tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
148 tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
149 (long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2);
150 ret = -EFAULT;
151 if (tmp)
152 goto out;
153 memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
154 info.regs32 = (struct pt_regs *) &v86;
155 tsk->thread.vm86_info = v86;
156 do_sys_vm86(&info, tsk);
157 ret = 0;
158out:
159 return ret;
160}
161
162
163asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86)
164{
165 struct kernel_vm86_struct info;
166
167
168
169
170 struct task_struct *tsk;
171 int tmp, ret;
172
173 tsk = current;
174 switch (subfunction) {
175 case VM86_REQUEST_IRQ:
176 case VM86_FREE_IRQ:
177 case VM86_GET_IRQ_BITS:
178 case VM86_GET_AND_RESET_IRQ:
179 ret = do_vm86_irq_handling(subfunction,(int)v86);
180 goto out;
181 case VM86_PLUS_INSTALL_CHECK:
182
183
184
185
186
187 ret = 0;
188 goto out;
189 }
190
191
192 ret = -EPERM;
193 if (tsk->thread.saved_esp0)
194 goto out;
195 tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
196 tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
197 (long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2);
198 ret = -EFAULT;
199 if (tmp)
200 goto out;
201 info.regs32 = (struct pt_regs *) &subfunction;
202 info.vm86plus.is_vm86pus = 1;
203 tsk->thread.vm86_info = (struct vm86_struct *)v86;
204 do_sys_vm86(&info, tsk);
205 ret = 0;
206out:
207 return ret;
208}
209
210
211static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
212{
213 struct tss_struct *tss;
214
215
216
217 info->regs.__null_ds = 0;
218 info->regs.__null_es = 0;
219
220
221
222
223
224
225
226
227
228
229 VEFLAGS = info->regs.eflags;
230 info->regs.eflags &= SAFE_MASK;
231 info->regs.eflags |= info->regs32->eflags & ~SAFE_MASK;
232 info->regs.eflags |= VM_MASK;
233
234 switch (info->cpu_type) {
235 case CPU_286:
236 tsk->thread.v86mask = 0;
237 break;
238 case CPU_386:
239 tsk->thread.v86mask = NT_MASK | IOPL_MASK;
240 break;
241 case CPU_486:
242 tsk->thread.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
243 break;
244 default:
245 tsk->thread.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
246 break;
247 }
248
249
250
251
252 info->regs32->eax = 0;
253 tsk->thread.saved_esp0 = tsk->thread.esp0;
254 tss = init_tss + smp_processor_id();
255 tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
256
257 tsk->thread.screen_bitmap = info->screen_bitmap;
258 if (info->flags & VM86_SCREEN_BITMAP)
259 mark_screen_rdonly(tsk);
260 __asm__ __volatile__(
261 "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t"
262 "movl %0,%%esp\n\t"
263 "jmp resume_userspace"
264 :
265 :"r" (&info->regs), "b" (tsk) : "ax");
266
267}
268
269static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
270{
271 struct pt_regs * regs32;
272
273 regs32 = save_v86_state(regs16);
274 regs32->eax = retval;
275 __asm__ __volatile__("movl %0,%%esp\n\t"
276 "jmp resume_userspace"
277 : : "r" (regs32), "b" (current));
278}
279
280static inline void set_IF(struct kernel_vm86_regs * regs)
281{
282 VEFLAGS |= VIF_MASK;
283 if (VEFLAGS & VIP_MASK)
284 return_to_32bit(regs, VM86_STI);
285}
286
287static inline void clear_IF(struct kernel_vm86_regs * regs)
288{
289 VEFLAGS &= ~VIF_MASK;
290}
291
292static inline void clear_TF(struct kernel_vm86_regs * regs)
293{
294 regs->eflags &= ~TF_MASK;
295}
296
297static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs)
298{
299 set_flags(VEFLAGS, eflags, current->thread.v86mask);
300 set_flags(regs->eflags, eflags, SAFE_MASK);
301 if (eflags & IF_MASK)
302 set_IF(regs);
303}
304
305static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs)
306{
307 set_flags(VFLAGS, flags, current->thread.v86mask);
308 set_flags(regs->eflags, flags, SAFE_MASK);
309 if (flags & IF_MASK)
310 set_IF(regs);
311}
312
313static inline unsigned long get_vflags(struct kernel_vm86_regs * regs)
314{
315 unsigned long flags = regs->eflags & RETURN_MASK;
316
317 if (VEFLAGS & VIF_MASK)
318 flags |= IF_MASK;
319 return flags | (VEFLAGS & current->thread.v86mask);
320}
321
322static inline int is_revectored(int nr, struct revectored_struct * bitmap)
323{
324 __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
325 :"=r" (nr)
326 :"m" (*bitmap),"r" (nr));
327 return nr;
328}
329
330
331
332
333
334
335#define pushb(base, ptr, val) \
336__asm__ __volatile__( \
337 "decw %w0\n\t" \
338 "movb %2,0(%1,%0)" \
339 : "=r" (ptr) \
340 : "r" (base), "q" (val), "0" (ptr))
341
342#define pushw(base, ptr, val) \
343__asm__ __volatile__( \
344 "decw %w0\n\t" \
345 "movb %h2,0(%1,%0)\n\t" \
346 "decw %w0\n\t" \
347 "movb %b2,0(%1,%0)" \
348 : "=r" (ptr) \
349 : "r" (base), "q" (val), "0" (ptr))
350
351#define pushl(base, ptr, val) \
352__asm__ __volatile__( \
353 "decw %w0\n\t" \
354 "rorl $16,%2\n\t" \
355 "movb %h2,0(%1,%0)\n\t" \
356 "decw %w0\n\t" \
357 "movb %b2,0(%1,%0)\n\t" \
358 "decw %w0\n\t" \
359 "rorl $16,%2\n\t" \
360 "movb %h2,0(%1,%0)\n\t" \
361 "decw %w0\n\t" \
362 "movb %b2,0(%1,%0)" \
363 : "=r" (ptr) \
364 : "r" (base), "q" (val), "0" (ptr))
365
366#define popb(base, ptr) \
367({ unsigned long __res; \
368__asm__ __volatile__( \
369 "movb 0(%1,%0),%b2\n\t" \
370 "incw %w0" \
371 : "=r" (ptr), "=r" (base), "=q" (__res) \
372 : "0" (ptr), "1" (base), "2" (0)); \
373__res; })
374
375#define popw(base, ptr) \
376({ unsigned long __res; \
377__asm__ __volatile__( \
378 "movb 0(%1,%0),%b2\n\t" \
379 "incw %w0\n\t" \
380 "movb 0(%1,%0),%h2\n\t" \
381 "incw %w0" \
382 : "=r" (ptr), "=r" (base), "=q" (__res) \
383 : "0" (ptr), "1" (base), "2" (0)); \
384__res; })
385
386#define popl(base, ptr) \
387({ unsigned long __res; \
388__asm__ __volatile__( \
389 "movb 0(%1,%0),%b2\n\t" \
390 "incw %w0\n\t" \
391 "movb 0(%1,%0),%h2\n\t" \
392 "incw %w0\n\t" \
393 "rorl $16,%2\n\t" \
394 "movb 0(%1,%0),%b2\n\t" \
395 "incw %w0\n\t" \
396 "movb 0(%1,%0),%h2\n\t" \
397 "incw %w0\n\t" \
398 "rorl $16,%2" \
399 : "=r" (ptr), "=r" (base), "=q" (__res) \
400 : "0" (ptr), "1" (base)); \
401__res; })
402
403static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp)
404{
405 unsigned long *intr_ptr, segoffs;
406
407 if (regs->cs == BIOSSEG)
408 goto cannot_handle;
409 if (is_revectored(i, &KVM86->int_revectored))
410 goto cannot_handle;
411 if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored))
412 goto cannot_handle;
413 intr_ptr = (unsigned long *) (i << 2);
414 if (get_user(segoffs, intr_ptr))
415 goto cannot_handle;
416 if ((segoffs >> 16) == BIOSSEG)
417 goto cannot_handle;
418 pushw(ssp, sp, get_vflags(regs));
419 pushw(ssp, sp, regs->cs);
420 pushw(ssp, sp, IP(regs));
421 regs->cs = segoffs >> 16;
422 SP(regs) -= 6;
423 IP(regs) = segoffs & 0xffff;
424 clear_TF(regs);
425 clear_IF(regs);
426 return;
427
428cannot_handle:
429 return_to_32bit(regs, VM86_INTx + (i << 8));
430}
431
432int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno)
433{
434 if (VMPI.is_vm86pus) {
435 if ( (trapno==3) || (trapno==1) )
436 return_to_32bit(regs, VM86_TRAP + (trapno << 8));
437 do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs));
438 return 0;
439 }
440 if (trapno !=1)
441 return 1;
442 if (current->ptrace & PT_PTRACED) {
443 unsigned long flags;
444 spin_lock_irqsave(¤t->sigmask_lock, flags);
445 sigdelset(¤t->blocked, SIGTRAP);
446 recalc_sigpending();
447 spin_unlock_irqrestore(¤t->sigmask_lock, flags);
448 }
449 send_sig(SIGTRAP, current, 1);
450 current->thread.trap_no = trapno;
451 current->thread.error_code = error_code;
452 return 0;
453}
454
455void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
456{
457 unsigned char *csp, *ssp;
458 unsigned long ip, sp;
459
460#define CHECK_IF_IN_TRAP \
461 if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
462 pushw(ssp,sp,popw(ssp,sp) | TF_MASK);
463#define VM86_FAULT_RETURN \
464 if (VMPI.force_return_for_pic && (VEFLAGS & (IF_MASK | VIF_MASK))) \
465 return_to_32bit(regs, VM86_PICRETURN); \
466 return;
467
468 csp = (unsigned char *) (regs->cs << 4);
469 ssp = (unsigned char *) (regs->ss << 4);
470 sp = SP(regs);
471 ip = IP(regs);
472
473 switch (popb(csp, ip)) {
474
475
476 case 0x66:
477 switch (popb(csp, ip)) {
478
479
480 case 0x9c:
481 SP(regs) -= 4;
482 IP(regs) += 2;
483 pushl(ssp, sp, get_vflags(regs));
484 VM86_FAULT_RETURN;
485
486
487 case 0x9d:
488 SP(regs) += 4;
489 IP(regs) += 2;
490 CHECK_IF_IN_TRAP
491 set_vflags_long(popl(ssp, sp), regs);
492 VM86_FAULT_RETURN;
493
494
495 case 0xcf:
496 SP(regs) += 12;
497 IP(regs) = (unsigned short)popl(ssp, sp);
498 regs->cs = (unsigned short)popl(ssp, sp);
499 CHECK_IF_IN_TRAP
500 set_vflags_long(popl(ssp, sp), regs);
501 VM86_FAULT_RETURN;
502
503 default:
504 return_to_32bit(regs, VM86_UNKNOWN);
505 }
506
507
508 case 0x9c:
509 SP(regs) -= 2;
510 IP(regs)++;
511 pushw(ssp, sp, get_vflags(regs));
512 VM86_FAULT_RETURN;
513
514
515 case 0x9d:
516 SP(regs) += 2;
517 IP(regs)++;
518 CHECK_IF_IN_TRAP
519 set_vflags_short(popw(ssp, sp), regs);
520 VM86_FAULT_RETURN;
521
522
523 case 0xcd: {
524 int intno=popb(csp, ip);
525 IP(regs) += 2;
526 if (VMPI.vm86dbg_active) {
527 if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] )
528 return_to_32bit(regs, VM86_INTx + (intno << 8));
529 }
530 do_int(regs, intno, ssp, sp);
531 return;
532 }
533
534
535 case 0xcf:
536 SP(regs) += 6;
537 IP(regs) = popw(ssp, sp);
538 regs->cs = popw(ssp, sp);
539 CHECK_IF_IN_TRAP
540 set_vflags_short(popw(ssp, sp), regs);
541 VM86_FAULT_RETURN;
542
543
544 case 0xfa:
545 IP(regs)++;
546 clear_IF(regs);
547 VM86_FAULT_RETURN;
548
549
550
551
552
553
554
555
556 case 0xfb:
557 IP(regs)++;
558 set_IF(regs);
559 VM86_FAULT_RETURN;
560
561 default:
562 return_to_32bit(regs, VM86_UNKNOWN);
563 }
564}
565
566
567
568#define VM86_IRQNAME "vm86irq"
569
570static struct vm86_irqs {
571 struct task_struct *tsk;
572 int sig;
573} vm86_irqs[16];
574
575static spinlock_t irqbits_lock = SPIN_LOCK_UNLOCKED;
576static int irqbits;
577
578#define ALLOWED_SIGS ( 1 \
579 | (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO) | (1 << SIGURG) \
580 | (1 << SIGUNUSED) )
581
582static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
583 int irq_bit;
584 unsigned long flags;
585
586 spin_lock_irqsave(&irqbits_lock, flags);
587 irq_bit = 1 << intno;
588 if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
589 goto out;
590 irqbits |= irq_bit;
591 if (vm86_irqs[intno].sig)
592 send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
593
594out:
595 spin_unlock_irqrestore(&irqbits_lock, flags);
596}
597
598static inline void free_vm86_irq(int irqnumber)
599{
600 unsigned long flags;
601
602 free_irq(irqnumber,0);
603 vm86_irqs[irqnumber].tsk = 0;
604
605 spin_lock_irqsave(&irqbits_lock, flags);
606 irqbits &= ~(1 << irqnumber);
607 spin_unlock_irqrestore(&irqbits_lock, flags);
608}
609
610static inline int task_valid(struct task_struct *tsk)
611{
612 struct task_struct *p;
613 int ret = 0;
614
615 read_lock(&tasklist_lock);
616 for_each_task(p) {
617 if ((p == tsk) && (p->sig)) {
618 ret = 1;
619 break;
620 }
621 }
622 read_unlock(&tasklist_lock);
623 return ret;
624}
625
626static inline void handle_irq_zombies(void)
627{
628 int i;
629 for (i=3; i<16; i++) {
630 if (vm86_irqs[i].tsk) {
631 if (task_valid(vm86_irqs[i].tsk)) continue;
632 free_vm86_irq(i);
633 }
634 }
635}
636
637static inline int get_and_reset_irq(int irqnumber)
638{
639 int bit;
640 unsigned long flags;
641
642 if ( (irqnumber<3) || (irqnumber>15) ) return 0;
643 if (vm86_irqs[irqnumber].tsk != current) return 0;
644 spin_lock_irqsave(&irqbits_lock, flags);
645 bit = irqbits & (1 << irqnumber);
646 irqbits &= ~bit;
647 spin_unlock_irqrestore(&irqbits_lock, flags);
648 return bit;
649}
650
651
652static int do_vm86_irq_handling(int subfunction, int irqnumber)
653{
654 int ret;
655 switch (subfunction) {
656 case VM86_GET_AND_RESET_IRQ: {
657 return get_and_reset_irq(irqnumber);
658 }
659 case VM86_GET_IRQ_BITS: {
660 return irqbits;
661 }
662 case VM86_REQUEST_IRQ: {
663 int sig = irqnumber >> 8;
664 int irq = irqnumber & 255;
665 handle_irq_zombies();
666 if (!capable(CAP_SYS_ADMIN)) return -EPERM;
667 if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM;
668 if ( (irq<3) || (irq>15) ) return -EPERM;
669 if (vm86_irqs[irq].tsk) return -EPERM;
670 ret = request_irq(irq, &irq_handler, 0, VM86_IRQNAME, 0);
671 if (ret) return ret;
672 vm86_irqs[irq].sig = sig;
673 vm86_irqs[irq].tsk = current;
674 return irq;
675 }
676 case VM86_FREE_IRQ: {
677 handle_irq_zombies();
678 if ( (irqnumber<3) || (irqnumber>15) ) return -EPERM;
679 if (!vm86_irqs[irqnumber].tsk) return 0;
680 if (vm86_irqs[irqnumber].tsk != current) return -EPERM;
681 free_vm86_irq(irqnumber);
682 return 0;
683 }
684 }
685 return -EINVAL;
686}
687
688