Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>

@@ -22,11 +22,11 @@
  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Copyright (c) 2010, Intel Corporation.
  * All rights reserved.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
  */
 
 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
 /*      All Rights Reserved   */
 

@@ -362,11 +362,96 @@
 #define CONTIG_LOCK()   mutex_enter(&contig_lock);
 #define CONTIG_UNLOCK() mutex_exit(&contig_lock);
 
 #define PFN_16M         (mmu_btop((uint64_t)0x1000000))
 
+caddr_t
+i86devmap(pfn_t pf, pgcnt_t pgcnt, uint_t prot)
+{
+        caddr_t addr;
+        caddr_t addr1;
+        page_t *pp;
+
+        addr1 = addr = vmem_alloc(heap_arena, mmu_ptob(pgcnt), VM_SLEEP);
+
+        for (; pgcnt != 0; addr += MMU_PAGESIZE, ++pf, --pgcnt) {
+                pp = page_numtopp_nolock(pf);
+                if (pp == NULL) {
+                        hat_devload(kas.a_hat, addr, MMU_PAGESIZE, pf,
+                            prot | HAT_NOSYNC, HAT_LOAD_LOCK);
+                } else {
+                        hat_memload(kas.a_hat, addr, pp,
+                            prot | HAT_NOSYNC, HAT_LOAD_LOCK);
+                }
+        }
+
+        return (addr1);
+}
+
 /*
+ * This routine is like page_numtopp, but accepts only free pages, which
+ * it allocates (unfrees) and returns with the exclusive lock held.
+ * It is used by machdep.c/dma_init() to find contiguous free pages.
+ */
+page_t *
+page_numtopp_alloc(pfn_t pfnum)
+{
+        page_t *pp;
+
+retry:
+        pp = page_numtopp_nolock(pfnum);
+        if (pp == NULL) {
+                return (NULL);
+        }
+
+        if (!page_trylock(pp, SE_EXCL)) {
+                return (NULL);
+        }
+
+        if (page_pptonum(pp) != pfnum) {
+                page_unlock(pp);
+                goto retry;
+        }
+
+        if (!PP_ISFREE(pp)) {
+                page_unlock(pp);
+                return (NULL);
+        }
+        if (pp->p_szc) {
+                page_demote_free_pages(pp);
+                page_unlock(pp);
+                goto retry;
+        }
+
+        /* If associated with a vnode, destroy mappings */
+
+        if (pp->p_vnode) {
+
+                page_destroy_free(pp);
+
+                if (!page_lock(pp, SE_EXCL, (kmutex_t *)NULL, P_NO_RECLAIM)) {
+                        return (NULL);
+                }
+
+                if (page_pptonum(pp) != pfnum) {
+                        page_unlock(pp);
+                        goto retry;
+                }
+        }
+
+        if (!PP_ISFREE(pp)) {
+                page_unlock(pp);
+                return (NULL);
+        }
+
+        if (!page_reclaim(pp, (kmutex_t *)NULL))
+                return (NULL);
+
+        return (pp);
+}
+
+/*
  * Return the optimum page size for a given mapping
  */
 /*ARGSUSED*/
 size_t
 map_pgsz(int maptype, struct proc *p, caddr_t addr, size_t len, int memcntl)