📄 vm86.c
字号:
: "r" (base), "q" (val), "0" (ptr))#define pushl(base, ptr, val) \__asm__ __volatile__( \ "decw %w0\n\t" \ "rorl $16,%2\n\t" \ "movb %h2,0(%1,%0)\n\t" \ "decw %w0\n\t" \ "movb %b2,0(%1,%0)\n\t" \ "decw %w0\n\t" \ "rorl $16,%2\n\t" \ "movb %h2,0(%1,%0)\n\t" \ "decw %w0\n\t" \ "movb %b2,0(%1,%0)" \ : "=r" (ptr) \ : "r" (base), "q" (val), "0" (ptr))#define popb(base, ptr) \({ unsigned long __res; \__asm__ __volatile__( \ "movb 0(%1,%0),%b2\n\t" \ "incw %w0" \ : "=r" (ptr), "=r" (base), "=q" (__res) \ : "0" (ptr), "1" (base), "2" (0)); \__res; })#define popw(base, ptr) \({ unsigned long __res; \__asm__ __volatile__( \ "movb 0(%1,%0),%b2\n\t" \ "incw %w0\n\t" \ "movb 0(%1,%0),%h2\n\t" \ "incw %w0" \ : "=r" (ptr), "=r" (base), "=q" (__res) \ : "0" (ptr), "1" (base), "2" (0)); \__res; })#define popl(base, ptr) \({ unsigned long __res; \__asm__ __volatile__( \ "movb 0(%1,%0),%b2\n\t" \ "incw %w0\n\t" \ "movb 0(%1,%0),%h2\n\t" \ "incw %w0\n\t" \ "rorl $16,%2\n\t" \ "movb 0(%1,%0),%b2\n\t" \ "incw %w0\n\t" \ "movb 0(%1,%0),%h2\n\t" \ "incw %w0\n\t" \ "rorl $16,%2" \ : "=r" (ptr), "=r" (base), "=q" (__res) \ : "0" (ptr), "1" (base)); \__res; })static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp){ unsigned long *intr_ptr, segoffs; if (regs->cs == BIOSSEG) goto cannot_handle; if (is_revectored(i, &KVM86->int_revectored)) goto cannot_handle; if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored)) goto cannot_handle; intr_ptr = (unsigned long *) (i << 2); if (get_user(segoffs, intr_ptr)) goto cannot_handle; if ((segoffs >> 16) == BIOSSEG) goto cannot_handle; pushw(ssp, sp, get_vflags(regs)); pushw(ssp, sp, regs->cs); pushw(ssp, sp, IP(regs)); regs->cs = segoffs >> 16; SP(regs) -= 6; IP(regs) = segoffs & 0xffff; clear_TF(regs); clear_IF(regs); return;cannot_handle: return_to_32bit(regs, VM86_INTx + (i << 8));}int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno){ if (VMPI.is_vm86pus) { if ( (trapno==3) || (trapno==1) ) return_to_32bit(regs, VM86_TRAP + (trapno << 8)); do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs)); return 0; } if (trapno !=1) return 1; /* we let this handle by the calling routine */ if (current->ptrace & PT_PTRACED) { unsigned long flags; spin_lock_irqsave(¤t->sigmask_lock, flags); sigdelset(¤t->blocked, SIGTRAP); recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); } send_sig(SIGTRAP, current, 1); current->thread.trap_no = trapno; current->thread.error_code = error_code; return 0;}void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code){ unsigned char *csp, *ssp; unsigned long ip, sp;#define CHECK_IF_IN_TRAP \ if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \ pushw(ssp,sp,popw(ssp,sp) | TF_MASK);#define VM86_FAULT_RETURN \ if (VMPI.force_return_for_pic && (VEFLAGS & (IF_MASK | VIF_MASK))) \ return_to_32bit(regs, VM86_PICRETURN); \ return; csp = (unsigned char *) (regs->cs << 4); ssp = (unsigned char *) (regs->ss << 4); sp = SP(regs); ip = IP(regs); switch (popb(csp, ip)) { /* operand size override */ case 0x66: switch (popb(csp, ip)) { /* pushfd */ case 0x9c: SP(regs) -= 4; IP(regs) += 2; pushl(ssp, sp, get_vflags(regs)); VM86_FAULT_RETURN; /* popfd */ case 0x9d: SP(regs) += 4; IP(regs) += 2; CHECK_IF_IN_TRAP set_vflags_long(popl(ssp, sp), regs); VM86_FAULT_RETURN; /* iretd */ case 0xcf: SP(regs) += 12; IP(regs) = (unsigned short)popl(ssp, sp); regs->cs = (unsigned short)popl(ssp, sp); CHECK_IF_IN_TRAP set_vflags_long(popl(ssp, sp), regs); VM86_FAULT_RETURN; /* need this to avoid a fallthrough */ default: return_to_32bit(regs, VM86_UNKNOWN); } /* pushf */ case 0x9c: SP(regs) -= 2; IP(regs)++; pushw(ssp, sp, get_vflags(regs)); VM86_FAULT_RETURN; /* popf */ case 0x9d: SP(regs) += 2; IP(regs)++; CHECK_IF_IN_TRAP set_vflags_short(popw(ssp, sp), regs); VM86_FAULT_RETURN; /* int xx */ case 0xcd: { int intno=popb(csp, ip); IP(regs) += 2; if (VMPI.vm86dbg_active) { if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] ) return_to_32bit(regs, VM86_INTx + (intno << 8)); } do_int(regs, intno, ssp, sp); return; } /* iret */ case 0xcf: SP(regs) += 6; IP(regs) = popw(ssp, sp); regs->cs = popw(ssp, sp); CHECK_IF_IN_TRAP set_vflags_short(popw(ssp, sp), regs); VM86_FAULT_RETURN; /* cli */ case 0xfa: IP(regs)++; clear_IF(regs); VM86_FAULT_RETURN; /* sti */ /* * Damn. This is incorrect: the 'sti' instruction should actually * enable interrupts after the /next/ instruction. Not good. * * Probably needs some horsing around with the TF flag. Aiee.. */ case 0xfb: IP(regs)++; set_IF(regs); VM86_FAULT_RETURN; default: return_to_32bit(regs, VM86_UNKNOWN); }}/* ---------------- vm86 special IRQ passing stuff ----------------- */#define VM86_IRQNAME "vm86irq"static struct vm86_irqs { struct task_struct *tsk; int sig;} vm86_irqs[16];static int irqbits;#define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \ | (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO) | (1 << SIGURG) \ | (1 << SIGUNUSED) ) static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) { int irq_bit; unsigned long flags; save_flags(flags); cli(); irq_bit = 1 << intno; if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk) goto out; irqbits |= irq_bit; if (vm86_irqs[intno].sig) send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1); /* else user will poll for IRQs */out: restore_flags(flags);}static inline void free_vm86_irq(int irqnumber){ free_irq(irqnumber,0); vm86_irqs[irqnumber].tsk = 0; irqbits &= ~(1 << irqnumber);}static inline int task_valid(struct task_struct *tsk){ struct task_struct *p; int ret = 0; read_lock(&tasklist_lock); for_each_task(p) { if ((p == tsk) && (p->sig)) { ret = 1; break; } } read_unlock(&tasklist_lock); return ret;}void release_x86_irqs(struct task_struct *task){ int i; for (i=3; i<16; i++) if (vm86_irqs[i].tsk == task) free_vm86_irq(i);}static inline void handle_irq_zombies(void){ int i; for (i=3; i<16; i++) { if (vm86_irqs[i].tsk) { if (task_valid(vm86_irqs[i].tsk)) continue; free_vm86_irq(i); } }}static inline int get_and_reset_irq(int irqnumber){ int bit; unsigned long flags; if ( (irqnumber<3) || (irqnumber>15) ) return 0; if (vm86_irqs[irqnumber].tsk != current) return 0; save_flags(flags); cli(); bit = irqbits & (1 << irqnumber); irqbits &= ~bit; restore_flags(flags); return bit;}static int do_vm86_irq_handling(int subfunction, int irqnumber){ int ret; switch (subfunction) { case VM86_GET_AND_RESET_IRQ: { return get_and_reset_irq(irqnumber); } case VM86_GET_IRQ_BITS: { return irqbits; } case VM86_REQUEST_IRQ: { int sig = irqnumber >> 8; int irq = irqnumber & 255; handle_irq_zombies(); if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM; if ( (irq<3) || (irq>15) ) return -EPERM; if (vm86_irqs[irq].tsk) return -EPERM; ret = request_irq(irq, &irq_handler, 0, VM86_IRQNAME, 0); if (ret) return ret; vm86_irqs[irq].sig = sig; vm86_irqs[irq].tsk = current; return irq; } case VM86_FREE_IRQ: { handle_irq_zombies(); if ( (irqnumber<3) || (irqnumber>15) ) return -EPERM; if (!vm86_irqs[irqnumber].tsk) return 0; if (vm86_irqs[irqnumber].tsk != current) return -EPERM; free_vm86_irq(irqnumber); return 0; } } return -EINVAL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -