aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Lemon <jlemon@FreeBSD.org>1999-04-15 21:01:14 +0000
committerJonathan Lemon <jlemon@FreeBSD.org>1999-04-15 21:01:14 +0000
commit039a180f50c7649bf7a9ac29a5fd14a6fcc3e94c (patch)
treebfcdf5691f83bd142d1a0fb405a9d22261523cf5 /sys
parent34d443c011b0f1b7d6b810cb2d99d9a5ac3a3d27 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/i386/vm86.c188
-rw-r--r--sys/i386/i386/vm86bios.s16
-rw-r--r--sys/i386/include/vm86.h24
-rw-r--r--sys/i386/isa/vesa.c48
4 files changed, 186 insertions, 90 deletions
diff --git a/sys/i386/i386/vm86.c b/sys/i386/i386/vm86.c
index c8d0be1c7203..55c435e04fae 100644
--- a/sys/i386/i386/vm86.c
+++ b/sys/i386/i386/vm86.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: vm86.c,v 1.19 1998/12/07 21:58:19 archie Exp $
+ * $Id: vm86.c,v 1.23 1999/03/18 18:43:03 jlemon Exp $
*/
#include "opt_vm86.h"
@@ -450,17 +450,56 @@ vm86_initialize(void)
vm86pcb = pcb;
}
+vm_offset_t
+vm86_getpage(struct vm86context *vmc, int pagenum)
+{
+ int i;
+
+ for (i = 0; i < vmc->npages; i++)
+ if (vmc->pmap[i].pte_num == pagenum)
+ return (vmc->pmap[i].kva);
+ return (0);
+}
+
+vm_offset_t
+vm86_addpage(struct vm86context *vmc, int pagenum, vm_offset_t kva)
+{
+ int i, flags = 0;
+
+ for (i = 0; i < vmc->npages; i++)
+ if (vmc->pmap[i].pte_num == pagenum)
+ goto bad;
+
+ if (vmc->npages == VM86_PMAPSIZE)
+ goto bad; /* XXX grow map? */
+
+ if (kva == 0) {
+ kva = (vm_offset_t)malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
+ flags = VMAP_MALLOC;
+ }
+
+ i = vmc->npages++;
+ vmc->pmap[i].flags = flags;
+ vmc->pmap[i].kva = kva;
+ vmc->pmap[i].pte_num = pagenum;
+ return (kva);
+bad:
+ panic("vm86_addpage: not enough room, or overlap");
+}
+
void
initial_bioscalls(u_int *basemem, u_int *extmem)
{
int i, method;
struct vm86frame vmf;
+ struct vm86context vmc;
u_int64_t highwat = 0;
+ pt_entry_t pte;
struct {
u_int64_t base;
u_int64_t length;
u_int32_t type;
- } smap;
+ } *smap;
bzero(&vmf, sizeof(struct vm86frame)); /* safety */
vm86_initialize();
@@ -474,9 +513,48 @@ initial_bioscalls(u_int *basemem, u_int *extmem)
* if basemem != 640, map pages r/w into vm86 page table so
* that the bios can scribble on it.
*/
- for (i = *basemem / 4; i < 160; i++) {
- u_int *pte = (u_int *)vm86paddr;
+ pte = (pt_entry_t)vm86paddr;
+ for (i = *basemem / 4; i < 160; i++)
pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
+
+ /*
+ * map page 1 R/W into the kernel page table so we can use it
+ * as a buffer. The kernel will unmap this page later.
+ */
+ pte = (pt_entry_t)vtopte(KERNBASE + (1 << PAGE_SHIFT));
+ *pte = (1 << PAGE_SHIFT) | PG_RW | PG_V;
+
+ /*
+ * get memory map with INT 15:E820
+ */
+#define SMAPSIZ sizeof(*smap)
+#define SMAP_SIG 0x534D4150 /* 'SMAP' */
+
+ vmc.npages = 0;
+ smap = (void *)vm86_addpage(&vmc, 1, KERNBASE + (1 << PAGE_SHIFT));
+ vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di);
+
+ vmf.vmf_ebx = 0;
+ do {
+ vmf.vmf_eax = 0xE820;
+ vmf.vmf_edx = SMAP_SIG;
+ vmf.vmf_ecx = SMAPSIZ;
+ i = vm86_datacall(0x15, &vmf, &vmc);
+ if (i || vmf.vmf_eax != SMAP_SIG)
+ break;
+ if (smap->type == 0x01 && smap->base >= highwat) {
+ *extmem += (smap->length / 1024);
+ highwat = smap->base + smap->length;
+ }
+ } while (vmf.vmf_ebx != 0);
+
+ if (*extmem != 0) {
+ if (*extmem > *basemem) {
+ *extmem -= *basemem;
+ method = 0xE820;
+ goto done;
+ }
+ printf("E820: extmem (%d) < basemem (%d)\n", *extmem, *basemem);
}
/*
@@ -498,11 +576,6 @@ done:
printf("BIOS basemem: %dK, extmem: %dK (from %#x call)\n",
*basemem, *extmem, method);
#endif /* !PC98 */
-#if 0
- /* VESA setup -- ? */
- vmf.vmf_ax = 0x4f02;
- error = vm86_intcall(0x10, &vmf);
-#endif
}
static void
@@ -580,63 +653,76 @@ vm86_intcall(int intnum, struct vm86frame *vmf)
}
/*
- * buffer must be entirely contained in a wired down page in kernel memory,
- * and is mapped into page 1 in vm86 space. segment/offset will be filled
- * in to create a vm86 pointer to the buffer. If intnum is a valid
- * interrupt number (0-255), then the "interrupt trampoline" will be
- * used, otherwise we use the caller's cs:ip routine.
- *
- * a future revision may allow multiple pages to be mapped, or allow
- * the caller to pass in a custom page table to use.
+ * struct vm86context contains the page table to use when making
+ * vm86 calls. If intnum is a valid interrupt number (0-255), then
+ * the "interrupt trampoline" will be used, otherwise we use the
+ * caller's cs:ip routine.
*/
int
-vm86_datacall(intnum, vmf, buffer, buflen, segment, offset)
+vm86_datacall(intnum, vmf, vmc)
int intnum;
struct vm86frame *vmf;
- char *buffer;
- int buflen;
- u_short *segment, *offset;
+ struct vm86context *vmc;
{
- int ret;
+ pt_entry_t pte = (pt_entry_t)vm86paddr;
u_int page;
- static u_char *buf;
+ int i, entry, retval;
- if (buflen < 0 || buflen > PAGE_SIZE)
- return(-1);
+ for (i = 0; i < vmc->npages; i++) {
+ page = vtophys(vmc->pmap[i].kva & PG_FRAME);
+ entry = vmc->pmap[i].pte_num;
+ vmc->pmap[i].old_pte = pte[entry];
+ pte[entry] = page | PG_V | PG_RW | PG_U;
+ }
- if (buf == NULL) {
- buf = (u_char *)contigmalloc(PAGE_SIZE, M_DEVBUF, M_WAITOK,
- 0ul, ~0ul, PAGE_SIZE, 0);
- if (buf == NULL)
- return(-1);
+ vmf->vmf_trapno = intnum;
+ retval = vm86_bioscall(vmf);
+
+ for (i = 0; i < vmc->npages; i++) {
+ entry = vmc->pmap[i].pte_num;
+ pte[entry] = vmc->pmap[i].old_pte;
}
- *offset = 0;
- *segment = 0x100;
+ return (retval);
+}
- bcopy((void *)buffer, (void *)buf, (size_t)buflen);
- page = (u_int)buf & PG_FRAME;
- page = vtophys(page);
- vmf->vmf_trapno = page | (intnum & PAGE_MASK);
- ret = vm86_bioscall(vmf);
- bcopy((void *)buf, (void *)buffer, (size_t)buflen);
+vm_offset_t
+vm86_getaddr(vmc, sel, off)
+ struct vm86context *vmc;
+ u_short sel;
+ u_short off;
+{
+ int i, page;
+ vm_offset_t addr;
- return ret;
+ addr = (vm_offset_t)MAKE_ADDR(sel, off);
+ page = addr >> PAGE_SHIFT;
+ for (i = 0; i < vmc->npages; i++)
+ if (page == vmc->pmap[i].pte_num)
+ return (vmc->pmap[i].kva + (addr & PAGE_MASK));
+ return (0);
}
-#if 0
int
-vm86_datacall(int intnum, u_int kpage, struct vm86frame *vmf)
+vm86_getptr(vmc, kva, sel, off)
+ struct vm86context *vmc;
+ vm_offset_t kva;
+ u_short *sel;
+ u_short *off;
{
- if (kpage & PAGE_MASK)
- return (EINVAL);
- kpage = vtophys(kpage);
+ int i;
- vmf->vmf_trapno = kpage | (intnum & PAGE_MASK);
- return (vm86_bioscall(vmf));
+ for (i = 0; i < vmc->npages; i++)
+ if (kva >= vmc->pmap[i].kva &&
+ kva < vmc->pmap[i].kva + PAGE_SIZE) {
+ *off = kva - vmc->pmap[i].kva;
+ *sel = vmc->pmap[i].pte_num << 8;
+ return (1);
+ }
+ return (0);
+ panic("vm86_getptr: address not found");
}
-#endif
-
+
int
vm86_sysarch(p, args)
struct proc *p;
@@ -646,11 +732,11 @@ vm86_sysarch(p, args)
struct i386_vm86_args ua;
struct vm86_kernel *vm86;
- if (error = copyin(args, &ua, sizeof(struct i386_vm86_args)))
+ if ((error = copyin(args, &ua, sizeof(struct i386_vm86_args))) != 0)
return (error);
if (p->p_addr->u_pcb.pcb_ext == 0)
- if (error = i386_extend_pcb(p))
+ if ((error = i386_extend_pcb(p)) != 0)
return (error);
vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86;
@@ -658,7 +744,7 @@ vm86_sysarch(p, args)
case VM86_INIT: {
struct vm86_init_args sa;
- if (error = copyin(ua.sub_args, &sa, sizeof(sa)))
+ if ((error = copyin(ua.sub_args, &sa, sizeof(sa))) != 0)
return (error);
if (cpu_feature & CPUID_VME)
vm86->vm86_has_vme = (rcr4() & CR4_VME ? 1 : 0);
diff --git a/sys/i386/i386/vm86bios.s b/sys/i386/i386/vm86bios.s
index ce53bcf25776..3a1d4b30585d 100644
--- a/sys/i386/i386/vm86bios.s
+++ b/sys/i386/i386/vm86bios.s
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: vm86bios.s,v 1.6 1998/09/29 18:01:18 jlemon Exp $
+ * $Id: vm86bios.s,v 1.7 1998/10/01 20:45:28 jlemon Exp $
*/
#include "opt_vm86.h"
@@ -95,18 +95,6 @@ ENTRY(vm86_bioscall)
rep
movsl /* copy frame to new stack */
- movl TF_TRAPNO(%ebx),%ebx
- cmpl $256,%ebx
- jb 1f /* no page frame to map */
-
- andl $~PAGE_MASK,%ebx
-#if 0
- orl $PG_V|PG_RW|PG_U,%ebx /* XXX assembler error?? */
-#endif
- orl $0x7,%ebx
- movl SCR_PGTABLE(%edx),%eax /* va of vm86 page table */
- movl %ebx,4(%eax) /* set vm86 PTE entry 1 */
-1:
movl _curpcb,%eax
pushl %eax /* save curpcb */
movl %edx,_curpcb /* set curpcb to vm86pcb */
@@ -194,8 +182,6 @@ ENTRY(vm86_biosret)
movl %eax,%cr3 /* install old page table */
movl $0,_in_vm86call /* reset trapflag */
- movl SCR_PGTABLE(%edx),%ebx /* va of vm86 page table */
- movl $0,4(%ebx) /* ...clear entry 1 */
movl _my_tr,%esi
leal _gdt(,%esi,8),%ebx /* entry in GDT */
diff --git a/sys/i386/include/vm86.h b/sys/i386/include/vm86.h
index c7fb23e42acb..0862f49cf629 100644
--- a/sys/i386/include/vm86.h
+++ b/sys/i386/include/vm86.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: vm86.h,v 1.7 1998/07/14 17:13:23 msmith Exp $
+ * $Id: vm86.h,v 1.8 1998/09/29 09:06:00 bde Exp $
*/
#ifndef _MACHINE_VM86_H_
@@ -98,6 +98,19 @@ struct vm86frame {
#define vmf_eflags eflags.r_ex
};
+#define VM86_PMAPSIZE 3
+#define VMAP_MALLOC 1 /* page was malloced by us */
+
+struct vm86context {
+ int npages;
+ struct vm86pmap {
+ int flags;
+ int pte_num;
+ vm_offset_t kva;
+ u_int old_pte;
+ } pmap[VM86_PMAPSIZE];
+};
+
#define VM_USERCHANGE (PSL_USERCHANGE | PSL_RF)
#define VME_USERCHANGE (VM_USERCHANGE | PSL_VIP | PSL_VIF)
@@ -142,8 +155,13 @@ extern int vm86_emulate __P((struct vm86frame *));
extern int vm86_sysarch __P((struct proc *, char *));
extern void vm86_trap __P((struct vm86frame *));
extern int vm86_intcall __P((int, struct vm86frame *));
-extern int vm86_datacall __P((int, struct vm86frame *, char *, int,
- u_short *, u_short *));
+extern int vm86_datacall __P((int, struct vm86frame *, struct vm86context *));
extern void initial_bioscalls __P((u_int *, u_int *));
+extern vm_offset_t vm86_getpage __P((struct vm86context *, int));
+extern vm_offset_t vm86_addpage __P((struct vm86context *, int, vm_offset_t));
+extern int vm86_getptr __P((struct vm86context *, vm_offset_t,
+ u_short *, u_short *));
+
+extern vm_offset_t vm86_getaddr __P((struct vm86context *, u_short, u_short));
#endif /* _MACHINE_VM86_H_ */
diff --git a/sys/i386/isa/vesa.c b/sys/i386/isa/vesa.c
index 51de263fa5a9..346e9b988b21 100644
--- a/sys/i386/isa/vesa.c
+++ b/sys/i386/isa/vesa.c
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: vesa.c,v 1.15.2.2 1999/02/20 03:06:04 yokota Exp $
+ * $Id: vesa.c,v 1.15.2.3 1999/03/29 15:11:47 yokota Exp $
*/
#include "vga.h"
@@ -101,6 +101,7 @@ static vi_set_hw_cursor_t vesa_set_hw_cursor;
static vi_set_hw_cursor_shape_t vesa_set_hw_cursor_shape;
static vi_mmap_t vesa_mmap;
static vi_diag_t vesa_diag;
+static struct vm86context vesa_vmcontext;
static video_switch_t vesavidsw = {
vesa_probe,
@@ -205,15 +206,16 @@ static int
vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
{
struct vm86frame vmf;
- u_char buf[256];
+ u_char *buf;
int err;
bzero(&vmf, sizeof(vmf));
- bzero(buf, sizeof(buf));
vmf.vmf_eax = 0x4f01;
vmf.vmf_ecx = mode;
- err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
- &vmf.vmf_es, &vmf.vmf_di);
+ buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
+ vm86_getptr(&vesa_vmcontext, buf, &vmf.vmf_es, &vmf.vmf_di);
+
+ err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
if ((err != 0) || (vmf.vmf_eax != 0x4f))
return 1;
bcopy(buf, vmode, sizeof(*vmode));
@@ -271,18 +273,17 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits)
int err;
int i;
- p = malloc(colors*4, M_DEVBUF, M_WAITOK);
-
bzero(&vmf, sizeof(vmf));
vmf.vmf_eax = 0x4f09;
vmf.vmf_ebx = 1; /* get primary palette data */
vmf.vmf_ecx = colors;
vmf.vmf_edx = start;
- err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
- if ((err != 0) || (vmf.vmf_eax != 0x4f)) {
- free(p, M_DEVBUF);
+ p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
+ vm86_getptr(&vesa_vmcontext, p, &vmf.vmf_es, &vmf.vmf_di);
+
+ err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
+ if ((err != 0) || (vmf.vmf_eax != 0x4f))
return 1;
- }
bits = 8 - bits;
for (i = 0; i < colors; ++i) {
@@ -290,7 +291,6 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits)
palette[i*3 + 1] = p[i*4 + 1] << bits;
palette[i*3 + 2] = p[i*4] << bits;
}
- free(p, M_DEVBUF);
return 0;
}
@@ -302,7 +302,7 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits)
int err;
int i;
- p = malloc(colors*4, M_DEVBUF, M_WAITOK);
+ p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
bits = 8 - bits;
for (i = 0; i < colors; ++i) {
p[i*4] = palette[i*3 + 2] >> bits;
@@ -316,8 +316,9 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits)
vmf.vmf_ebx = 0; /* set primary palette data */
vmf.vmf_ecx = colors;
vmf.vmf_edx = start;
- err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
- free(p, M_DEVBUF);
+ vm86_getptr(&vesa_vmcontext, p, &vmf.vmf_es, &vmf.vmf_di);
+
+ err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
return ((err != 0) || (vmf.vmf_eax != 0x4f));
}
@@ -341,14 +342,18 @@ static int
vesa_bios_save_restore(int code, void *p, size_t size)
{
struct vm86frame vmf;
+ u_char *buf;
int err;
bzero(&vmf, sizeof(vmf));
vmf.vmf_eax = 0x4f04;
vmf.vmf_ecx = STATE_MOST;
vmf.vmf_edx = code; /* STATE_SAVE/STATE_LOAD */
- err = vm86_datacall(0x10, &vmf, (char *)p, size,
- &vmf.vmf_es, &vmf.vmf_bx);
+ buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
+ vm86_getptr(&vesa_vmcontext, buf, &vmf.vmf_es, &vmf.vmf_di);
+ bcopy(p, buf, size);
+
+ err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
return ((err != 0) || (vmf.vmf_eax != 0x4f));
}
@@ -427,9 +432,9 @@ static void
static int
vesa_bios_init(void)
{
- static u_char buf[512];
struct vm86frame vmf;
struct vesa_mode vmode;
+ u_char *buf;
int modes;
int err;
int i;
@@ -441,12 +446,13 @@ vesa_bios_init(void)
vesa_adp_info = NULL;
vesa_vmode[0].vi_mode = EOT;
+ buf = (u_char *)vm86_addpage(&vesa_vmcontext, 1, 0);
bzero(&vmf, sizeof(vmf)); /* paranoia */
- bzero(buf, sizeof(buf));
bcopy("VBE2", buf, 4); /* try for VBE2 data */
vmf.vmf_eax = 0x4f00;
- err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
- &vmf.vmf_es, &vmf.vmf_di);
+ vm86_getptr(&vesa_vmcontext, buf, &vmf.vmf_es, &vmf.vmf_di);
+
+ err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
if ((err != 0) || (vmf.vmf_eax != 0x4f) || bcmp("VESA", buf, 4))
return 1;
vesa_adp_info = (struct vesa_info *)buf;