summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-01-24 05:27:33 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-01-24 05:27:33 +0000
commit30fc9d119e30bf22d052c977d18372070ccb6d58 (patch)
tree394b993e80d3918424828f077c5978ac46cc985f /sys/arch
parent719379108dc1273e171fba00dab795b25d555e33 (diff)
Machines have started to appear that have the framebuffer at an address > 4GB.
On these machines we can't use the direct map since early on during boot the direct map only covers the first 4GB of memory. Instead, use a special (and temporary) mapping until we remap the framebuffer near the start of autoconf. With lots of help from mlarkin@ tested by yasuoka@ ok mlarkin@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/amd64/amd64/efifb.c25
-rw-r--r--sys/arch/amd64/amd64/locore0.S9
-rw-r--r--sys/arch/amd64/amd64/machdep.c13
-rw-r--r--sys/arch/amd64/amd64/pmap.c74
-rw-r--r--sys/arch/amd64/include/pmap.h6
5 files changed, 116 insertions, 11 deletions
diff --git a/sys/arch/amd64/amd64/efifb.c b/sys/arch/amd64/amd64/efifb.c
index 44c2478463e..69d6a01bad4 100644
--- a/sys/arch/amd64/amd64/efifb.c
+++ b/sys/arch/amd64/amd64/efifb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: efifb.c,v 1.26 2019/11/26 02:20:50 jsg Exp $ */
+/* $OpenBSD: efifb.c,v 1.27 2020/01/24 05:27:31 kettenis Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@@ -105,6 +105,8 @@ int efifb_load_font(void *, void *, struct wsdisplay_font *);
void efifb_scrollback(void *, void *, int lines);
void efifb_efiinfo_init(struct efifb *);
void efifb_cnattach_common(void);
+vaddr_t efifb_early_map(paddr_t);
+void efifb_early_cleanup(void);
struct cb_framebuffer *cb_find_fb(paddr_t);
@@ -430,7 +432,7 @@ efifb_cnattach_common(void)
struct rasops_info *ri = &fb->rinfo;
long defattr = 0;
- ri->ri_bits = (u_char *)PMAP_DIRECT_MAP(fb->paddr);
+ ri->ri_bits = (u_char *)efifb_early_map(fb->paddr);
efifb_rasops_preinit(fb);
@@ -459,14 +461,17 @@ efifb_cnremap(void)
return;
if (_bus_space_map(iot, fb->paddr, fb->psize,
- BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR, &ioh) == 0)
- ri->ri_origbits = bus_space_vaddr(iot, ioh);
+ BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR, &ioh))
+ panic("can't remap framebuffer");
+ ri->ri_origbits = bus_space_vaddr(iot, ioh);
efifb_rasops_preinit(fb);
ri->ri_flg &= ~RI_CLEAR;
ri->ri_flg |= RI_CENTER | RI_WRONLY;
rasops_init(ri, efifb_std_descr.nrows, efifb_std_descr.ncols);
+
+ efifb_early_cleanup();
}
int
@@ -637,3 +642,15 @@ efifb_stolen(void)
struct efifb *fb = &efifb_console;
return fb->psize;
}
+
+vaddr_t
+efifb_early_map(paddr_t pa)
+{
+ return pmap_set_pml4_early(pa);
+}
+
+void
+efifb_early_cleanup(void)
+{
+ pmap_clear_pml4_early();
+}
diff --git a/sys/arch/amd64/amd64/locore0.S b/sys/arch/amd64/amd64/locore0.S
index 3be32d5718d..62d31e89917 100644
--- a/sys/arch/amd64/amd64/locore0.S
+++ b/sys/arch/amd64/amd64/locore0.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore0.S,v 1.17 2019/02/18 08:26:20 yasuoka Exp $ */
+/* $OpenBSD: locore0.S,v 1.18 2020/01/24 05:27:31 kettenis Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -321,7 +321,7 @@ cont:
#define PROC0_DMP2_OFF (PROC0_DMP3_OFF + NDML3_ENTRIES * NBPG)
#define TABLESIZE \
((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES + \
- NDML3_ENTRIES + NDML2_ENTRIES) * NBPG)
+ NDML3_ENTRIES + NDML2_ENTRIES + 3) * NBPG)
#define fillkpt \
1: movl %eax,(%ebx) ; /* store phys addr */ \
@@ -669,10 +669,11 @@ longmode_hi:
movw %ax,%gs
movw %ax,%fs
- /* XXX merge these */
leaq TABLESIZE(%rsi),%rdi
- call _C_LABEL(init_x86_64)
+ subq $(NBPG*3), %rdi
+ /* XXX merge these */
+ call _C_LABEL(init_x86_64)
call _C_LABEL(main)
.section .codepatch,"a"
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index f2d96f949ea..21c88098743 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.260 2019/12/20 07:49:31 jsg Exp $ */
+/* $OpenBSD: machdep.c,v 1.261 2020/01/24 05:27:31 kettenis Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -1365,6 +1365,8 @@ map_tramps(void)
typedef void (vector)(void);
extern vector *IDTVEC(exceptions)[];
+paddr_t early_pte_pages;
+
void
init_x86_64(paddr_t first_avail)
{
@@ -1373,6 +1375,15 @@ init_x86_64(paddr_t first_avail)
int x, ist;
uint64_t max_dm_size = ((uint64_t)512 * NUM_L4_SLOT_DIRECT) << 30;
+ /*
+ * locore0 mapped 3 pages for use before the pmap is initialized
+ * starting at first_avail. These pages are currently used by
+ * efifb to create early-use VAs for the framebuffer before efifb
+ * is attached.
+ */
+ early_pte_pages = first_avail;
+ first_avail += 3 * NBPG;
+
cpu_init_msrs(&cpu_info_primary);
proc0.p_addr = proc0paddr;
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
index 5ca512aadda..42f25b12000 100644
--- a/sys/arch/amd64/amd64/pmap.c
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.137 2019/12/19 17:42:17 mpi Exp $ */
+/* $OpenBSD: pmap.c,v 1.138 2020/01/24 05:27:31 kettenis Exp $ */
/* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
/*
@@ -544,6 +544,78 @@ pmap_kremove(vaddr_t sva, vsize_t len)
}
/*
+ * pmap_set_pml4_early
+ *
+ * Utility function to map 2GB of 2MB pages to 'pa'. The VA that is assigned
+ * is the pml4 entry for 'early mappings' (see pmap.h). This function is used
+ * by display drivers that need to map their framebuffers early, before the
+ * pmap is fully initialized (eg, to show panic messages).
+ *
+ * Users of this function must call pmap_clear_pml4_early to remove the
+ * mapping when finished.
+ *
+ * Parameters:
+ * pa: phys addr to map
+ *
+ * Return value:
+ * VA mapping to 'pa'. This mapping is 2GB in size and starts at the base
+ * of the 2MB region containing 'va'.
+ */
+vaddr_t
+pmap_set_pml4_early(paddr_t pa)
+{
+ extern paddr_t early_pte_pages;
+ pt_entry_t *pml4e, *pte;
+ int i, j, off;
+ paddr_t curpa;
+ vaddr_t va;
+
+ pml4e = (pt_entry_t *)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE);
+ pml4e[PDIR_SLOT_EARLY] = (pd_entry_t)early_pte_pages | PG_V | PG_RW;
+
+ off = pa & PAGE_MASK_L2;
+ curpa = pa & L2_FRAME;
+
+ pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages);
+ memset(pte, 0, 3 * NBPG);
+
+ pte[0] = (early_pte_pages + NBPG) | PG_V | PG_RW;
+ pte[1] = (early_pte_pages + 2 * NBPG) | PG_V | PG_RW;
+
+ pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages + NBPG);
+ for (i = 0; i < 2; i++) {
+ /* 2 early pages of mappings */
+ for (j = 0; j < 512; j++) {
+ /* j[0..511] : 2MB mappings per page */
+ pte[(i * 512) + j] = curpa | PG_V | PG_RW | PG_PS;
+ curpa += (2 * 1024 * 1024);
+ }
+ }
+
+ va = (vaddr_t)((PDIR_SLOT_EARLY * 512ULL) << L3_SHIFT) + off;
+ return VA_SIGN_NEG(va);
+}
+
+/*
+ * pmap_clear_pml4_early
+ *
+ * Clears the mapping previously established with pmap_set_pml4_early.
+ */
+void
+pmap_clear_pml4_early(void)
+{
+ extern paddr_t early_pte_pages;
+ pt_entry_t *pml4e, *pte;
+
+ pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages);
+ memset(pte, 0, 3 * NBPG);
+
+ pml4e = (pd_entry_t *)pmap_kernel()->pm_pdir;
+ pml4e[PDIR_SLOT_EARLY] = 0;
+ tlbflush();
+}
+
+/*
* p m a p i n i t f u n c t i o n s
*
* pmap_bootstrap and pmap_init are called during system startup
diff --git a/sys/arch/amd64/include/pmap.h b/sys/arch/amd64/include/pmap.h
index a2180a05b1b..bcce28080ac 100644
--- a/sys/arch/amd64/include/pmap.h
+++ b/sys/arch/amd64/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.76 2019/12/19 17:42:17 mpi Exp $ */
+/* $OpenBSD: pmap.h,v 1.77 2020/01/24 05:27:32 kettenis Exp $ */
/* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */
/*
@@ -143,10 +143,12 @@
#define L4_SLOT_KERNBASE 511
#define NUM_L4_SLOT_DIRECT 4
#define L4_SLOT_DIRECT (L4_SLOT_KERNBASE - NUM_L4_SLOT_DIRECT)
+#define L4_SLOT_EARLY (L4_SLOT_DIRECT - 1)
#define PDIR_SLOT_KERN L4_SLOT_KERN
#define PDIR_SLOT_PTE L4_SLOT_PTE
#define PDIR_SLOT_DIRECT L4_SLOT_DIRECT
+#define PDIR_SLOT_EARLY L4_SLOT_EARLY
/*
* the following defines give the virtual addresses of various MMU
@@ -401,6 +403,8 @@ void pagezero(vaddr_t);
int pmap_convert(struct pmap *, int);
void pmap_enter_special(vaddr_t, paddr_t, vm_prot_t);
+vaddr_t pmap_set_pml4_early(paddr_t pa);
+void pmap_clear_pml4_early(void);
/*
* functions for flushing the cache for vaddrs and pages.