diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-01-24 05:27:33 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2020-01-24 05:27:33 +0000 |
commit | 30fc9d119e30bf22d052c977d18372070ccb6d58 (patch) | |
tree | 394b993e80d3918424828f077c5978ac46cc985f /sys/arch | |
parent | 719379108dc1273e171fba00dab795b25d555e33 (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.c | 25 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/locore0.S | 9 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 13 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/pmap.c | 74 | ||||
-rw-r--r-- | sys/arch/amd64/include/pmap.h | 6 |
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. |