xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

linux_vm86.c (8868B)


      1 #ifdef HAVE_XORG_CONFIG_H
      2 #include <xorg-config.h>
      3 #endif
      4 
      5 #include <errno.h>
      6 #include <string.h>
      7 
      8 #include "xf86.h"
      9 #include "xf86_OSproc.h"
     10 #include "xf86Pci.h"
     11 #include "compiler.h"
     12 #define _INT10_PRIVATE
     13 #include "xf86int10.h"
     14 
     15 #define REG pInt
     16 
     17 #ifdef _VM86_LINUX
     18 #include "int10Defines.h"
     19 
     20 static int vm86_rep(struct vm86_struct *ptr);
     21 static struct vm86_struct vm86_s;
     22 
     23 Bool
     24 xf86Int10ExecSetup(xf86Int10InfoPtr pInt)
     25 {
     26 #define VM86S ((struct vm86_struct *)pInt->cpuRegs)
     27 
     28     pInt->cpuRegs = &vm86_s;
     29     VM86S->flags = 0;
     30     VM86S->screen_bitmap = 0;
     31     VM86S->cpu_type = CPU_586;
     32     memset(&VM86S->int_revectored, 0xff, sizeof(VM86S->int_revectored));
     33     memset(&VM86S->int21_revectored, 0xff, sizeof(VM86S->int21_revectored));
     34     return TRUE;
     35 }
     36 
     37 /* get the linear address */
     38 #define LIN_PREF_SI ((pref_seg << 4) + X86_SI)
     39 #define LWECX       ((prefix66 ^ prefix67) ? X86_ECX : X86_CX)
     40 #define LWECX_ZERO  {if (prefix66 ^ prefix67) X86_ECX = 0; else X86_CX = 0;}
     41 #define DF (1 << 10)
     42 
     43 /* vm86 fault handling */
     44 static Bool
     45 vm86_GP_fault(xf86Int10InfoPtr pInt)
     46 {
     47     unsigned char *csp, *lina;
     48     CARD32 org_eip;
     49     int pref_seg;
     50     int done, is_rep, prefix66, prefix67;
     51 
     52     csp = lina = SEG_ADR((unsigned char *), X86_CS, IP);
     53 
     54     is_rep = 0;
     55     prefix66 = prefix67 = 0;
     56     pref_seg = -1;
     57 
     58     /* eat up prefixes */
     59     done = 0;
     60     do {
     61         switch (MEM_RB(pInt, (int) csp++)) {
     62         case 0x66:             /* operand prefix */
     63             prefix66 = 1;
     64             break;
     65         case 0x67:             /* address prefix */
     66             prefix67 = 1;
     67             break;
     68         case 0x2e:             /* CS */
     69             pref_seg = X86_CS;
     70             break;
     71         case 0x3e:             /* DS */
     72             pref_seg = X86_DS;
     73             break;
     74         case 0x26:             /* ES */
     75             pref_seg = X86_ES;
     76             break;
     77         case 0x36:             /* SS */
     78             pref_seg = X86_SS;
     79             break;
     80         case 0x65:             /* GS */
     81             pref_seg = X86_GS;
     82             break;
     83         case 0x64:             /* FS */
     84             pref_seg = X86_FS;
     85             break;
     86         case 0xf0:             /* lock */
     87             break;
     88         case 0xf2:             /* repnz */
     89         case 0xf3:             /* rep */
     90             is_rep = 1;
     91             break;
     92         default:
     93             done = 1;
     94         }
     95     } while (!done);
     96     csp--;                      /* oops one too many */
     97     org_eip = X86_EIP;
     98     X86_IP += (csp - lina);
     99 
    100     switch (MEM_RB(pInt, (int) csp)) {
    101     case 0x6c:                 /* insb */
    102         /* NOTE: ES can't be overwritten; prefixes 66,67 should use esi,edi,ecx
    103          * but is anyone using extended regs in real mode? */
    104         /* WARNING: no test for DI wrapping! */
    105         X86_EDI += port_rep_inb(pInt, X86_DX, SEG_EADR((CARD32), X86_ES, DI),
    106                                 X86_FLAGS & DF, is_rep ? LWECX : 1);
    107         if (is_rep)
    108             LWECX_ZERO;
    109         X86_IP++;
    110         break;
    111 
    112     case 0x6d:                 /* (rep) insw / insd */
    113         /* NOTE: ES can't be overwritten */
    114         /* WARNING: no test for _DI wrapping! */
    115         if (prefix66) {
    116             X86_DI += port_rep_inl(pInt, X86_DX, SEG_ADR((CARD32), X86_ES, DI),
    117                                    X86_EFLAGS & DF, is_rep ? LWECX : 1);
    118         }
    119         else {
    120             X86_DI += port_rep_inw(pInt, X86_DX, SEG_ADR((CARD32), X86_ES, DI),
    121                                    X86_FLAGS & DF, is_rep ? LWECX : 1);
    122         }
    123         if (is_rep)
    124             LWECX_ZERO;
    125         X86_IP++;
    126         break;
    127 
    128     case 0x6e:                 /* (rep) outsb */
    129         if (pref_seg < 0)
    130             pref_seg = X86_DS;
    131         /* WARNING: no test for _SI wrapping! */
    132         X86_SI += port_rep_outb(pInt, X86_DX, (CARD32) LIN_PREF_SI,
    133                                 X86_FLAGS & DF, is_rep ? LWECX : 1);
    134         if (is_rep)
    135             LWECX_ZERO;
    136         X86_IP++;
    137         break;
    138 
    139     case 0x6f:                 /* (rep) outsw / outsd */
    140         if (pref_seg < 0)
    141             pref_seg = X86_DS;
    142         /* WARNING: no test for _SI wrapping! */
    143         if (prefix66) {
    144             X86_SI += port_rep_outl(pInt, X86_DX, (CARD32) LIN_PREF_SI,
    145                                     X86_EFLAGS & DF, is_rep ? LWECX : 1);
    146         }
    147         else {
    148             X86_SI += port_rep_outw(pInt, X86_DX, (CARD32) LIN_PREF_SI,
    149                                     X86_FLAGS & DF, is_rep ? LWECX : 1);
    150         }
    151         if (is_rep)
    152             LWECX_ZERO;
    153         X86_IP++;
    154         break;
    155 
    156     case 0xe5:                 /* inw xx, inl xx */
    157         if (prefix66)
    158             X86_EAX = x_inl(csp[1]);
    159         else
    160             X86_AX = x_inw(csp[1]);
    161         X86_IP += 2;
    162         break;
    163 
    164     case 0xe4:                 /* inb xx */
    165         X86_AL = x_inb(csp[1]);
    166         X86_IP += 2;
    167         break;
    168 
    169     case 0xed:                 /* inw dx, inl dx */
    170         if (prefix66)
    171             X86_EAX = x_inl(X86_DX);
    172         else
    173             X86_AX = x_inw(X86_DX);
    174         X86_IP += 1;
    175         break;
    176 
    177     case 0xec:                 /* inb dx */
    178         X86_AL = x_inb(X86_DX);
    179         X86_IP += 1;
    180         break;
    181 
    182     case 0xe7:                 /* outw xx */
    183         if (prefix66)
    184             x_outl(csp[1], X86_EAX);
    185         else
    186             x_outw(csp[1], X86_AX);
    187         X86_IP += 2;
    188         break;
    189 
    190     case 0xe6:                 /* outb xx */
    191         x_outb(csp[1], X86_AL);
    192         X86_IP += 2;
    193         break;
    194 
    195     case 0xef:                 /* outw dx */
    196         if (prefix66)
    197             x_outl(X86_DX, X86_EAX);
    198         else
    199             x_outw(X86_DX, X86_AX);
    200         X86_IP += 1;
    201         break;
    202 
    203     case 0xee:                 /* outb dx */
    204         x_outb(X86_DX, X86_AL);
    205         X86_IP += 1;
    206         break;
    207 
    208     case 0xf4:
    209         DebugF("hlt at %p\n", lina);
    210         return FALSE;
    211 
    212     case 0x0f:
    213         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    214                    "CPU 0x0f Trap at CS:EIP=0x%4.4x:0x%8.8lx\n", X86_CS,
    215                    X86_EIP);
    216         goto op0ferr;
    217 
    218     default:
    219         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "unknown reason for exception\n");
    220 
    221  op0ferr:
    222         dump_registers(pInt);
    223         stack_trace(pInt);
    224         dump_code(pInt);
    225         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "cannot continue\n");
    226         return FALSE;
    227     }                           /* end of switch() */
    228     return TRUE;
    229 }
    230 
    231 static int
    232 do_vm86(xf86Int10InfoPtr pInt)
    233 {
    234     int retval;
    235 
    236     retval = vm86_rep(VM86S);
    237 
    238     switch (VM86_TYPE(retval)) {
    239     case VM86_UNKNOWN:
    240         if (!vm86_GP_fault(pInt))
    241             return 0;
    242         break;
    243     case VM86_STI:
    244         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "vm86_sti :-((\n");
    245         dump_registers(pInt);
    246         dump_code(pInt);
    247         stack_trace(pInt);
    248         return 0;
    249     case VM86_INTx:
    250         pInt->num = VM86_ARG(retval);
    251         if (!int_handler(pInt)) {
    252             xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    253                        "Unknown vm86_int: 0x%X\n\n", VM86_ARG(retval));
    254             dump_registers(pInt);
    255             dump_code(pInt);
    256             stack_trace(pInt);
    257             return 0;
    258         }
    259         /* I'm not sure yet what to do if we can handle ints */
    260         break;
    261     case VM86_SIGNAL:
    262         return 1;
    263         /*
    264          * we used to warn here and bail out - but now the sigio stuff
    265          * always fires signals at us. So we just ignore them for now.
    266          */
    267         xf86DrvMsg(pInt->pScrn->scrnIndex, X_WARNING, "received signal\n");
    268         return 0;
    269     default:
    270         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "unknown type(0x%x)=0x%x\n",
    271                    VM86_ARG(retval), VM86_TYPE(retval));
    272         dump_registers(pInt);
    273         dump_code(pInt);
    274         stack_trace(pInt);
    275         return 0;
    276     }
    277 
    278     return 1;
    279 }
    280 
    281 void
    282 xf86ExecX86int10(xf86Int10InfoPtr pInt)
    283 {
    284     int sig = setup_int(pInt);
    285 
    286     if (int_handler(pInt))
    287         while (do_vm86(pInt)) {
    288         };
    289 
    290     finish_int(pInt, sig);
    291 }
    292 
    293 static int
    294 vm86_rep(struct vm86_struct *ptr)
    295 {
    296     int __res;
    297 
    298 #ifdef __PIC__
    299     /* When compiling with -fPIC, we can't use asm constraint "b" because
    300        %ebx is already taken by gcc. */
    301     __asm__ __volatile__("pushl %%ebx\n\t"
    302                          "push %%gs\n\t"
    303                          "movl %2,%%ebx\n\t"
    304                          "movl %1,%%eax\n\t"
    305                          "int $0x80\n\t" "pop %%gs\n\t" "popl %%ebx":"=a"(__res)
    306                          :"n"((int) 113), "r"((struct vm86_struct *) ptr));
    307 #else
    308     __asm__ __volatile__("push %%gs\n\t"
    309                          "int $0x80\n\t"
    310                          "pop %%gs":"=a"(__res):"a"((int) 113),
    311                          "b"((struct vm86_struct *) ptr));
    312 #endif
    313 
    314     if (__res < 0) {
    315         errno = -__res;
    316         __res = -1;
    317     }
    318     else
    319         errno = 0;
    320     return __res;
    321 }
    322 
    323 #endif