VirtualBox

Changeset 59765 in vbox


Ignore:
Timestamp:
Feb 22, 2016 8:51:07 AM (9 years ago)
Author:
vboxsync
Message:

BIOS: 386 LOADALL emulation. Disabled by default.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/invop.c

    r56292 r59765  
    2020#include "biosint.h"
    2121#include "inlines.h"
     22
     23//#define EMU_386_LOADALL
    2224
    2325/* The layout of 286 LOADALL descriptors. */
     
    6365ct_assert(sizeof(ldall_286_s) == 0x66);
    6466
     67#ifdef EMU_386_LOADALL
     68
     69/* The layout of 386 LOADALL descriptors. */
     70typedef struct tag_ldal3_desc {
     71    uint32_t    attr;           /* Segment attributes. */
     72    uint32_t    base;           /* Expanded segment base. */
     73    uint32_t    limit;          /* Expanded segment limit. */
     74} ldal3_desc;
     75
     76/* The 386 LOADALL memory buffer pointed to by ES:EDI.
     77 */
     78typedef struct tag_ldall_386 {
     79    uint32_t    cr0;            /* 00h */
     80    uint32_t    eflags;         /* 04h */
     81    uint32_t    eip;            /* 08h */
     82    uint32_t    edi;            /* 0Ch */
     83    uint32_t    esi;            /* 10h */
     84    uint32_t    ebp;            /* 14h */
     85    uint32_t    esp;            /* 18h */
     86    uint32_t    ebx;            /* 1Ch */
     87    uint32_t    edx;            /* 20h */
     88    uint32_t    ecx;            /* 24h */
     89    uint32_t    eax;            /* 28h */
     90    uint32_t    dr6;            /* 2Ch */
     91    uint32_t    dr7;            /* 30h */
     92    uint32_t    tr;             /* 34h */
     93    uint32_t    ldt;            /* 38h */
     94    uint32_t    gs;             /* 3Ch */
     95    uint32_t    fs;             /* 40h */
     96    uint32_t    ds;             /* 44h */
     97    uint32_t    ss;             /* 4Ch */
     98    uint32_t    cs;             /* 48h */
     99    uint32_t    es;             /* 50h */
     100    ldal3_desc  tss_desc;       /* 54h */
     101    ldal3_desc  idt_desc;       /* 60h */
     102    ldal3_desc  gdt_desc;       /* 6Ch */
     103    ldal3_desc  ldt_desc;       /* 78h */
     104    ldal3_desc  gs_desc;        /* 84h */
     105    ldal3_desc  fs_desc;        /* 90h */
     106    ldal3_desc  ds_desc;        /* 9Ch */
     107    ldal3_desc  ss_desc;        /* A8h */
     108    ldal3_desc  cs_desc;        /* B4h */
     109    ldal3_desc  es_desc;        /* C0h */
     110} ldall_386_s;
     111ct_assert(sizeof(ldall_386_s) == 0xCC);
     112
     113#endif
     114
    65115/*
    66116 * LOADALL emulation assumptions:
     
    146196    parm nomemory modify nomemory aborts;
    147197
     198#ifdef EMU_386_LOADALL
     199
     200/* 386 version of the above. */
     201void ldal3_finish(void);
     202#pragma aux ldal3_finish =  \
     203    ".386"                  \
     204    "mov sp, 28h"           \
     205    "popad"                 \
     206    "mov sp, ss:[18h]"      \
     207    "sub sp, 6"             \
     208    "mov ss, ss:[48h]"      \
     209    "iret"                  \
     210    parm nomemory modify nomemory aborts;
     211
     212/* 386 version of load_rm_segs.
     213 * NB: Must not touch CX!
     214 */
     215void load_rm_seg3(int seg_flags, uint16_t ss_base);
     216#pragma aux load_rm_seg3 =  \
     217    "mov ss, ax"            \
     218    "mov ax, ss:[44h]"      \
     219    "mov ds, ax"            \
     220    "mov ax, ss:[50h]"      \
     221    "mov es, ax"            \
     222    parm [ax] [cx] nomemory modify nomemory;
     223
     224#endif
    148225
    149226#define LOAD_ES     0x01    /* ES needs to be loaded in protected mode. */
     
    213290        load_pm_segs();
    214291        ldall_finish();
     292#ifdef EMU_386_LOADALL
     293    } else if (*(uint16_t __far *)ins == 0x070F) {
     294        /* 386 LOADALL. NB: Same opcode as SYSRET. */
     295        ldall_386_s __far   *ldbuf = (void __far *)es :> gr.u.r16.di;   /* Assume 16-bit value in EDI. */
     296        ldall_286_s __far   *ldbuf2 = 0 :> 0x800;
     297        iret_addr_t __far   *ret_addr;
     298        uint32_t            seg_base;
     299        int                 seg_flags = 0;
     300
     301        /* NB: BIG FAT ASSUMPTION! Users of 386 LOADALL are assumed to also
     302         * have a 286 LOADALL buffer at physical address 800h. We use unused fields
     303         * in that buffer for temporary storage.
     304         */
     305
     306        /* Set up return stack. */
     307        ret_addr = ldbuf->ss :> (ldbuf->esp - sizeof(iret_addr_t));
     308        ret_addr->ip = ldbuf->eip;
     309        ret_addr->cs = ldbuf->cs;
     310        ret_addr->flags.u.r16.flags = ldbuf->eflags;
     311
     312        /* Examine ES/DS. */
     313        seg_base = ldbuf->es_desc.base;
     314        if (seg_base != (uint32_t)ldbuf->es << 4)
     315            seg_flags |= LOAD_ES;
     316        seg_base = ldbuf->ds_desc.base;
     317        if (seg_base != (uint32_t)ldbuf->ds << 4)
     318            seg_flags |= LOAD_DS;
     319
     320        /* The LOADALL buffer doubles as a tiny GDT. */
     321        load_gdtr(0x800, 4 * 8 - 1);
     322
     323        /* Store the ES base/limit/attributes in the unused words (GDT selector 8). */
     324        ldbuf2->unused2[0] = ldbuf->es_desc.limit;
     325        ldbuf2->unused2[1] = (uint16_t)ldbuf->es_desc.base;
     326        ldbuf2->unused2[2] = (ldbuf->es_desc.attr & 0xFF00) | (ldbuf->es_desc.base >> 16);
     327        ldbuf2->unused2[3] = 0;
     328
     329        /* Store the DS base/limit/attributes in other unused words. */
     330        ldbuf2->unused1[0] = ldbuf->ds_desc.limit;
     331        ldbuf2->unused1[1] = (uint16_t)ldbuf->ds_desc.base;
     332        ldbuf2->unused1[2] = (ldbuf->ds_desc.attr & 0xFF00) | (ldbuf->ds_desc.base >> 16);
     333
     334        /* Load the IDTR as specified. */
     335        seg_base = ldbuf->idt_desc.base;
     336        load_idtr(seg_base, ldbuf->idt_desc.limit);
     337
     338        /* Do the tricky bits now. */
     339        load_rm_seg3(es, seg_flags);
     340        load_pm_segs();
     341        ldal3_finish();
     342#endif
    215343    } else {
    216344        /* There isn't much point in executing the invalid opcode handler
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette