vm86.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:20k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/kernel/vm86.c
  3.  *
  4.  *  Copyright (C) 1994  Linus Torvalds
  5.  *
  6.  *  29 dec 2001 - Fixed oopses caused by unchecked access to the vm86
  7.  *                stack - Manfred Spraul <manfreds@colorfullife.com>
  8.  *
  9.  *  22 mar 2002 - Manfred detected the stackfaults, but didn't handle
  10.  *                them correctly. Now the emulation will be in a
  11.  *                consistent state after stackfaults - Kasper Dupont
  12.  *                <kasperd@daimi.au.dk>
  13.  *
  14.  *  22 mar 2002 - Added missing clear_IF in set_vflags_* Kasper Dupont
  15.  *                <kasperd@daimi.au.dk>
  16.  *
  17.  *  ?? ??? 2002 - Fixed premature returns from handle_vm86_fault
  18.  *                caused by Kasper Dupont's changes - Stas Sergeev
  19.  *
  20.  *   4 apr 2002 - Fixed CHECK_IF_IN_TRAP broken by Stas' changes.
  21.  *                Kasper Dupont <kasperd@daimi.au.dk>
  22.  *
  23.  *   9 apr 2002 - Changed syntax of macros in handle_vm86_fault.
  24.  *                Kasper Dupont <kasperd@daimi.au.dk>
  25.  *
  26.  *   9 apr 2002 - Changed stack access macros to jump to a label
  27.  *                instead of returning to userspace. This simplifies
  28.  *                do_int, and is needed by handle_vm6_fault. Kasper
  29.  *                Dupont <kasperd@daimi.au.dk>
  30.  *   
  31.  */
  32. #include <linux/errno.h>
  33. #include <linux/sched.h>
  34. #include <linux/kernel.h>
  35. #include <linux/signal.h>
  36. #include <linux/string.h>
  37. #include <linux/ptrace.h>
  38. #include <linux/mm.h>
  39. #include <linux/smp.h>
  40. #include <linux/smp_lock.h>
  41. #include <asm/uaccess.h>
  42. #include <asm/pgalloc.h>
  43. #include <asm/io.h>
  44. #include <asm/irq.h>
  45. /*
  46.  * Known problems:
  47.  *
  48.  * Interrupt handling is not guaranteed:
  49.  * - a real x86 will disable all interrupts for one instruction
  50.  *   after a "mov ss,xx" to make stack handling atomic even without
  51.  *   the 'lss' instruction. We can't guarantee this in v86 mode,
  52.  *   as the next instruction might result in a page fault or similar.
  53.  * - a real x86 will have interrupts disabled for one instruction
  54.  *   past the 'sti' that enables them. We don't bother with all the
  55.  *   details yet.
  56.  *
  57.  * Let's hope these problems do not actually matter for anything.
  58.  */
  59. #define KVM86 ((struct kernel_vm86_struct *)regs)
  60. #define VMPI  KVM86->vm86plus
  61. /*
  62.  * 8- and 16-bit register defines..
  63.  */
  64. #define AL(regs) (((unsigned char *)&((regs)->eax))[0])
  65. #define AH(regs) (((unsigned char *)&((regs)->eax))[1])
  66. #define IP(regs) (*(unsigned short *)&((regs)->eip))
  67. #define SP(regs) (*(unsigned short *)&((regs)->esp))
  68. /*
  69.  * virtual flags (16 and 32-bit versions)
  70.  */
  71. #define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
  72. #define VEFLAGS (current->thread.v86flags)
  73. #define set_flags(X,new,mask) 
  74. ((X) = ((X) & ~(mask)) | ((new) & (mask)))
  75. #define SAFE_MASK (0xDD5)
  76. #define RETURN_MASK (0xDFF)
  77. #define VM86_REGS_PART2 orig_eax
  78. #define VM86_REGS_SIZE1 
  79.         ( (unsigned)( & (((struct kernel_vm86_regs *)0)->VM86_REGS_PART2) ) )
  80. #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1)
  81. struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
  82. struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
  83. {
  84. struct tss_struct *tss;
  85. struct pt_regs *ret;
  86. unsigned long tmp;
  87. if (!current->thread.vm86_info) {
  88. printk("no vm86_info: BADn");
  89. do_exit(SIGSEGV);
  90. }
  91. set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);
  92. tmp = copy_to_user(&current->thread.vm86_info->regs,regs, VM86_REGS_SIZE1);
  93. tmp += copy_to_user(&current->thread.vm86_info->regs.VM86_REGS_PART2,
  94. &regs->VM86_REGS_PART2, VM86_REGS_SIZE2);
  95. tmp += put_user(current->thread.screen_bitmap,&current->thread.vm86_info->screen_bitmap);
  96. if (tmp) {
  97. printk("vm86: could not access userspace vm86_infon");
  98. do_exit(SIGSEGV);
  99. }
  100. tss = init_tss + smp_processor_id();
  101. tss->esp0 = current->thread.esp0 = current->thread.saved_esp0;
  102. current->thread.saved_esp0 = 0;
  103. ret = KVM86->regs32;
  104. return ret;
  105. }
  106. static void mark_screen_rdonly(struct task_struct * tsk)
  107. {
  108. pgd_t *pgd;
  109. pmd_t *pmd;
  110. pte_t *pte;
  111. int i;
  112. spin_lock(&tsk->mm->page_table_lock);
  113. pgd = pgd_offset(tsk->mm, 0xA0000);
  114. if (pgd_none(*pgd))
  115. goto out;
  116. if (pgd_bad(*pgd)) {
  117. pgd_ERROR(*pgd);
  118. pgd_clear(pgd);
  119. goto out;
  120. }
  121. pmd = pmd_offset(pgd, 0xA0000);
  122. if (pmd_none(*pmd))
  123. goto out;
  124. if (pmd_bad(*pmd)) {
  125. pmd_ERROR(*pmd);
  126. pmd_clear(pmd);
  127. goto out;
  128. }
  129. pte = pte_offset(pmd, 0xA0000);
  130. for (i = 0; i < 32; i++) {
  131. if (pte_present(*pte))
  132. set_pte(pte, pte_wrprotect(*pte));
  133. pte++;
  134. }
  135. out:
  136. spin_unlock(&tsk->mm->page_table_lock);
  137. flush_tlb();
  138. }
  139. static int do_vm86_irq_handling(int subfunction, int irqnumber);
  140. static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
  141. asmlinkage int sys_vm86old(struct vm86_struct * v86)
  142. {
  143. struct kernel_vm86_struct info; /* declare this _on top_,
  144.  * this avoids wasting of stack space.
  145.  * This remains on the stack until we
  146.  * return to 32 bit user space.
  147.  */
  148. struct task_struct *tsk;
  149. int tmp, ret = -EPERM;
  150. tsk = current;
  151. if (tsk->thread.saved_esp0)
  152. goto out;
  153. tmp  = copy_from_user(&info, v86, VM86_REGS_SIZE1);
  154. tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
  155. (long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2);
  156. ret = -EFAULT;
  157. if (tmp)
  158. goto out;
  159. memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
  160. info.regs32 = (struct pt_regs *) &v86;
  161. tsk->thread.vm86_info = v86;
  162. do_sys_vm86(&info, tsk);
  163. ret = 0; /* we never return here */
  164. out:
  165. return ret;
  166. }
  167. asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86)
  168. {
  169. struct kernel_vm86_struct info; /* declare this _on top_,
  170.  * this avoids wasting of stack space.
  171.  * This remains on the stack until we
  172.  * return to 32 bit user space.
  173.  */
  174. struct task_struct *tsk;
  175. int tmp, ret;
  176. tsk = current;
  177. switch (subfunction) {
  178. case VM86_REQUEST_IRQ:
  179. case VM86_FREE_IRQ:
  180. case VM86_GET_IRQ_BITS:
  181. case VM86_GET_AND_RESET_IRQ:
  182. ret = do_vm86_irq_handling(subfunction,(int)v86);
  183. goto out;
  184. case VM86_PLUS_INSTALL_CHECK:
  185. /* NOTE: on old vm86 stuff this will return the error
  186.    from verify_area(), because the subfunction is
  187.    interpreted as (invalid) address to vm86_struct.
  188.    So the installation check works.
  189.  */
  190. ret = 0;
  191. goto out;
  192. }
  193. /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
  194. ret = -EPERM;
  195. if (tsk->thread.saved_esp0)
  196. goto out;
  197. tmp  = copy_from_user(&info, v86, VM86_REGS_SIZE1);
  198. tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
  199. (long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2);
  200. ret = -EFAULT;
  201. if (tmp)
  202. goto out;
  203. info.regs32 = (struct pt_regs *) &subfunction;
  204. info.vm86plus.is_vm86pus = 1;
  205. tsk->thread.vm86_info = (struct vm86_struct *)v86;
  206. do_sys_vm86(&info, tsk);
  207. ret = 0; /* we never return here */
  208. out:
  209. return ret;
  210. }
  211. static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
  212. {
  213. struct tss_struct *tss;
  214. /*
  215.  * make sure the vm86() system call doesn't try to do anything silly
  216.  */
  217. info->regs.__null_ds = 0;
  218. info->regs.__null_es = 0;
  219. /* we are clearing fs,gs later just before "jmp ret_from_sys_call",
  220.  * because starting with Linux 2.1.x they aren't no longer saved/restored
  221.  */
  222. /*
  223.  * The eflags register is also special: we cannot trust that the user
  224.  * has set it up safely, so this makes sure interrupt etc flags are
  225.  * inherited from protected mode.
  226.  */
  227.   VEFLAGS = info->regs.eflags;
  228. info->regs.eflags &= SAFE_MASK;
  229. info->regs.eflags |= info->regs32->eflags & ~SAFE_MASK;
  230. info->regs.eflags |= VM_MASK;
  231. switch (info->cpu_type) {
  232. case CPU_286:
  233. tsk->thread.v86mask = 0;
  234. break;
  235. case CPU_386:
  236. tsk->thread.v86mask = NT_MASK | IOPL_MASK;
  237. break;
  238. case CPU_486:
  239. tsk->thread.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
  240. break;
  241. default:
  242. tsk->thread.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
  243. break;
  244. }
  245. /*
  246.  * Save old state, set default return value (%eax) to 0
  247.  */
  248. info->regs32->eax = 0;
  249. tsk->thread.saved_esp0 = tsk->thread.esp0;
  250. tss = init_tss + smp_processor_id();
  251. tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
  252. tsk->thread.screen_bitmap = info->screen_bitmap;
  253. if (info->flags & VM86_SCREEN_BITMAP)
  254. mark_screen_rdonly(tsk);
  255. __asm__ __volatile__(
  256. "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gsnt"
  257. "movl %0,%%espnt"
  258. "jmp ret_from_sys_call"
  259. : /* no outputs */
  260. :"r" (&info->regs), "b" (tsk) : "ax");
  261. /* we never return here */
  262. }
  263. static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
  264. {
  265. struct pt_regs * regs32;
  266. regs32 = save_v86_state(regs16);
  267. regs32->eax = retval;
  268. __asm__ __volatile__("movl %0,%%espnt"
  269. "jmp ret_from_sys_call"
  270. : : "r" (regs32), "b" (current));
  271. }
  272. static inline void set_IF(struct kernel_vm86_regs * regs)
  273. {
  274. VEFLAGS |= VIF_MASK;
  275. if (VEFLAGS & VIP_MASK)
  276. return_to_32bit(regs, VM86_STI);
  277. }
  278. static inline void clear_IF(struct kernel_vm86_regs * regs)
  279. {
  280. VEFLAGS &= ~VIF_MASK;
  281. }
  282. static inline void clear_TF(struct kernel_vm86_regs * regs)
  283. {
  284. regs->eflags &= ~TF_MASK;
  285. }
  286. static inline void clear_AC(struct kernel_vm86_regs * regs)
  287. {
  288. regs->eflags &= ~AC_MASK;
  289. }
  290. /* It is correct to call set_IF(regs) from the set_vflags_*
  291.  * functions. However someone forgot to call clear_IF(regs)
  292.  * in the opposite case.
  293.  * After the command sequence CLI PUSHF STI POPF you should
  294.  * end up with interrups disabled, but you ended up with
  295.  * interrupts enabled.
  296.  *  ( I was testing my own changes, but the only bug I
  297.  *    could find was in a function I had not changed. )
  298.  * [KD]
  299.  */
  300. static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs)
  301. {
  302. set_flags(VEFLAGS, eflags, current->thread.v86mask);
  303. set_flags(regs->eflags, eflags, SAFE_MASK);
  304. if (eflags & IF_MASK)
  305. set_IF(regs);
  306. else
  307. clear_IF(regs);
  308. }
  309. static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs)
  310. {
  311. set_flags(VFLAGS, flags, current->thread.v86mask);
  312. set_flags(regs->eflags, flags, SAFE_MASK);
  313. if (flags & IF_MASK)
  314. set_IF(regs);
  315. else
  316. clear_IF(regs);
  317. }
  318. static inline unsigned long get_vflags(struct kernel_vm86_regs * regs)
  319. {
  320. unsigned long flags = regs->eflags & RETURN_MASK;
  321. if (VEFLAGS & VIF_MASK)
  322. flags |= IF_MASK;
  323. return flags | (VEFLAGS & current->thread.v86mask);
  324. }
  325. static inline int is_revectored(int nr, struct revectored_struct * bitmap)
  326. {
  327. __asm__ __volatile__("btl %2,%1ntsbbl %0,%0"
  328. :"=r" (nr)
  329. :"m" (*bitmap),"r" (nr));
  330. return nr;
  331. }
  332. #define val_byte(val, n) (((__u8 *)&val)[n])
  333. #define pushb(base, ptr, val, err_label) 
  334. do { 
  335. __u8 __val = val; 
  336. ptr--; 
  337. if (put_user(__val, base + ptr) < 0) 
  338. goto err_label; 
  339. } while(0)
  340. #define pushw(base, ptr, val, err_label) 
  341. do { 
  342. __u16 __val = val; 
  343. ptr--; 
  344. if (put_user(val_byte(__val, 1), base + ptr) < 0) 
  345. goto err_label; 
  346. ptr--; 
  347. if (put_user(val_byte(__val, 0), base + ptr) < 0) 
  348. goto err_label; 
  349. } while(0)
  350. #define pushl(base, ptr, val, err_label) 
  351. do { 
  352. __u32 __val = val; 
  353. ptr--; 
  354. if (put_user(val_byte(__val, 3), base + ptr) < 0) 
  355. goto err_label; 
  356. ptr--; 
  357. if (put_user(val_byte(__val, 2), base + ptr) < 0) 
  358. goto err_label; 
  359. ptr--; 
  360. if (put_user(val_byte(__val, 1), base + ptr) < 0) 
  361. goto err_label; 
  362. ptr--; 
  363. if (put_user(val_byte(__val, 0), base + ptr) < 0) 
  364. goto err_label; 
  365. } while(0)
  366. #define popb(base, ptr, err_label) 
  367. ({ 
  368.   __u8 __res; 
  369. if (get_user(__res, base + ptr) < 0) 
  370. goto err_label; 
  371. ptr++; 
  372. __res; 
  373. })
  374. #define popw(base, ptr, err_label) 
  375. ({ 
  376.   __u16 __res; 
  377. if (get_user(val_byte(__res, 0), base + ptr) < 0) 
  378. goto err_label; 
  379. ptr++; 
  380. if (get_user(val_byte(__res, 1), base + ptr) < 0) 
  381. goto err_label; 
  382. ptr++; 
  383. __res; 
  384. })
  385. #define popl(base, ptr, err_label) 
  386. ({ 
  387.   __u32 __res; 
  388. if (get_user(val_byte(__res, 0), base + ptr) < 0) 
  389. goto err_label; 
  390. ptr++; 
  391. if (get_user(val_byte(__res, 1), base + ptr) < 0) 
  392. goto err_label; 
  393. ptr++; 
  394. if (get_user(val_byte(__res, 2), base + ptr) < 0) 
  395. goto err_label; 
  396. ptr++; 
  397. if (get_user(val_byte(__res, 3), base + ptr) < 0) 
  398. goto err_label; 
  399. ptr++; 
  400. __res; 
  401. })
  402. /* There are so many possible reasons for this function to return
  403.  * VM86_INTx, so adding another doesn't bother me. We can expect
  404.  * userspace programs to be able to handle it. (Getting a problem
  405.  * in userspace is always better than an Oops anyway.) [KD]
  406.  */
  407. static void do_int(struct kernel_vm86_regs *regs, int i,
  408.     unsigned char * ssp, unsigned short sp)
  409. {
  410. unsigned long *intr_ptr, segoffs;
  411. if (regs->cs == BIOSSEG)
  412. goto cannot_handle;
  413. if (is_revectored(i, &KVM86->int_revectored))
  414. goto cannot_handle;
  415. if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored))
  416. goto cannot_handle;
  417. intr_ptr = (unsigned long *) (i << 2);
  418. if (get_user(segoffs, intr_ptr))
  419. goto cannot_handle;
  420. if ((segoffs >> 16) == BIOSSEG)
  421. goto cannot_handle;
  422. pushw(ssp, sp, get_vflags(regs), cannot_handle);
  423. pushw(ssp, sp, regs->cs, cannot_handle);
  424. pushw(ssp, sp, IP(regs), cannot_handle);
  425. regs->cs = segoffs >> 16;
  426. SP(regs) -= 6;
  427. IP(regs) = segoffs & 0xffff;
  428. clear_TF(regs);
  429. clear_IF(regs);
  430. clear_AC(regs);
  431. return;
  432. cannot_handle:
  433. return_to_32bit(regs, VM86_INTx + (i << 8));
  434. }
  435. int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno)
  436. {
  437. if (VMPI.is_vm86pus) {
  438. if ( (trapno==3) || (trapno==1) )
  439. return_to_32bit(regs, VM86_TRAP + (trapno << 8));
  440. do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs));
  441. return 0;
  442. }
  443. if (trapno !=1)
  444. return 1; /* we let this handle by the calling routine */
  445. if (current->ptrace & PT_PTRACED) {
  446. unsigned long flags;
  447. spin_lock_irqsave(&current->sigmask_lock, flags);
  448. sigdelset(&current->blocked, SIGTRAP);
  449. recalc_sigpending(current);
  450. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  451. }
  452. send_sig(SIGTRAP, current, 1);
  453. current->thread.trap_no = trapno;
  454. current->thread.error_code = error_code;
  455. return 0;
  456. }
  457. void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
  458. {
  459. unsigned char *csp, *ssp, opcode;
  460. unsigned short ip, sp;
  461. int data32, pref_done;
  462. #define CHECK_IF_IN_TRAP 
  463. if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) 
  464. newflags |= TF_MASK
  465. #define VM86_FAULT_RETURN do { 
  466. if (VMPI.force_return_for_pic  && (VEFLAGS & (IF_MASK | VIF_MASK))) 
  467. return_to_32bit(regs, VM86_PICRETURN); 
  468. return; } while (0)
  469.                                    
  470. csp = (unsigned char *) (regs->cs << 4);
  471. ssp = (unsigned char *) (regs->ss << 4);
  472. sp = SP(regs);
  473. ip = IP(regs);
  474. data32 = 0;
  475. pref_done = 0;
  476. do {
  477. switch (opcode = popb(csp, ip, simulate_sigsegv)) {
  478. case 0x66:      /* 32-bit data */     data32=1; break;
  479. case 0x67:      /* 32-bit address */  break;
  480. case 0x2e:      /* CS */              break;
  481. case 0x3e:      /* DS */              break;
  482. case 0x26:      /* ES */              break;
  483. case 0x36:      /* SS */              break;
  484. case 0x65:      /* GS */              break;
  485. case 0x64:      /* FS */              break;
  486. case 0xf2:      /* repnz */       break;
  487. case 0xf3:      /* rep */             break;
  488. default: pref_done = 1;
  489. }
  490. } while (!pref_done);
  491. switch (opcode) {
  492. /* pushf */
  493. case 0x9c:
  494. if (data32) {
  495. pushl(ssp, sp, get_vflags(regs), simulate_sigsegv);
  496. SP(regs) -= 4;
  497. } else {
  498. pushw(ssp, sp, get_vflags(regs), simulate_sigsegv);
  499. SP(regs) -= 2;
  500. }
  501. IP(regs) = ip;
  502. VM86_FAULT_RETURN;
  503. /* popf */
  504. case 0x9d:
  505. {
  506. unsigned long newflags;
  507. if (data32) {
  508. newflags=popl(ssp, sp, simulate_sigsegv);
  509. SP(regs) += 4;
  510. } else {
  511. newflags = popw(ssp, sp, simulate_sigsegv);
  512. SP(regs) += 2;
  513. }
  514. IP(regs) = ip;
  515. CHECK_IF_IN_TRAP;
  516. if (data32) {
  517. set_vflags_long(newflags, regs);
  518. } else {
  519. set_vflags_short(newflags, regs);
  520. }
  521. VM86_FAULT_RETURN;
  522. }
  523. /* int xx */
  524. case 0xcd: {
  525.         int intno=popb(csp, ip, simulate_sigsegv);
  526. IP(regs) = ip;
  527. if (VMPI.vm86dbg_active) {
  528. if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] )
  529. return_to_32bit(regs, VM86_INTx + (intno << 8));
  530. }
  531. do_int(regs, intno, ssp, sp);
  532. return;
  533. }
  534. /* iret */
  535. case 0xcf:
  536. {
  537. unsigned long newip;
  538. unsigned long newcs;
  539. unsigned long newflags;
  540. if (data32) {
  541. newip=popl(ssp, sp, simulate_sigsegv);
  542. newcs=popl(ssp, sp, simulate_sigsegv);
  543. newflags=popl(ssp, sp, simulate_sigsegv);
  544. SP(regs) += 12;
  545. } else {
  546. newip = popw(ssp, sp, simulate_sigsegv);
  547. newcs = popw(ssp, sp, simulate_sigsegv);
  548. newflags = popw(ssp, sp, simulate_sigsegv);
  549. SP(regs) += 6;
  550. }
  551. IP(regs) = newip;
  552. regs->cs = newcs;
  553. CHECK_IF_IN_TRAP;
  554. if (data32) {
  555. set_vflags_long(newflags, regs);
  556. } else {
  557. set_vflags_short(newflags, regs);
  558. }
  559. VM86_FAULT_RETURN;
  560. }
  561. /* cli */
  562. case 0xfa:
  563. IP(regs) = ip;
  564. clear_IF(regs);
  565. VM86_FAULT_RETURN;
  566. /* sti */
  567. /*
  568.  * Damn. This is incorrect: the 'sti' instruction should actually
  569.  * enable interrupts after the /next/ instruction. Not good.
  570.  *
  571.  * Probably needs some horsing around with the TF flag. Aiee..
  572.  */
  573. case 0xfb:
  574. IP(regs) = ip;
  575. set_IF(regs);
  576. VM86_FAULT_RETURN;
  577. default:
  578. return_to_32bit(regs, VM86_UNKNOWN);
  579. }
  580. return;
  581. simulate_sigsegv:
  582. /* FIXME: After a long discussion with Stas we finally
  583.  *        agreed, that this is wrong. Here we should
  584.  *        really send a SIGSEGV to the user program.
  585.  *        But how do we create the correct context? We
  586.  *        are inside a general protection fault handler
  587.  *        and has just returned from a page fault handler.
  588.  *        The correct context for the signal handler
  589.  *        should be a mixture of the two, but how do we
  590.  *        get the information? [KD]
  591.  */
  592. return_to_32bit(regs, VM86_UNKNOWN);
  593. }
  594. /* ---------------- vm86 special IRQ passing stuff ----------------- */
  595. #define VM86_IRQNAME "vm86irq"
  596. static struct vm86_irqs {
  597. struct task_struct *tsk;
  598. int sig;
  599. } vm86_irqs[16];
  600. static int irqbits;
  601. #define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ 
  602. | (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO)  | (1 << SIGURG) 
  603. | (1 << SIGUNUSED) )
  604. static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
  605. int irq_bit;
  606. unsigned long flags;
  607. save_flags(flags);
  608. cli();
  609. irq_bit = 1 << intno;
  610. if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
  611. goto out;
  612. irqbits |= irq_bit;
  613. if (vm86_irqs[intno].sig)
  614. send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
  615. /* else user will poll for IRQs */
  616. out:
  617. restore_flags(flags);
  618. }
  619. static inline void free_vm86_irq(int irqnumber)
  620. {
  621. free_irq(irqnumber,0);
  622. vm86_irqs[irqnumber].tsk = 0;
  623. irqbits &= ~(1 << irqnumber);
  624. }
  625. static inline int task_valid(struct task_struct *tsk)
  626. {
  627. struct task_struct *p;
  628. int ret = 0;
  629. read_lock(&tasklist_lock);
  630. for_each_task(p) {
  631. if ((p == tsk) && (p->sig)) {
  632. ret = 1;
  633. break;
  634. }
  635. }
  636. read_unlock(&tasklist_lock);
  637. return ret;
  638. }
  639. void release_x86_irqs(struct task_struct *task)
  640. {
  641. int i;
  642. for (i=3; i<16; i++)
  643.     if (vm86_irqs[i].tsk == task)
  644. free_vm86_irq(i);
  645. }
  646. static inline void handle_irq_zombies(void)
  647. {
  648. int i;
  649. for (i=3; i<16; i++) {
  650. if (vm86_irqs[i].tsk) {
  651. if (task_valid(vm86_irqs[i].tsk)) continue;
  652. free_vm86_irq(i);
  653. }
  654. }
  655. }
  656. static inline int get_and_reset_irq(int irqnumber)
  657. {
  658. int bit;
  659. unsigned long flags;
  660. if ( (irqnumber<3) || (irqnumber>15) ) return 0;
  661. if (vm86_irqs[irqnumber].tsk != current) return 0;
  662. save_flags(flags);
  663. cli();
  664. bit = irqbits & (1 << irqnumber);
  665. irqbits &= ~bit;
  666. restore_flags(flags);
  667. return bit;
  668. }
  669. static int do_vm86_irq_handling(int subfunction, int irqnumber)
  670. {
  671. int ret;
  672. switch (subfunction) {
  673. case VM86_GET_AND_RESET_IRQ: {
  674. return get_and_reset_irq(irqnumber);
  675. }
  676. case VM86_GET_IRQ_BITS: {
  677. return irqbits;
  678. }
  679. case VM86_REQUEST_IRQ: {
  680. int sig = irqnumber >> 8;
  681. int irq = irqnumber & 255;
  682. handle_irq_zombies();
  683. if (!capable(CAP_SYS_ADMIN)) return -EPERM;
  684. if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM;
  685. if ( (irq<3) || (irq>15) ) return -EPERM;
  686. if (vm86_irqs[irq].tsk) return -EPERM;
  687. ret = request_irq(irq, &irq_handler, 0, VM86_IRQNAME, 0);
  688. if (ret) return ret;
  689. vm86_irqs[irq].sig = sig;
  690. vm86_irqs[irq].tsk = current;
  691. return irq;
  692. }
  693. case  VM86_FREE_IRQ: {
  694. handle_irq_zombies();
  695. if ( (irqnumber<3) || (irqnumber>15) ) return -EPERM;
  696. if (!vm86_irqs[irqnumber].tsk) return 0;
  697. if (vm86_irqs[irqnumber].tsk != current) return -EPERM;
  698. free_vm86_irq(irqnumber);
  699. return 0;
  700. }
  701. }
  702. return -EINVAL;
  703. }