summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2015-07-17 21:36:57 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2015-07-17 21:36:57 +0000
commit89d278d7fc97dc41c3878adce3f703cda41a32b1 (patch)
treeb68d76414acb9f8d907e7f704d330afb5013772c
parent55aa389fb6be51c59d1cb9d28361af2c4e8e38c5 (diff)
Include executable mapping for BIOS32 pages. Fixes a problem where mappings
done in this region using PAE w/NX caused #PFs (as they lacked the exec permission previously). Also unmap the region when we're finished. No sense in leaving extra executable regions lying around. Fixes non-ACPI uniprocessor i386 machines that have NX/PAE (these would previously panic in pcibiosattach). ok deraadt@
-rw-r--r--sys/arch/i386/i386/bios.c35
-rw-r--r--sys/arch/i386/include/biosvar.h3
-rw-r--r--sys/arch/i386/pci/pcibios.c4
3 files changed, 34 insertions, 8 deletions
diff --git a/sys/arch/i386/i386/bios.c b/sys/arch/i386/i386/bios.c
index f4dd2b8c0d4..e40cab7f276 100644
--- a/sys/arch/i386/i386/bios.c
+++ b/sys/arch/i386/i386/bios.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bios.c,v 1.109 2015/01/21 18:39:54 tedu Exp $ */
+/* $OpenBSD: bios.c,v 1.110 2015/07/17 21:36:56 mlarkin Exp $ */
/*
* Copyright (c) 1997-2001 Michael Shalayeff
@@ -84,6 +84,7 @@
struct bios_softc {
struct device sc_dev;
+ vaddr_t bios32_service_va;
};
int biosprobe(struct device *, void *, void *);
@@ -110,6 +111,7 @@ bios_pciinfo_t *bios_pciinfo;
#endif
bios_diskinfo_t *bios_diskinfo;
bios_memmap_t *bios_memmap;
+struct bios_softc *bios_softc;
u_int32_t bios_cksumlen;
struct bios32_entry bios32_entry;
struct smbios_entry smbios_entry;
@@ -173,6 +175,7 @@ biosattach(struct device *parent, struct device *self, void *aux)
int usingacpi = 0;
#endif
+ bios_softc = sc;
/* remember flags */
flags = sc->sc_dev.dv_cfdata->cf_flags;
@@ -648,13 +651,15 @@ bios32_service(u_int32_t service, bios32_entry_t e, bios32_entry_info_t ei)
if (ent <= BIOS32_START || ent >= BIOS32_END)
return 0;
-
endpa = round_page(BIOS32_END);
sva = va = uvm_km_valloc(kernel_map, endpa);
if (va == 0)
return (0);
+ /* Store bios32 service kva for cleanup later */
+ bios_softc->bios32_service_va = sva;
+
slot = gdt_get_slot();
setgdt(slot, (caddr_t)va, BIOS32_END, SDT_MEMERA, SEL_KPL, 1, 0);
@@ -662,14 +667,14 @@ bios32_service(u_int32_t service, bios32_entry_t e, bios32_entry_info_t ei)
va += trunc_page(BIOS32_START);
pa < endpa; pa += NBPG, va += NBPG) {
pmap_enter(pmap_kernel(), va, pa,
- PROT_READ | PROT_WRITE,
- PROT_READ | PROT_WRITE | PMAP_WIRED);
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ PROT_READ | PROT_WRITE | PROT_EXEC | PMAP_WIRED);
/* for all you, broken hearted */
if (pa >= trunc_page(base)) {
pmap_enter(pmap_kernel(), sva, pa,
- PROT_READ | PROT_WRITE,
- PROT_READ | PROT_WRITE | PMAP_WIRED);
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ PROT_READ | PROT_WRITE | PROT_EXEC | PMAP_WIRED);
sva += NBPG;
}
}
@@ -684,6 +689,24 @@ bios32_service(u_int32_t service, bios32_entry_t e, bios32_entry_info_t ei)
return 1;
}
+void
+bios32_cleanup(void)
+{
+ u_long pa, size;
+ vaddr_t va;
+
+ size = round_page(BIOS32_END);
+
+ for (va = bios_softc->bios32_service_va;
+ va < bios_softc->bios32_service_va + size;
+ va += NBPG) {
+ if (pmap_extract(pmap_kernel(), va, &pa))
+ pmap_remove(pmap_kernel(), va, va + PAGE_SIZE);
+ }
+
+ uvm_km_free(kernel_map, bios_softc->bios32_service_va, size);
+}
+
int
biosopen(dev_t dev, int flag, int mode, struct proc *p)
{
diff --git a/sys/arch/i386/include/biosvar.h b/sys/arch/i386/include/biosvar.h
index afe03ffe631..9852bd8b45d 100644
--- a/sys/arch/i386/include/biosvar.h
+++ b/sys/arch/i386/include/biosvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: biosvar.h,v 1.62 2015/04/12 18:37:54 mlarkin Exp $ */
+/* $OpenBSD: biosvar.h,v 1.63 2015/07/17 21:36:56 mlarkin Exp $ */
/*
* Copyright (c) 1997-1999 Michael Shalayeff
@@ -268,6 +268,7 @@ void bios_getopt(void);
/* bios32.c */
int bios32_service(u_int32_t, bios32_entry_t, bios32_entry_info_t);
+void bios32_cleanup(void);
extern u_int bootapiver;
extern bios_memmap_t *bios_memmap;
diff --git a/sys/arch/i386/pci/pcibios.c b/sys/arch/i386/pci/pcibios.c
index ddf28cd2b4d..39c824d4824 100644
--- a/sys/arch/i386/pci/pcibios.c
+++ b/sys/arch/i386/pci/pcibios.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcibios.c,v 1.45 2014/07/12 18:44:42 tedu Exp $ */
+/* $OpenBSD: pcibios.c,v 1.46 2015/07/17 21:36:56 mlarkin Exp $ */
/* $NetBSD: pcibios.c,v 1.5 2000/08/01 05:23:59 uch Exp $ */
/*
@@ -228,6 +228,8 @@ pcibiosattach(struct device *parent, struct device *self, void *aux)
if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP))
pci_addr_fixup(sc, NULL, sc->max_bus);
+
+ bios32_cleanup();
}
struct pcibios_intr_routing *