]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/mmu.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / mmu.c
index ca504613302a2b752fc5af576a28b50cd79f6cf7..c0b13674a6cab1083b782d7c4dbcb4480ac96416 100644 (file)
@@ -59,7 +59,6 @@ Segdesc gdt[NGDT] =
 [KESEG16]              EXEC16SEGM(0),  /* kernel code 16-bit */
 };
 
-static int didmmuinit;
 static void taskswitch(ulong, ulong);
 static void memglobal(void);
 
@@ -67,19 +66,17 @@ static void memglobal(void);
 #define        VPTX(va)                (((ulong)(va))>>12)
 #define        vpd (vpt+VPTX(VPT))
 
-void
-mmuinit0(void)
-{
-       memmove(m->gdt, gdt, sizeof gdt);
-}
+enum {
+       /* PAT entry used for write combining */
+       PATWC   = 7,
+};
 
 void
 mmuinit(void)
 {
        ulong x, *p;
        ushort ptr[3];
-
-       didmmuinit = 1;
+       vlong v;
 
        if(0) print("vpt=%#.8ux vpd=%#p kmap=%#.8ux\n",
                VPT, vpd, KMAP);
@@ -128,6 +125,14 @@ mmuinit(void)
 
        taskswitch(PADDR(m->pdb),  (ulong)m + BY2PG);
        ltr(TSSSEL);
+
+       /* IA32_PAT write combining */
+       if((MACHP(0)->cpuiddx & Pat) != 0
+       && rdmsr(0x277, &v) != -1){
+               v &= ~(255LL<<(PATWC*8));
+               v |= 1LL<<(PATWC*8);    /* WC */
+               wrmsr(0x277, v);
+       }
 }
 
 /* 
@@ -193,7 +198,7 @@ flushmmu(void)
 void
 flushpg(ulong va)
 {
-       if(X86FAMILY(m->cpuidax) >= 4)
+       if(m->cpuidfamily >= 4)
                invlpg(va);
        else
                putcr3(getcr3());
@@ -303,7 +308,7 @@ mmuswitch(Proc* proc)
                proc->newtlb = 0;
        }
 
-       if(proc->mmupdb){
+       if(proc->mmupdb != nil){
                pdb = tmpmap(proc->mmupdb);
                pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
                tmpunmap(pdb);
@@ -341,11 +346,11 @@ mmurelease(Proc* proc)
        if(islo())
                panic("mmurelease: islo");
        taskswitch(PADDR(m->pdb), (ulong)m + BY2PG);
-       if(proc->kmaptable){
+       if(proc->kmaptable != nil){
                if(proc->mmupdb == nil)
                        panic("mmurelease: no mmupdb");
-               if(--proc->kmaptable->ref)
-                       panic("mmurelease: kmap ref %d", proc->kmaptable->ref);
+               if(--proc->kmaptable->ref != 0)
+                       panic("mmurelease: kmap ref %ld", proc->kmaptable->ref);
                if(proc->nkmap)
                        panic("mmurelease: nkmap %d", proc->nkmap);
                /*
@@ -361,23 +366,23 @@ mmurelease(Proc* proc)
                 * move kmaptable to free list.
                 */
                pagechainhead(proc->kmaptable);
-               proc->kmaptable = 0;
+               proc->kmaptable = nil;
        }
-       if(proc->mmupdb){
+       if(proc->mmupdb != nil){
                mmuptefree(proc);
                mmupdbfree(proc, proc->mmupdb);
-               proc->mmupdb = 0;
+               proc->mmupdb = nil;
        }
-       for(page = proc->mmufree; page; page = next){
+       for(page = proc->mmufree; page != nil; page = next){
                next = page->next;
-               if(--page->ref)
-                       panic("mmurelease: page->ref %d", page->ref);
+               if(--page->ref != 0)
+                       panic("mmurelease: page->ref %ld", page->ref);
                pagechainhead(page);
        }
-       if(proc->mmufree && palloc.r.p)
-               wakeup(&palloc.r);
-       proc->mmufree = 0;
-       if(proc->ldt){
+       if(proc->mmufree != nil)
+               pagechaindone();
+       proc->mmufree = nil;
+       if(proc->ldt != nil){
                free(proc->ldt);
                proc->ldt = nil;
                proc->nldt = 0;
@@ -421,7 +426,7 @@ upallocpdb(void)
  * Update the mmu in response to a user fault.  pa may have PTEWRITE set.
  */
 void
-putmmu(ulong va, ulong pa, Page*)
+putmmu(uintptr va, uintptr pa, Page*)
 {
        int old, s;
        Page *page;
@@ -518,17 +523,8 @@ mmuwalk(ulong* pdb, ulong va, int level, int create)
                if(*table & PTESIZE)
                        panic("mmuwalk2: va %luX entry %luX", va, *table);
                if(!(*table & PTEVALID)){
-                       /*
-                        * Have to call low-level allocator from
-                        * memory.c if we haven't set up the xalloc
-                        * tables yet.
-                        */
-                       if(didmmuinit)
-                               map = xspanalloc(BY2PG, BY2PG, 0);
-                       else
-                               map = rampage();
-                       if(map == nil)
-                               panic("mmuwalk xspanalloc failed");
+                       map = rampage();
+                       memset(map, 0, BY2PG);
                        *table = PADDR(map)|PTEWRITE|PTEVALID;
                }
                table = KADDR(PPN(*table));
@@ -547,6 +543,7 @@ static Lock vmaplock;
 
 static int findhole(ulong *a, int n, int count);
 static ulong vmapalloc(ulong size);
+static int pdbmap(ulong *, ulong, ulong, int);
 static void pdbunmap(ulong*, ulong, int);
 
 /*
@@ -646,10 +643,7 @@ vmapalloc(ulong size)
 void
 vunmap(void *v, int size)
 {
-       int i;
        ulong va, o;
-       Mach *nm;
-       Proc *p;
        
        /*
         * might not be aligned
@@ -674,35 +668,18 @@ vunmap(void *v, int size)
         * boot. In that case it suffices to flush the MACH(0) TLB
         * and return.
         */
-       if(!active.thunderbirdsarego){
+       if(up == nil){
                putcr3(PADDR(MACHP(0)->pdb));
                return;
        }
-       for(i=0; i<conf.nproc; i++){
-               p = proctab(i);
-               if(p->state == Dead)
-                       continue;
-               if(p != up)
-                       p->newtlb = 1;
-       }
-       for(i=0; i<conf.nmach; i++){
-               nm = MACHP(i);
-               if(nm != m)
-                       nm->flushmmu = 1;
-       }
+       procflushothers();
        flushmmu();
-       for(i=0; i<conf.nmach; i++){
-               nm = MACHP(i);
-               if(nm != m)
-                       while((active.machs&(1<<nm->machno)) && nm->flushmmu)
-                               ;
-       }
 }
 
 /*
  * Add kernel mappings for pa -> va for a section of size bytes.
  */
-int
+static int
 pdbmap(ulong *pdb, ulong pa, ulong va, int size)
 {
        int pse;
@@ -772,6 +749,19 @@ pdbunmap(ulong *pdb, ulong va, int size)
        }
 }
 
+void
+pmap(ulong pa, ulong va, int size)
+{
+       pdbmap(MACHP(0)->pdb, pa, va, size);
+}
+
+void
+punmap(ulong va, int size)
+{
+       pdbunmap(MACHP(0)->pdb, va, size);
+       mmuflushtlb(PADDR(m->pdb));
+}
+
 /*
  * Handle a fault by bringing vmap up to date.
  * Only copy pdb entries and they never go away,
@@ -947,7 +937,7 @@ tmpunmap(void *v)
 void*
 kaddr(ulong pa)
 {
-       if(pa > (ulong)-KZERO)
+       if(pa >= (ulong)-KZERO)
                panic("kaddr: pa=%#.8lux", pa);
        return (void*)(pa+KZERO);
 }
@@ -966,97 +956,6 @@ paddr(void *v)
 /*
  * More debugging.
  */
-void
-countpagerefs(ulong *ref, int print)
-{
-       int i, n;
-       Mach *mm;
-       Page *pg;
-       Proc *p;
-       
-       n = 0;
-       for(i=0; i<conf.nproc; i++){
-               p = proctab(i);
-               if(p->mmupdb){
-                       if(print){
-                               if(ref[pagenumber(p->mmupdb)])
-                                       iprint("page %#.8lux is proc %d (pid %lud) pdb\n",
-                                               p->mmupdb->pa, i, p->pid);
-                               continue;
-                       }
-                       if(ref[pagenumber(p->mmupdb)]++ == 0)
-                               n++;
-                       else
-                               iprint("page %#.8lux is proc %d (pid %lud) pdb but has other refs!\n",
-                                       p->mmupdb->pa, i, p->pid);
-               }
-               if(p->kmaptable){
-                       if(print){
-                               if(ref[pagenumber(p->kmaptable)])
-                                       iprint("page %#.8lux is proc %d (pid %lud) kmaptable\n",
-                                               p->kmaptable->pa, i, p->pid);
-                               continue;
-                       }
-                       if(ref[pagenumber(p->kmaptable)]++ == 0)
-                               n++;
-                       else
-                               iprint("page %#.8lux is proc %d (pid %lud) kmaptable but has other refs!\n",
-                                       p->kmaptable->pa, i, p->pid);
-               }
-               for(pg=p->mmuused; pg; pg=pg->next){
-                       if(print){
-                               if(ref[pagenumber(pg)])
-                                       iprint("page %#.8lux is on proc %d (pid %lud) mmuused\n",
-                                               pg->pa, i, p->pid);
-                               continue;
-                       }
-                       if(ref[pagenumber(pg)]++ == 0)
-                               n++;
-                       else
-                               iprint("page %#.8lux is on proc %d (pid %lud) mmuused but has other refs!\n",
-                                       pg->pa, i, p->pid);
-               }
-               for(pg=p->mmufree; pg; pg=pg->next){
-                       if(print){
-                               if(ref[pagenumber(pg)])
-                                       iprint("page %#.8lux is on proc %d (pid %lud) mmufree\n",
-                                               pg->pa, i, p->pid);
-                               continue;
-                       }
-                       if(ref[pagenumber(pg)]++ == 0)
-                               n++;
-                       else
-                               iprint("page %#.8lux is on proc %d (pid %lud) mmufree but has other refs!\n",
-                                       pg->pa, i, p->pid);
-               }
-       }
-       if(!print)
-               iprint("%d pages in proc mmu\n", n);
-       n = 0;
-       for(i=0; i<conf.nmach; i++){
-               mm = MACHP(i);
-               for(pg=mm->pdbpool; pg; pg=pg->next){
-                       if(print){
-                               if(ref[pagenumber(pg)])
-                                       iprint("page %#.8lux is in cpu%d pdbpool\n",
-                                               pg->pa, i);
-                               continue;
-                       }
-                       if(ref[pagenumber(pg)]++ == 0)
-                               n++;
-                       else
-                               iprint("page %#.8lux is in cpu%d pdbpool but has other refs!\n",
-                                       pg->pa, i);
-               }
-       }
-       if(!print){
-               iprint("%d pages in mach pdbpools\n", n);
-               for(i=0; i<conf.nmach; i++)
-                       iprint("cpu%d: %d pdballoc, %d pdbfree\n",
-                               i, MACHP(i)->pdballoc, MACHP(i)->pdbfree);
-       }
-}
-
 void
 checkfault(ulong, ulong)
 {
@@ -1074,3 +973,36 @@ cankaddr(ulong pa)
        return -KZERO - pa;
 }
 
+/*
+ * mark pages as write combining (used for framebuffer)
+ */
+void
+patwc(void *a, int n)
+{
+       ulong *pte, mask, attr, va;
+       vlong v;
+       int z;
+
+       /* check if pat is usable */
+       if((MACHP(0)->cpuiddx & Pat) == 0
+       || rdmsr(0x277, &v) == -1
+       || ((v >> PATWC*8) & 7) != 1)
+               return;
+
+       /* set the bits for all pages in range */
+       for(va = (ulong)a; n > 0; n -= z, va += z){
+               pte = mmuwalk(MACHP(0)->pdb, va, 1, 0);
+               if(pte && (*pte & (PTEVALID|PTESIZE)) == (PTEVALID|PTESIZE)){
+                       z = 4*MB - (va & (4*MB-1));
+                       mask = 3<<3 | 1<<12;
+               } else {
+                       pte = mmuwalk(MACHP(0)->pdb, va, 2, 0);
+                       if(pte == 0 || (*pte & PTEVALID) == 0)
+                               panic("patwc: va=%#p", va);
+                       z = BY2PG - (va & (BY2PG-1));
+                       mask = 3<<3 | 1<<7;
+               }
+               attr = (((PATWC&3)<<3) | ((PATWC&4)<<5) | ((PATWC&4)<<10));
+               *pte = (*pte & ~mask) | (attr & mask);
+       }
+}