home *** CD-ROM | disk | FTP | other *** search
- /* This is file PAGING.C */
- /*
- ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
- **
- ** This file is distributed under the terms listed in the document
- ** "copying.dj", available from DJ Delorie at the address above.
- ** A copy of "copying.dj" should accompany this file; if not, a copy
- ** should be available from where this file was obtained. This file
- ** may not be distributed without a verbatim copy of "copying.dj".
- **
- ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
- ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
- /* Modified for DPMI Implement by H.Tsubakimoto */
- /* NUR paging algorithm by rcharif@math.utexas.edu */
- /* Merged DPMI with V1.09+ code C. Sandmann sandmann@clio.rice.edu */
-
- #include <stdio.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <io.h>
- #include <sys/stat.h>
- #include <bios.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "gotypes.h"
- #include "paging.h"
- #include "graphics.h"
- #include "tss.h"
- #include "idt.h"
- #include "gdt.h"
- #include "valloc.h"
- #include "dalloc.h"
- #include "utils.h"
- #include "aout.h"
- #include "mono.h"
- #include "vcpi.h"
- #include "dpmi.h"
- #include "extdebug.h"
- #include "exphdlr.h"
- #include "stubinfo.h"
- #include "proginfo.h"
- #include "control.h"
-
- #define VERBOSE 0
-
- /* #define KEEP_ON_EXEC */
-
- #define MAX_PAGING_NUM 2
-
-
- #define DOS_PAGE 256 /* 1MB / 4KB = 256 Pages */
-
-
- extern char transfer_buffer[4096];
-
- extern word32 ptr2linear(void far *ptr);
-
- struct {
- word16 limit;
- word32 base;
- } gdt_phys, idt_phys;
-
- CLIENT client; /* VCPI Change Mode Structure */
- word32 abs_client; /* _DS * 16L + &client */
- far32 vcpi_entry;
- SYS_TBL int_descriptor;
- SYS_TBL gbl_descriptor;
-
- extern word16 vcpi_installed; /* VCPI Installed Flag */
- extern near protect_entry();
- word32 DPMI_STACK = 0x40000L; /* 256Kb Min */
- #define DPMIgetpage 0xffffL /* 64K instead of 4K for speed */
- DPMImemory DPMImem; /* protected memory block */
- static word32 oldbase; /* DPMI selector base for allocated memory */
- static word16 DPMIselect; /* selectors for application */
- /* DPMIselect + 0 : data selector */
- /* DPMIselect + 8 : code selector */
- /* DPMIselect + 16 : stack selector */
- /* DPMIselect + 24 : linear 1Mb range */
-
- extern TSS *utils_tss;
- extern int debug_mode;
- extern word32 mem_avail;
- extern int self_contained;
- extern long header_offset;
-
- word16 core_selector, arena_ds, arena_cs;
-
- AREAS areas[MAX_AREA];
- #if VERBOSE
- static char *aname[MAX_AREA] = {
- "text ",
- "data ",
- "bss ",
- "arena",
- "stack",
- "vga ",
- "syms ",
- "syms2",
- "emu"
- };
- #endif
- static char achar[MAX_AREA] = "tdbmsg?e";
-
- word32 far *pd = 0;
- word8 pd_seg[1024];
- word32 far *vcpi_pt = 0;
- word8 paging_buffer[4096*MAX_PAGING_NUM];
-
- word32 screen_primary, screen_secondary;
-
- word32 ptr2linear(void far *ptr)
- {
- return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
- }
-
- static word32 far2pte(void far *ptr, word32 flags)
- {
- return (vcpi_pt[(int)(((word32)ptr) >> 24)] & 0xfffff000L) | flags;
- }
-
- static word32 pn2pte(unsigned pn, word32 flags)
- {
- return (vcpi_pt[pn] & 0xfffff000L) | flags;
- }
-
- static void setDPMISelectors(int firsttime)
- {
- int selfail;
-
- selfail = 0;
- if(!DPMIassignSelector(DPMIselect, 0xc0b3, DPMImem.address,
- DPMImem.bytes - 1 ) ) selfail = 1; /* win 3.1 needs f, 3.0 b */
-
- if(firsttime){
- if(!DPMIassignSelector(DPMIselect + 8, 0xc0bb, DPMImem.address,
- DPMImem.bytes - 1) ) selfail |= 2;
- if(!DPMIassignSelector(DPMIselect + 16, 0xc0b7, DPMImem.address,
- (areas[A_stack].first_addr - 1) ) ) selfail |= 4;
- } else if(DPMImem.address != oldbase) {
- if(!DPMISelectorBase(DPMIselect + 8, DPMImem.address) ) selfail |= 10;
- if(!DPMISelectorBase(DPMIselect + 16, DPMImem.address) ) selfail |= 12;
- if(using_external_debugger) {
- DPMIrealMode();
- clear_break_DPMI(); /* This clears the breakpoints */
- set_break_DPMI(); /* This resets them with new base */
- DPMIprotectedMode();
- }
- }
- oldbase = DPMImem.address;
-
- #if VERBOSE
- if(selfail) {
- /* For some reason stack #4 fails under OS2 but it still works; thus
- the workaround is to ignore this section unless in verbose mode */
- DPMIrealMode();
- fprintf(stderr,"DPMI: AssignSelector %d failed!\n",selfail);
- /* exit(3); */
- DPMIprotectedMode(); /* Only if exit commented */
- }
- #endif
- }
-
- void loadAout(const AREAS* areas)
- {
- word32 count = areas->last_addr + 1 - areas->first_addr;
-
- if (count > 0) {
- word32 loadAddr = areas->first_addr;
- lseek(areas->fileno, areas->foffset, 0);
- while (count > 0) {
- word16 readBytes;
- word16 bytes = (count > 4096) ? 4096 : (word16)count;
- readBytes = read(areas->fileno, transfer_buffer, bytes);
- if (readBytes < bytes) memset(transfer_buffer + readBytes, 0, bytes - readBytes);
- memput(loadAddr, transfer_buffer, bytes);
- loadAddr += bytes;
- count -= bytes;
- }
- }
- }
-
- void clearDPMIstate(void)
- {
- DPMIfree(&DPMImem); /* QDPMI bug fix - child processes don't free memory */
- }
-
- static void saveDPMIstate(void)
- {
- int a;
- word32 firsta, lengtha;
- word16 bytes;
- unsigned block;
-
- block = 0;
- for (a=0; a<MAX_AREA; a++) {
- firsta = areas[a].first_addr;
- if ( a == A_stack ) firsta = a_tss.tss_esp & 0xfffff000L;
- lengtha = areas[a].last_addr - firsta + 1;
- while (lengtha > 0) {
- bytes = (lengtha > 4096) ? 4096 : (word16)lengtha;
- Pmemget(DPMIselect, firsta, paging_buffer, bytes);
- dwrite(paging_buffer, block++);
- firsta += bytes;
- lengtha -= bytes;
- }
- }
- DPMIprotectedMode();
- DPMIfree(&DPMImem);
- restoreDPMIvector();
- DPMIrealMode();
- }
-
- static void restoreDPMIstate(void)
- {
- int a;
- word32 firsta, lengtha;
- word16 bytes;
- unsigned block;
-
- DPMIprotectedMode();
- setDPMIvector();
- lengtha = (areas[A_arena].last_addr + 1 + DPMIgetpage) & ~DPMIgetpage;
- if (! DPMIalloc(&DPMImem, lengtha)) {
- DPMIrealMode();
- fprintf(stderr,"\nDPMI: Not enough memory (0x%08lx bytes).\n", lengtha);
- exit(3);
- }
- setDPMISelectors(0);
- DPMIrealMode();
- firsta = areas[A_arena].last_addr + 1;
- if(lengtha > firsta)
- Pmemset(DPMIselect, firsta, 0, lengtha - firsta );
-
- block = 0;
- for (a=0; a<MAX_AREA; a++) {
- firsta = areas[a].first_addr;
- if ( a == A_stack ) firsta = a_tss.tss_esp & 0xfffff000L;
- lengtha = areas[a].last_addr - firsta + 1;
- while (lengtha > 0) {
- bytes = (lengtha > 4096) ? 4096 : (word16)lengtha;
- dread(paging_buffer, block++);
- Pmemput(DPMIselect, firsta, paging_buffer, bytes);
- firsta += bytes;
- lengtha -= bytes;
- }
- }
- }
-
- int changeBreak(word32 breakPoint)
- {
- word32 oldbytes, newbytes;
-
- newbytes = (breakPoint + DPMIgetpage) & ~DPMIgetpage; /* 64K for performance */
- oldbytes = DPMImem.bytes;
- if (newbytes < areas[A_arena].first_addr) newbytes=areas[A_arena].first_addr;
- #if VERBOSE
- fprintf(stderr,"changeBreak: old=0x%08lx break=0x%08lx new=0x%08lx\n",
- oldbytes, breakPoint, newbytes);
- #endif
- if (DPMImem.bytes != newbytes) {
- DPMIprotectedMode();
- if (! DPMIrealloc(&DPMImem, newbytes)) {
- DPMIrealMode();
- fprintf(stderr,"\nDPMI: Not enough memory (0x%08lx bytes).\n", newbytes);
- return 0;
- }
- setDPMISelectors(0);
- DPMIrealMode();
- }
- if(newbytes > oldbytes)
- Pmemset(DPMIselect, oldbytes, 0, newbytes - oldbytes );
- return 1;
- }
-
- /* VCPI Get Interface */
- void link_vcpi(word32 far *dir, word32 far *table)
- {
-
- vcpi_entry.selector = g_vcpicode * 8;
- vcpi_entry.offset32 = get_interface(table,&gdt[g_vcpicode]);
- client.page_table = far2pte(dir, 0); /* (word32)dir>>12; */
- client.gdt_address = ptr2linear(&gdt_phys);
- client.idt_address = ptr2linear(&idt_phys);
- client.ldt_selector = 0;
- client.tss_selector = g_ctss * 8;
- client.entry_eip = (word16)protect_entry;
- client.entry_cs = g_rcode * 8;
-
- abs_client = ptr2linear(&client);
- }
-
- void handle_screen_swap(word32 far *pt)
- {
- struct REGPACK r;
- int have_mono=0;
- int have_color=0;
- int have_graphics=0;
- int save, new;
-
- r.r_ax = 0x1200;
- r.r_bx = 0xff10;
- r.r_cx = 0xffff;
- intr(0x10, &r);
- if (r.r_cx == 0xffff)
- pokeb(0x40, 0x84, 24); /* the only size for CGA/MDA */
-
- if (!vcpi_installed || (pt[0xb8] & (PT_U|PT_W)) == (PT_W|PT_U))
- {
- save = peekb(screen_seg, 0);
- pokeb(screen_seg, 0, ~save);
- new = peekb(screen_seg, 0);
- pokeb(screen_seg, 0, save);
- if (new == ~save)
- have_color = 1;
- }
-
- if (!vcpi_installed || (pt[0xb0] & (PT_U|PT_W)) == (PT_W|PT_U))
- {
- save = peekb(0xb000, 0);
- pokeb(0xb000, 0, ~save);
- new = peekb(0xb000, 0);
- pokeb(0xb000, 0, save);
- if (new == ~save)
- have_mono = 1;
- }
-
- r.r_ax = 0x0f00;
- intr(0x10, &r);
- if ((r.r_ax & 0xff) > 0x07)
- have_graphics = 1;
-
- if (have_graphics && have_mono)
- have_color = 1;
- else if (have_graphics && have_color)
- have_mono = 1;
-
- screen_primary = 0xe00b8000L;
- screen_secondary = 0xe00b0000L;
-
- if (have_color && !have_mono)
- {
- screen_secondary = 0xe00b8000L;
- return;
- }
- if (have_mono & !have_color)
- {
- screen_primary = 0xe00b0000L;
- return;
- }
-
- if ((biosequip() & 0x0030) == 0x0030) /* mono mode, swap! */
- {
- screen_primary = 0xe00b0000L;
- screen_secondary = 0xe00b8000L;
- return;
- }
- }
-
- void paging_set_file(char *fname)
- {
- word32 newbytes;
- word32 far *pt;
- FILEHDR filehdr;
- AOUTHDR aouthdr;
- SCNHDR scnhdr[3];
- GNU_AOUT gnu_aout;
- unsigned short *exe_hdr;
- int i;
- int aout_f;
-
- aout_f = open(fname, O_RDONLY|O_BINARY);
- if (aout_f < 0)
- {
- fprintf(stderr, "Can't open file <%s>\n", fname);
- exit(1);
- }
-
- areas[A_text].fileno = aout_f;
- areas[A_data].fileno = aout_f;
- for (i=A_bss; i<A_max; i++)
- areas[i].fileno = 0;
-
- if (topline_info)
- for (i=0; fname[i]; i++)
- poke(screen_seg, i*2+10, fname[i] | 0x0700);
-
- lseek(aout_f, header_offset, 0);
- read(aout_f, &filehdr, sizeof(filehdr));
-
- if (filehdr.f_magic == 0x5a4d) /* .EXE */
- {
- exe_hdr = (unsigned short *)&filehdr;
- header_offset += (long)exe_hdr[2]*512L;
- if (exe_hdr[1])
- header_offset += (long)exe_hdr[1] - 512L;
- lseek(aout_f, header_offset, 0);
- read(aout_f, &filehdr, sizeof(filehdr));
- }
-
- if (filehdr.f_magic != 0x14c)
- {
- lseek(aout_f, header_offset, 0);
- read(aout_f, &gnu_aout, sizeof(gnu_aout));
- a_tss.tss_eip = gnu_aout.entry;
- aouthdr.tsize = gnu_aout.tsize;
- aouthdr.dsize = gnu_aout.dsize;
- aouthdr.bsize = gnu_aout.bsize;
- }
- else
- {
- read(aout_f, &aouthdr, sizeof(aouthdr));
- a_tss.tss_eip = aouthdr.entry;
- read(aout_f, scnhdr, sizeof(scnhdr));
- }
- arena_cs =
- a_tss.tss_cs = g_acode*8;
- arena_ds =
- a_tss.tss_ds =
- a_tss.tss_es =
- a_tss.tss_fs =
- a_tss.tss_ss = g_adata*8;
- a_tss.tss_esp = 0x7ffffffcL;
-
- if (filehdr.f_magic == 0x14c)
- {
- areas[A_text].first_addr = aouthdr.text_start + ARENA;
- areas[A_text].foffset = scnhdr[0].s_scnptr + header_offset;
- areas[A_text].last_addr = areas[A_text].first_addr + aouthdr.tsize - 1;
- }
- else if (filehdr.f_magic == 0x10b)
- {
- areas[A_text].first_addr = ARENA;
- if (a_tss.tss_eip >= 0x1000) /* leave space for null reference */
- areas[A_text].first_addr += 0x1000; /* to cause seg fault */
- areas[A_text].foffset = header_offset;
- areas[A_text].last_addr = areas[A_text].first_addr + aouthdr.tsize + 0x20 - 1;
- }
- else if (debug_mode && filehdr.f_magic == 0x107)
- {
- struct stat sbuf;
- fstat(aout_f, &sbuf);
- areas[A_text].first_addr = ARENA;
- areas[A_text].foffset = 0x20 + header_offset;
- areas[A_text].last_addr = sbuf.st_size + ARENA - 0x20;
- }
- else if (debug_mode)
- {
- struct stat sbuf;
- fstat(aout_f, &sbuf);
- areas[A_text].first_addr = ARENA;
- areas[A_text].foffset = header_offset;
- areas[A_text].last_addr = sbuf.st_size + ARENA;
- }
- else
- {
- fprintf(stderr, "Unknown file type 0x%x (0%o)\n", filehdr.f_magic, filehdr.f_magic);
- exit(-1);
- }
- if (debug_mode)
- fprintf(stderr, "%ld+", aouthdr.tsize);
-
- if (filehdr.f_magic == 0x14c)
- {
- areas[A_data].first_addr = aouthdr.data_start + ARENA;
- areas[A_data].foffset = scnhdr[1].s_scnptr + header_offset;
- }
- else
- {
- areas[A_data].first_addr = (areas[A_text].last_addr+0x3fffffL)&~0x3fffffL;
- areas[A_data].foffset = ((aouthdr.tsize + 0x20 + 0xfffL) & ~0xfffL) + header_offset;
- }
- areas[A_data].last_addr = areas[A_data].first_addr + aouthdr.dsize - 1;
- if (debug_mode)
- fprintf(stderr, "%ld+", aouthdr.dsize);
-
- areas[A_bss].first_addr = areas[A_data].last_addr + 1;
- areas[A_bss].foffset = -1;
- areas[A_bss].last_addr = areas[A_bss].first_addr + aouthdr.bsize - 1;
- if (debug_mode)
- fprintf(stderr, "%ld = %ld\n", aouthdr.bsize,
- aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
-
- areas[A_arena].first_addr = (areas[A_bss].last_addr + 1 + 7) & ~7L;
- areas[A_arena].last_addr = areas[A_arena].first_addr - 1;
- areas[A_arena].foffset = -1;
-
- if(!use_DPMI)
- {
- areas[A_stack].first_addr = 0x50000000L;
- areas[A_stack].last_addr = 0x8fffffffL;
- areas[A_stack].foffset = -1;
-
- areas[A_vga].first_addr = 0xe0000000L;
- areas[A_vga].last_addr = 0xe03fffffL;
- areas[A_vga].foffset = -1;
-
- areas[A_syms].first_addr = 0xa0000000L;
- areas[A_syms].last_addr = 0xafffffffL;
- areas[A_syms].foffset = -1;
-
- pd = (word32 far *)((long)valloc(VA_640) << 24);
- vcpi_pt = pt = (word32 far *)((long)valloc(VA_640) << 24);
- for (i=0; i<1024; i++)
- {
- pd[i] = 0;
- pd_seg[i] = 0;
- }
-
- if (vcpi_installed)
- {
- link_vcpi(pd,pt); /* Get VCPI Page Table */
- for ( i=0; i<1024; i++)
- if (pt[i] & PT_P)
- pt[i] |= PT_I;
- }
- else
- {
- for (i=0; i < DOS_PAGE; i++)
- pt[i] = ((unsigned long)i<<12) | PT_P | PT_W | PT_I;
- for (; i<1024; i++)
- pt[i] = 0;
- }
-
- pd[0] =
- pd[0x3c0] = far2pte(pt, PT_P | PT_W | PT_I); /* map 1:1 1st Mb */
- pd_seg[0] =
- pd_seg[0x3c0] = (word32)pt >> 24;
-
- gdt_phys.limit = gdt[g_gdt].lim0;
- gdt_phys.base = ptr2linear(&gdt);
- idt_phys.limit = gdt[g_idt].lim0;
- idt_phys.base = ptr2linear(&idt);
-
- handle_screen_swap(pt);
- a_tss.tss_ebx = screen_primary;
- a_tss.tss_ebp = screen_secondary;
- prog_info.linear_address_of_primary_screen = screen_primary;
- prog_info.linear_address_of_secondary_screen = screen_secondary;
-
- /* CB changes: two page tables + stuff for graphics page fault handler */
- /* to move around page tables in the page directory */
- /* OLD:
- * graphics_pt = (word32 far *)((long)valloc(VA_640) << 24);
- * graphics_pt_lin = ptr2linear(graphics_pt);
- * for (i=0; i<1024; i++)
- * graphics_pt[i] = 0x000a0000L | ((i * 4096L) & 0xffffL) | PT_W | PT_U;
- * pd[0x380] = far2pte(graphics_pt, PT_P | PT_W | PT_U);
- * pd_seg[0x380] = (word32)graphics_pt >> 24;
- */
- graphics_pd = &pd[0x380];
- graphics_pd_seg = &pd_seg[0x380];
- graphics_pd_lin = ptr2linear(graphics_pd);
- graphics_pd_seg_lin = ptr2linear(graphics_pd_seg);
- graphics_pt1 = (word32 far *)((long)valloc(VA_640) << 24);
- graphics_pt2 = (word32 far *)((long)valloc(VA_640) << 24);
- graphics_pt1_lin = ptr2linear(graphics_pt1);
- graphics_pt2_lin = ptr2linear(graphics_pt2);
- graphics_pt1_loc = 0; /* first RW page */
- graphics_pt2_loc = (0x03000000L / 4096L / 1024L); /* first page of the 16 MB write only area */
- graphics_pd[(word16)graphics_pt1_loc] = far2pte(graphics_pt1,(PT_P | PT_W | PT_U));
- graphics_pd[(word16)graphics_pt2_loc] = far2pte(graphics_pt2,(PT_P | PT_W | PT_U));
- graphics_pd_seg[(word16)graphics_pt1_loc] = (word32)graphics_pt1 >> 24;
- graphics_pd_seg[(word16)graphics_pt2_loc] = (word32)graphics_pt2 >> 24;
- for(i = 0; i < 1024; i++) {
- graphics_pt1[i] = 0L;
- graphics_pt2[i] = 0L;
- }
- /* end CB changes */
-
- c_tss.tss_cr3 =
- a_tss.tss_cr3 =
- o_tss.tss_cr3 =
- i_tss.tss_cr3 =
- p_tss.tss_cr3 =
- f_tss.tss_cr3 =
- r_tss.tss_cr3 =
- v74_tss.tss_cr3 =
- v78_tss.tss_cr3 =
- v79_tss.tss_cr3 = far2pte(pd, 0);
-
- a_tss.tss_esi = far2pte(pd,0) >> 12; /* PID */
- prog_info.pid = far2pte(pd,0) >> 12;
-
- }
- else /* use_DPMI */
- {
-
- if (areas[A_bss].last_addr < 0x11000L)
- areas[A_bss].last_addr = 0x11000L;
- handle_screen_swap(NULL);
- a_tss.tss_ebx = screen_primary;
- a_tss.tss_ebp = screen_secondary;
- prog_info.linear_address_of_primary_screen = screen_primary;
- prog_info.linear_address_of_secondary_screen = screen_secondary;
- a_tss.tss_esi = FP_SEG(paging_buffer);
- prog_info.pid = FP_SEG(paging_buffer);
- #if VERBOSE
- fprintf(stderr,"%ld+%ld+%ld = %ld\n", aouthdr.tsize, aouthdr.dsize, aouthdr.bsize,
- aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
- #endif
-
- /* In certain instances, there is a large gap between text and data. If it
- is larger than the stack size, lets take advantage of it. */
-
- if (areas[A_data].first_addr - areas[A_text].last_addr <= DPMI_STACK)
- { /* No room, put stack between bss and arena */
- areas[A_stack].first_addr = (areas[A_bss].last_addr + 1 + 0xfff) & ~0xfff;
- if (areas[A_stack].first_addr < 0x11000L)
- areas[A_stack].first_addr = 0x11000L; /* Some bizzare windows bug */
- areas[A_stack].last_addr = areas[A_stack].first_addr + DPMI_STACK - 1;
- areas[A_arena].first_addr = areas[A_stack].last_addr + 1;
- areas[A_arena].last_addr = areas[A_stack].last_addr;
- } else { /* Put stack in gap */
- areas[A_stack].last_addr = areas[A_data].first_addr - 1;
- /* areas[A_stack].first_addr = areas[A_stack].last_addr - DPMI_STACK + 1; */
- areas[A_stack].first_addr = (areas[A_text].last_addr + 1 + 0xfff) & ~0xfff;
- if (areas[A_stack].first_addr < 0x11000L)
- areas[A_stack].first_addr = 0x11000L; /* Some bizzare windows bug */
- }
- areas[A_vga].first_addr =
- areas[A_syms].first_addr =
- areas[A_syms2].first_addr = 1; /* Not used */
- areas[A_vga].last_addr =
- areas[A_syms].last_addr =
- areas[A_syms2].last_addr = 0; /* len zero */
-
- /* Here and in changeBreak we use 64K breaks to minimize calls to DPMI */
- newbytes = (areas[A_arena].last_addr + 1 + DPMIgetpage) & ~DPMIgetpage;
- DPMIprotectedMode();
- if (! DPMIalloc(&DPMImem, newbytes))
- {
- DPMIrealMode();
- fprintf(stderr,"DPMI: Not enough memory (0x%08lx bytes).\n", newbytes);
- exit(1);
- }
- DPMIselect = DPMIselector(4);
- if (DPMIselect == 0)
- {
- DPMIrealMode();
- fprintf(stderr,"DPMI: Not enough selectors.\n");
- exit(1);
- }
- setDPMISelectors(1);
- DPMIassignSelector(DPMIselect+24, 0xc0b3, 0L, 0xfffffL);
- DPMIrealMode();
-
- core_selector =
- a_tss.tss_gs =
- prog_info.selector_for_linear_memory = (word16)(DPMIselect+24);
-
- a_tss.tss_eax = (word32)(DPMIselect + 24) << 16; /* Hi word for "core" selector */
- arena_ds = a_tss.tss_ds = a_tss.tss_es = a_tss.tss_fs = DPMIselect;
- arena_cs = a_tss.tss_cs = DPMIselect + 8;
- a_tss.tss_ss = DPMIselect + 16;
- a_tss.tss_esp = areas[A_stack].last_addr + 1;
- a_tss.tss_eflags = 0x0202;
-
- r_tss.tss_es = r_tss.tss_fs = DPMIselect;
- r_tss.tss_cs = DPMIselect + 8;
-
- loadAout(&areas[A_text]);
- loadAout(&areas[A_data]);
- Pmemset(DPMIselect, areas[A_bss].first_addr, 0, areas[A_bss].last_addr + 1 - areas[A_bss].first_addr);
- Pmemset(DPMIselect, areas[A_arena].first_addr, 0, newbytes - areas[A_arena].first_addr);
-
- close(aout_f);
- } /* end else use_DPMI */
-
- #if VERBOSE
- for (i=0; i<5; i++)
- fprintf(stderr,"%d %-10s %08lx-%08lx (offset 0x%08lx)\n", i, aname[i], areas[i].first_addr, areas[i].last_addr, areas[i].foffset);
- #endif
- }
-
- static update_status(int c, int col)
- {
- int r;
- r = peek(screen_seg, 2*79);
- poke(screen_seg, 2*col, c);
- return r;
- }
-
- static int cant_ask_for(int32 amount)
- {
- static word32 reserved = 0;
- static word32 used_at_first = 0;
- word32 max;
-
- if (use_DPMI)
- return 0;
- if (used_at_first == 0)
- used_at_first = (valloc_used() - dalloc_used()) * 4096L + 8192L /* stack */;
- max = valloc_max_size()*4092L - used_at_first; /* 4096 - PTE */
-
- if (reserved + amount >= max)
- max += dalloc_max_size() * 4092L;
-
- if (reserved + amount < max)
- {
- reserved += amount;
- return 0;
- }
- return 1;
- }
-
- word32 paging_brk(word32 b)
- {
- word32 r;
-
- r = (areas[A_arena].last_addr - ARENA + 1 + 7) & ~7; /* Even value */
- if (use_DPMI)
- if (! changeBreak(b)) return -1L;
- if (cant_ask_for(b-r))
- return -1L;
- areas[A_arena].last_addr = b + ARENA - 1;
- return r;
- }
-
- word32 paging_sbrk(int32 b)
- {
- word32 r;
-
- r = (areas[A_arena].last_addr - ARENA + 1 + 7) & ~7; /* Even value */
- if (use_DPMI)
- if (! changeBreak(r + b)) return -1L;
- if (cant_ask_for(b))
- return -1L;
- areas[A_arena].last_addr = r + b + ARENA - 1;
- return r;
- }
-
- int page_is_valid(word32 vaddr)
- {
- int a;
- for (a=0; a<MAX_AREA; a++)
- if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
- return 1;
- if ( use_DPMI )
- return 0;
- if (vaddr >= 0xf0000000L)
- return 1;
- return 0;
- }
-
- int page_in(void)
- {
- int old_status;
- TSS *old_util_tss;
- word32 far *pt;
- word32 vaddr, cnt32;
- word32 eaddr, vtran, vcnt, zaddr;
- int pdi, pti, pn, a, count;
- unsigned dblock;
-
- if (use_DPMI)
- return 1;
-
- #if 0
- unsigned char buf[100];
- sprintf(buf, "0x%08lx", a_tss.tss_cr2 - ARENA);
- for (a=0; buf[a]; a++)
- poke(screen_seg, 80+a*2, 0x0600 | buf[a]);
- #endif
-
- old_util_tss = utils_tss;
- utils_tss = &f_tss;
- vaddr = tss_ptr->tss_cr2;
-
- for (a=0; a<MAX_AREA; a++)
- if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
- goto got_area;
-
- if (vaddr >= 0xf0000000L)
- {
- pdi = (word16)(vaddr >> 22) & 0x3ff;
- if (!(pd[pdi] & PT_P)) /* put in a mapped page table */
- {
- pn = valloc(VA_640);
- pt = (word32 far *)((word32)pn << 24);
- if (pd[pdi] & PT_S)
- {
- dread(paging_buffer, (word16)(pd[pdi]>>12));
- movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
- dfree((word16)(pd[pdi]>>12));
- pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
- pd_seg[pdi] = pn;
- }
- else
- {
- pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
- pd_seg[pdi] = pn;
- vaddr &= 0x0fc00000L;
- for (pti = 0; pti < 1024; pti++)
- pt[pti] = PT_P | PT_W | PT_I | vaddr | (((word32)pti)<<12);
- }
- return 0;
- }
- pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
- vaddr &= 0x0ffff000L;
- pti = (word16)(vaddr>>12) & 0x3ff;
- pt[pti] = vaddr | PT_P | PT_W | PT_I;
- return 0;
- }
-
- segfault(tss_ptr->tss_cr2);
- return 1;
-
- got_area:
- vaddr &= 0xFFFFF000L; /* points to beginning of page */
- #if 0 /* handled in protected mode for speed */
- if (a == A_vga)
- return graphics_fault(vaddr, graphics_pt);
- #endif
-
- #if VERBOSE
- printf("area(%d) - ", a);
- #endif
-
- if ((a == A_bss) & (vaddr < areas[a].first_addr)) /* bss, but data too */
- {
- #if VERBOSE
- printf("split page (data/bss) detected - ");
- #endif
- a = A_data; /* set to page in data */
- }
-
- if (topline_info)
- old_status = update_status(achar[a] | 0x0a00, 78);
- #if VERBOSE
- printf("Paging in %s block for vaddr %#010lx -", aname[a], tss_ptr->tss_cr2-ARENA);
- #endif
- pdi = (word16)(vaddr >> 22) & 0x3ff;
- if (!(pd[pdi] & PT_P)) /* put in an empty page table if required */
- {
- pn = valloc(VA_640);
- pt = (word32 far *)((word32)pn << 24);
- if (pd[pdi] & PT_I)
- {
- dread(paging_buffer, (word16)(pd[pdi]>>12));
- movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
- dfree((word16)(pd[pdi] >> 12));
- pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
- pd_seg[pdi] = pn;
- }
- else
- {
- pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
- pd_seg[pdi] = pn;
- for (pti=0; pti<1024; pti++)
- pt[pti] = PT_W | PT_S;
- }
- }
- else
- pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
- pti = (word16)(vaddr >> 12) & 0x3ff;
- if (pt[pti] & PT_P)
- {
- utils_tss = old_util_tss;
- if (topline_info)
- update_status(old_status, 78);
- return 0;
- }
- count = MAX_PAGING_NUM;
- if (count > mem_avail/4)
- count = 1;
- if (pti + count > 1024)
- count = 1024 - pti;
- if (vaddr + count*4096L > areas[a].last_addr+4096L)
- count = (word16)((areas[a].last_addr - vaddr + 4095) / 4096);
- if (count < 1)
- count = 1;
- zaddr = eaddr = -1;
- vtran = vaddr;
- vcnt = 0;
- for (; count; count--, pti++, vaddr+=4096)
- {
- if (pt[pti] & PT_P)
- break;
- if (eaddr != -1 && (pt[pti] & PT_I) != 0)
- break; /* EastWind 1993 */
- dblock = (word16)(pt[pti] >> 12);
- pn = valloc(VA_1M);
- pt[pti] &= 0xfffL & ~(word32)(PT_A | PT_D);
- pt[pti] |= ((word32)pn << 12) | PT_P;
-
- if (pt[pti] & PT_I)
- {
- #if VERBOSE
- printf(" swap");
- #endif
- dread(paging_buffer, dblock);
- dfree(dblock);
- memput(vaddr, paging_buffer, 4096);
- pt[pti] &= ~(word32)(PT_A | PT_D); /* clean dirty an accessed bits (set by memput) */
- }
- else
- {
- pt[pti] &= ~(word32)(PT_C);
- if (areas[a].foffset != -1)
- {
- #if VERBOSE
- if (a == A_emu)
- printf(" emu");
- else
- printf(" exec");
- #endif
- if (eaddr == -1)
- {
- eaddr = areas[a].foffset + (vaddr - areas[a].first_addr);
- vtran = vaddr;
- }
- cnt32 = areas[a].last_addr - vaddr + 1;
- if (cnt32 > 4096)
- cnt32 = 4096;
- else
- zaddr = vaddr;
- vcnt += cnt32;
- }
- else
- {
- zero32(vaddr);
- #if VERBOSE
- printf(" zero");
- #endif
- }
- pt[pti] |= PT_I;
- }
- /* if (paged_out_something) */
- break;
- }
- if (eaddr != -1)
- {
- int cur_f, rsize, vc;
- cur_f = areas[a].fileno;
- lseek(cur_f, eaddr, 0);
- rsize = read(cur_f, paging_buffer, (word16)vcnt);
- if (rsize < vcnt)
- memset(paging_buffer+rsize, 0, (word16)(vcnt-rsize));
- if (zaddr != -1)
- zero32(zaddr);
- memput(vtran, paging_buffer, vcnt);
- vc = (word16)(vcnt / 4096); /* don't reset BSS parts */
- while (vc)
- {
- pdi = (word16)(vtran >> 22);
- pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
- pti = (word16)(vtran >> 12) & 0x3ff;
- pt[pti] &= ~(word32)(PT_A | PT_D); /* clean dirty an accessed bits (set by memput) */
- vc--;
- vtran += 4096;
- }
- }
- #if VERBOSE
- printf("\n");
- #endif
- utils_tss = old_util_tss;
- if (topline_info)
- update_status(old_status, 78);
- return 0;
- }
-
- static fInPageOutEverything = 0;
- static last_po_pdi = 0;
- static last_po_pti = 0;
- static last_pti = 0;
-
- unsigned page_out(int where) /* return >= 0 page which is paged out, 0xffff if not */
- {
- int start_pdi, start_pti, pti;
- word32 far *pt, v, rv;
- unsigned dblock;
- int old_status;
- if (topline_info)
- {
- old_status = update_status('>' | 0x0a00, 79);
- }
- start_pdi = last_po_pdi;
- start_pti = last_po_pti;
- if (where == VA_640)
- {
- for (pti = last_pti+1; pti != last_pti; pti = (pti+1)%1024)
- if ((pd[pti] & (PT_P | PT_S)) == (PT_P | PT_S))
- {
- dblock = dalloc();
- movedata(pd_seg[pti]<<8, 0, _DS, FP_OFF(paging_buffer), 4096);
- dwrite(paging_buffer, dblock);
- #if VERBOSE
- printf ("out_640 %d\n", pti);
- #endif
- pd[pti] &= 0xfff & ~(word32)(PT_P); /* no longer present */
- pd[pti] |= (long)dblock << 12;
- if (topline_info)
- update_status(old_status, 79);
- last_pti = pti;
- return pd_seg[pti];
- }
- return -1;
- }
- pt = (word32 far *)((word32)(pd_seg[last_po_pdi]) << 24);
- do {
- if ((pd[last_po_pdi] & (PT_P | PT_S)) == (PT_P | PT_S))
- {
- if ((pt[last_po_pti] & (PT_P | PT_S)) == (PT_P | PT_S))
- {
- rv = pt[last_po_pti] >> 12;
- v = ((word32)last_po_pdi << 22) | ((word32)last_po_pti << 12);
- if (!fInPageOutEverything)
- if ((v & 0xfffff000L) == ((tss_ptr->tss_eip + ARENA) & 0xfffff000L) ||
- (v & 0xfffff000L) == ((tss_ptr->tss_esp + ARENA) & 0xfffff000L))
- {
- #if VERBOSE
- printf("\nskip: v=%08lx - ", v);
- #endif
- goto bad_choice;
- }
- if (pt[last_po_pti] & (PT_C | PT_D))
- {
- pt[last_po_pti] |= PT_C;
- dblock = dalloc();
- memget(v, paging_buffer, 4096);
- #if VERBOSE
- printf ("dout %08lx", ((word32)last_po_pdi<<22) | ((word32)last_po_pti<<12));
- #endif
- dwrite(paging_buffer, dblock);
- pt[last_po_pti] &= 0xfff & ~PT_P; /* no longer present */
- pt[last_po_pti] |= (long)dblock << 12;
- }
- else
- {
- pt[last_po_pti] = PT_W | PT_S;
- #if VERBOSE
- printf ("dflush %08lx", ((word32)last_po_pdi<<22) | ((word32)last_po_pti<<12));
- #endif
- }
- if (topline_info)
- update_status(old_status, 79);
- return (word16)rv;
- }
- }
- else /* imagine we just checked the last entry */
- last_po_pti = 1023;
-
- bad_choice:
- if (++last_po_pti == 1024)
- {
- last_po_pti = 0;
- if (++last_po_pdi == 1024)
- last_po_pdi = 0;
- pt = (word32 far *)((word32)(pd_seg[last_po_pdi]) << 24);
- }
- } while ((start_pdi != last_po_pdi) || (start_pti != last_po_pti));
- if (topline_info)
- update_status(old_status, 79);
- return 0xffff;
- }
-
- unsigned pd_dblock;
-
- extern int valloc_initted;
- extern void vfree_640(void);
- extern void vrecover_640(void);
-
- void page_out_everything(void)
- {
- int pdi, i;
- word32 opde;
- unsigned ptb;
- void far *fp;
-
- if(use_DPMI)
- {
- saveDPMIstate();
- return;
- }
-
- fInPageOutEverything = 1;
-
- #ifndef KEEP_ON_EXEC
- while (page_out(-1) != 0xffff)
- {
- vfree();
- }
- #endif
- for (pdi=0; pdi<1024; pdi++)
- if (pd[pdi] & PT_P)
- {
- ptb = dalloc();
- opde = pd[pdi] & 0xfffff001L;
- fp = (word32 far *)((word32)pd_seg[pdi] << 24);
- movedata(FP_SEG(fp), FP_OFF(fp), _DS, FP_OFF(paging_buffer), 4096);
- dwrite(paging_buffer, ptb);
- vfree();
- pd[pdi] = (pd[pdi] & (0xFFF&~PT_P)) | ((word32)ptb<<12);
- for (i=pdi+1; i<1024; i++)
- if ((pd[i] & 0xfffff001L) == opde)
- pd[i] = pd[pdi];
- }
- movedata(FP_SEG(pd), FP_OFF(pd), _DS, FP_OFF(paging_buffer), 4096);
- pd_dblock = dalloc();
- dwrite(paging_buffer, pd_dblock);
- vfree();
- #ifndef KEEP_ON_EXEC
- vcpi_flush();
- valloc_uninit();
- #else
- vfree_640();
- #endif
- }
-
- void page_in_everything(void)
- {
- int pdi, i;
- word32 opde;
- unsigned ptb;
- word32 far *pt;
- unsigned pta;
-
- if(use_DPMI)
- {
- restoreDPMIstate();
- return;
- }
-
- fInPageOutEverything = 0;
-
- #ifndef KEEP_ON_EXEC
- valloc_initted = 0;
- #else
- vrecover_640();
- #endif
- pta = valloc(VA_640);
- pd = (word32 far *)((word32)pta << 24);
- dread(paging_buffer, pd_dblock);
- dfree(pd_dblock);
- movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pd), FP_OFF(pd), 4096);
- for (pdi=0; pdi<1024; pdi++)
- if (pd[pdi] && !(pd[pdi] & PT_P))
- {
- pta = valloc(VA_640);
- opde = pd[pdi] & 0xfffff001L;
- pt = (word32 far *)((word32)pta << 24);
- ptb = (word16)(opde >> 12);
- dread(paging_buffer, ptb);
- dfree(ptb);
- movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
- if (pdi == 0)
- vcpi_pt = (word32 far *)((word32)pta << 24);
- pd[pdi] = pn2pte(pta, (pd[pdi] & 0xFFF) | PT_P);
- pd_seg[pdi] = pta;
- for (i=pdi+1; i<1024; i++)
- if ((pd[i] & 0xfffff001L) == opde)
- {
- pd[i] = pd[pdi];
- pd_seg[i] = pd_seg[pdi];
- }
- }
- /* CB changes: two tables + page directory stuff */
- /* OLD:
- * graphics_pt = (word32 far *)((long)pd_seg[0x380] << 24);
- * graphics_pt_lin = ptr2linear(graphics_pt);
- */
- graphics_pd = &pd[0x380];
- graphics_pd_lin = ptr2linear(graphics_pd);
- graphics_pt1 = (word32 far *)((word32)graphics_pd_seg[(word16)graphics_pt1_loc] << 24);
- graphics_pt2 = (word32 far *)((word32)graphics_pd_seg[(word16)graphics_pt2_loc] << 24);
- graphics_pt1_lin = ptr2linear(graphics_pt1);
- graphics_pt2_lin = ptr2linear(graphics_pt2);
- for(i = 0; i < 1024; i++) {
- graphics_pt1[i] = 0L;
- graphics_pt2[i] = 0L;
- }
- /* end CB changes */
- }
-
-
- static word32 emu_start_ip_val = 0;
-
- word32 emu_start_ip()
- {
- return emu_start_ip_val;
- }
-
- int emu_install(char *filename)
- {
- FILEHDR filehdr;
- AOUTHDR aouthdr;
- GNU_AOUT gnu_aout;
- int emu_f;
-
- areas[A_emu].first_addr = EMU_TEXT+ARENA;
- areas[A_emu].last_addr = EMU_TEXT-1+ARENA;
- areas[A_emu].foffset = 0;
-
- if (use_DPMI)
- return 0;
- if (filename == 0)
- return 0;
- emu_f = open(filename, O_RDONLY|O_BINARY);
- if (emu_f < 0)
- {
- fprintf(stderr, "Can't open 80387 emulator file <%s>\n", filename);
- return 0;
- }
- areas[A_emu].fileno = emu_f;
-
- read(emu_f, &filehdr, sizeof(filehdr));
- if (filehdr.f_magic != 0x14c)
- {
- lseek(emu_f, 0L, 0);
- read(emu_f, &gnu_aout, sizeof(gnu_aout));
- emu_start_ip_val = gnu_aout.entry;
- aouthdr.tsize = gnu_aout.tsize;
- aouthdr.dsize = gnu_aout.dsize;
- aouthdr.bsize = gnu_aout.bsize;
- }
- else
- {
- read(emu_f, &aouthdr, sizeof(aouthdr));
- emu_start_ip_val = aouthdr.entry;
- }
-
- areas[A_emu].last_addr += aouthdr.tsize + aouthdr.dsize + aouthdr.bsize + (emu_start_ip_val & 0xff);
- return 1;
- }
-
- word32 stack_used(void)
- {
- int pdi,pti;
- word32 far *pt;
-
- for(pdi=0x140;pdi<0x240;pdi++)
- if( pd[pdi] & PT_I ) { /* really should check for PT_P here, but */
- pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
- for(pti=0;pti<1024;pti++)
- if( pt[pti] & PT_I )
- return ((word32)(0x23f-pdi) << 22) | ((word32)(1024-pti) << 12);
- }
- return 0L; /* No stack pd entries found! */
- }
-