From owner-p4-projects@FreeBSD.ORG Tue Aug 26 19:56:01 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0D6C71065678; Tue, 26 Aug 2008 19:56:01 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C59971065674 for ; Tue, 26 Aug 2008 19:56:00 +0000 (UTC) (envelope-from nwhitehorn@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id A18988FC1A for ; Tue, 26 Aug 2008 19:56:00 +0000 (UTC) (envelope-from nwhitehorn@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.2/8.14.2) with ESMTP id m7QJu0UP004110 for ; Tue, 26 Aug 2008 19:56:00 GMT (envelope-from nwhitehorn@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m7QJu09K004108 for perforce@freebsd.org; Tue, 26 Aug 2008 19:56:00 GMT (envelope-from nwhitehorn@freebsd.org) Date: Tue, 26 Aug 2008 19:56:00 GMT Message-Id: <200808261956.m7QJu09K004108@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to nwhitehorn@freebsd.org using -f From: Nathan Whitehorn To: Perforce Change Reviews Cc: Subject: PERFORCE change 148545 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Aug 2008 19:56:01 -0000 http://perforce.freebsd.org/chv.cgi?CH=148545 Change 148545 by nwhitehorn@nwhitehorn_trantor on 2008/08/26 19:55:27 Support for the G5 as it currently stands. Boots multiuser and is self-hosting on my iMac. Built-in SATA nonfunctional, and INVARIANTS is broken. Affected files ... .. //depot/projects/ppc-g5/lib/libc/powerpc/gen/syncicache.c#2 edit .. //depot/projects/ppc-g5/sys/conf/files.powerpc#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/machdep.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/mmu_oea.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/mmu_oea64.c#1 add .. //depot/projects/ppc-g5/sys/powerpc/aim/ofw_machdep.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/trap_subr.S#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/uio_machdep.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/uma_machdep.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/aim/vm_machdep.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/booke/machdep.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/hid.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/md_var.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/pmap.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/pte.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/sf_buf.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/spr.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/include/vmparam.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pci.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/ata_kauai.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/cpcht.c#1 add .. //depot/projects/ppc-g5/sys/powerpc/powermac/cpchtvar.h#1 add .. //depot/projects/ppc-g5/sys/powerpc/powermac/macio.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/uninorth.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/uninorthvar.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powerpc/cpu.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powerpc/syncicache.c#2 edit Differences ... ==== //depot/projects/ppc-g5/lib/libc/powerpc/gen/syncicache.c#2 (text+ko) ==== @@ -48,27 +48,23 @@ #include #if defined(_KERNEL) || defined(_STANDALONE) -#ifndef CACHELINESIZE -#error "Must know the size of a cache line" -#endif +int cacheline_size = 32; #else #include +static int cacheline_size; static void getcachelinesize(void); -static int _cachelinesize; -#define CACHELINESIZE _cachelinesize - static void getcachelinesize() { static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE }; int clen; - clen = sizeof(_cachelinesize); + clen = sizeof(cacheline_size); if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]), - &_cachelinesize, &clen, NULL, 0) < 0 || !_cachelinesize) { + &cacheline_size, &clen, NULL, 0) < 0 || !cacheline_size) { abort(); } } @@ -81,21 +77,23 @@ char *p; #if !defined(_KERNEL) && !defined(_STANDALONE) - if (!_cachelinesize) + if (!cacheline_size) getcachelinesize(); #endif - off = (u_int)from & (CACHELINESIZE - 1); + + off = (u_int)from & (cacheline_size - 1); l = len += off; p = (char *)from - off; + do { __asm __volatile ("dcbst 0,%0" :: "r"(p)); - p += CACHELINESIZE; - } while ((l -= CACHELINESIZE) > 0); + p += cacheline_size; + } while ((l -= cacheline_size) > 0); __asm __volatile ("sync"); p = (char *)from - off; do { __asm __volatile ("icbi 0,%0" :: "r"(p)); - p += CACHELINESIZE; - } while ((len -= CACHELINESIZE) > 0); + p += cacheline_size; + } while ((len -= cacheline_size) > 0); __asm __volatile ("sync; isync"); } ==== //depot/projects/ppc-g5/sys/conf/files.powerpc#2 (text+ko) ==== @@ -70,6 +70,7 @@ powerpc/aim/locore.S optional aim no-obj powerpc/aim/machdep.c optional aim powerpc/aim/mmu_oea.c optional aim +powerpc/aim/mmu_oea64.c optional aim powerpc/aim/mp_cpudep.c optional aim smp powerpc/aim/nexus.c optional aim powerpc/aim/ofw_machdep.c optional aim @@ -116,6 +117,7 @@ powerpc/powermac/openpic_macio.c optional powermac pci powerpc/powermac/pswitch.c optional powermac pswitch powerpc/powermac/uninorth.c optional powermac pci +powerpc/powermac/cpcht.c optional powermac pci powerpc/powerpc/atomic.S standard powerpc/powerpc/autoconf.c standard powerpc/powerpc/bcopy.c standard ==== //depot/projects/ppc-g5/sys/powerpc/aim/machdep.c#2 (text+ko) ==== @@ -128,6 +128,8 @@ #endif int cold = 1; +int ppc64 = 0; +int hw_direct_map = 1; struct pcpu __pcpu[MAXCPU]; @@ -136,7 +138,7 @@ char machine[] = "powerpc"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); -static int cacheline_size = CACHELINESIZE; +extern int cacheline_size; SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, CTLFLAG_RD, &cacheline_size, 0, ""); @@ -229,6 +231,9 @@ extern char kernel_text[], _end[]; +extern void *testppc64, *testppc64size; +extern void *restorebridge, *restorebridgesize; +extern void *rfid_patch, *rfi_patch1, *rfi_patch2; #ifdef SMP extern void *rstcode, *rstsize; #endif @@ -245,11 +250,15 @@ { struct pcpu *pc; vm_offset_t end; + size_t trap_offset; void *kmdp; char *env; + int vers; + uint32_t msr, scratch; end = 0; kmdp = NULL; + trap_offset = 0; /* * Parse metadata if present and fetch parameters. Must be done @@ -305,6 +314,26 @@ printf("powerpc_init: no loader metadata.\n"); } + /* + * Set cacheline_size based on the CPU model. + */ + + vers = mfpvr() >> 16; + switch (vers) { + case IBM970: + case IBM970FX: + case IBM970MP: + case IBM970GX: + cacheline_size = 128; + break; + default: + cacheline_size = 32; + } + + /* + * Init KDB and KOBJ + */ + kdb_init(); kobj_machdep_init(); @@ -314,47 +343,110 @@ * Disable translation in case the vector area * hasn't been mapped (G5) */ - mtmsr(mfmsr() & ~(PSL_IR | PSL_DR)); + msr = mfmsr(); + mtmsr(msr & ~(PSL_IR | PSL_DR)); isync(); + + /* + * Figure out whether we need to use the 64 bit PMAP. This works by + * executing an instruction that is only legal on 64-bit PPC (mtmsrd), + * and setting ppc64 = 0 if that causes a trap. + */ + + ppc64 = 1; + + bcopy(&testppc64, (void *)EXC_PGM, (size_t)&testppc64size); + __syncicache((void *)EXC_PGM, (size_t)&testppc64size); + + __asm __volatile("\ + mfmsr %0; \ + mtsprg2 %1; \ + \ + mtmsrd %0; \ + mfsprg2 %1;" + : "=r"(scratch), "=r"(ppc64)); + + /* + * Now copy restorebridge into all the handlers, if necessary, + * and set up the trap tables. + */ + + if (ppc64) { + /* Patch the two instances of rfi -> rfid */ + bcopy(&rfid_patch,&rfi_patch1,4); + bcopy(&rfid_patch,&rfi_patch2,4); + + /* Copy a code snippet to restore 32-bit bridge mode + * to the top of every trap handler */ + trap_offset += (size_t)&restorebridgesize; + bcopy(&restorebridge, (void *)EXC_RST, trap_offset); + bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset); + bcopy(&restorebridge, (void *)EXC_DSI, trap_offset); + bcopy(&restorebridge, (void *)EXC_ISI, trap_offset); + bcopy(&restorebridge, (void *)EXC_EXI, trap_offset); + bcopy(&restorebridge, (void *)EXC_ALI, trap_offset); + bcopy(&restorebridge, (void *)EXC_PGM, trap_offset); + bcopy(&restorebridge, (void *)EXC_FPU, trap_offset); + bcopy(&restorebridge, (void *)EXC_DECR, trap_offset); + bcopy(&restorebridge, (void *)EXC_SC, trap_offset); + bcopy(&restorebridge, (void *)EXC_TRC, trap_offset); + bcopy(&restorebridge, (void *)EXC_FPA, trap_offset); + bcopy(&restorebridge, (void *)EXC_VEC, trap_offset); + bcopy(&restorebridge, (void *)EXC_VECAST, trap_offset); + bcopy(&restorebridge, (void *)EXC_THRM, trap_offset); + bcopy(&restorebridge, (void *)EXC_BPT, trap_offset); + } + #ifdef SMP - bcopy(&rstcode, (void *)EXC_RST, (size_t)&rstsize); + bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstsize); #else - bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_RST + trap_offset), (size_t)&trapsize); +#endif + bcopy(&trapcode, (void *)(EXC_MCHK + trap_offset), (size_t)&trapsize); +#if 0 + if (ppc64) + bcopy(&alitrap, (void *)(EXC_DSI + trap_offset), (size_t)&alisize); + else #endif - bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize); - bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); - bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); - bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); - bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize); - bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize); - bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize); - bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize); + bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsisize); + bcopy(&trapcode, (void *)(EXC_ISI + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_EXI + trap_offset), (size_t)&trapsize); + bcopy(&alitrap, (void *)(EXC_ALI + trap_offset), (size_t)&alisize); + bcopy(&trapcode, (void *)(EXC_PGM + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_FPU + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_DECR + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_SC + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_TRC + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_FPA + trap_offset), (size_t)&trapsize); + bcopy(&vectrap, (void *)(EXC_VEC + trap_offset), (size_t)&vectrapsize); + bcopy(&trapcode, (void *)(EXC_VECAST + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_THRM + trap_offset), (size_t)&trapsize); + bcopy(&trapcode, (void *)(EXC_BPT + trap_offset), (size_t)&trapsize); #ifdef KDB - bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize); - bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize); + bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbsize); + bcopy(&dblow, (void *)(EXC_PGM + trap_offset), (size_t)&dbsize); + bcopy(&dblow, (void *)(EXC_TRC + trap_offset), (size_t)&dbsize); + bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbsize); #endif __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); /* - * Make sure translation has been enabled + * Restore MSR */ - mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); + mtmsr(msr); isync(); /* * Initialise virtual memory. */ - pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */ + if (ppc64) + pmap_mmu_install(MMU_TYPE_G5, 0); + else + pmap_mmu_install(MMU_TYPE_OEA, 0); + pmap_bootstrap(startkernel, endkernel); + mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); + isync(); /* * Initialize params/tunables that are derived from memsize ==== //depot/projects/ppc-g5/sys/powerpc/aim/mmu_oea.c#2 (text+ko) ==== @@ -714,6 +714,9 @@ __asm __volatile("mtdbatl 1,%0" :: "r"(battable[8].batl)); isync(); + /* set global direct map flag */ + hw_direct_map = 1; + mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz); CTR0(KTR_PMAP, "moea_bootstrap: physical memory"); @@ -952,9 +955,7 @@ * not issue any loads while we have interrupts disabled below. */ pm = &td->td_proc->p_vmspace->vm_pmap; - - if ((pmr = (pmap_t)moea_kextract(mmu, (vm_offset_t)pm)) == NULL) - pmr = pm; + pmr = pm->pmap_phys; pm->pm_active |= PCPU_GET(cpumask); PCPU_SET(curpmap, pmr); @@ -1206,7 +1207,7 @@ if (pvo == NULL) pa = 0; else - pa = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); + pa = (pvo->pvo_pte.pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); PMAP_UNLOCK(pm); return (pa); } @@ -1226,10 +1227,10 @@ vm_page_lock_queues(); PMAP_LOCK(pmap); pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL); - if (pvo != NULL && (pvo->pvo_pte.pte_hi & PTE_VALID) && - ((pvo->pvo_pte.pte_lo & PTE_PP) == PTE_RW || + if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID) && + ((pvo->pvo_pte.pte.pte_lo & PTE_PP) == PTE_RW || (prot & VM_PROT_WRITE) == 0)) { - m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN); + m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN); vm_page_hold(m); } vm_page_unlock_queues(); @@ -1300,15 +1301,15 @@ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { pmap = pvo->pvo_pmap; PMAP_LOCK(pmap); - if ((pvo->pvo_pte.pte_lo & PTE_PP) != PTE_BR) { + if ((pvo->pvo_pte.pte.pte_lo & PTE_PP) != PTE_BR) { pt = moea_pvo_to_pte(pvo, -1); - pvo->pvo_pte.pte_lo &= ~PTE_PP; - pvo->pvo_pte.pte_lo |= PTE_BR; + pvo->pvo_pte.pte.pte_lo &= ~PTE_PP; + pvo->pvo_pte.pte.pte_lo |= PTE_BR; if (pt != NULL) { - moea_pte_synch(pt, &pvo->pvo_pte); - lo |= pvo->pvo_pte.pte_lo; - pvo->pvo_pte.pte_lo &= ~PTE_CHG; - moea_pte_change(pt, &pvo->pvo_pte, + moea_pte_synch(pt, &pvo->pvo_pte.pte); + lo |= pvo->pvo_pte.pte.pte_lo; + pvo->pvo_pte.pte.pte_lo &= ~PTE_CHG; + moea_pte_change(pt, &pvo->pvo_pte.pte, pvo->pvo_vaddr); mtx_unlock(&moea_table_mutex); } @@ -1399,19 +1400,17 @@ struct pvo_entry *pvo; vm_paddr_t pa; -#ifdef UMA_MD_SMALL_ALLOC /* - * Allow direct mappings + * Allow direct mappings on 32-bit OEA */ if (va < VM_MIN_KERNEL_ADDRESS) { return (va); } -#endif PMAP_LOCK(kernel_pmap); pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL); KASSERT(pvo != NULL, ("moea_kextract: no addr found")); - pa = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); + pa = (pvo->pvo_pte.pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); PMAP_UNLOCK(kernel_pmap); return (pa); } @@ -1510,6 +1509,10 @@ entropy = 0; __asm __volatile("mftb %0" : "=r"(entropy)); + if ((pmap->pmap_phys = (pmap_t)moea_kextract(mmu, (vm_offset_t)pmap)) == NULL) + pmap->pmap_phys = pmap; + + /* * Allocate some segment registers for this pmap. */ @@ -1602,14 +1605,14 @@ /* * Change the protection of the page. */ - pvo->pvo_pte.pte_lo &= ~PTE_PP; - pvo->pvo_pte.pte_lo |= PTE_BR; + pvo->pvo_pte.pte.pte_lo &= ~PTE_PP; + pvo->pvo_pte.pte.pte_lo |= PTE_BR; /* * If the PVO is in the page table, update that pte as well. */ if (pt != NULL) { - moea_pte_change(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + moea_pte_change(pt, &pvo->pvo_pte.pte, pvo->pvo_vaddr); mtx_unlock(&moea_table_mutex); } } @@ -1808,8 +1811,8 @@ mtx_lock(&moea_table_mutex); LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) { - if ((pvo->pvo_pte.pte_lo & PTE_RPGN) == pa && - (pvo->pvo_pte.pte_lo & PTE_PP) == + if ((pvo->pvo_pte.pte.pte_lo & PTE_RPGN) == pa && + (pvo->pvo_pte.pte.pte_lo & PTE_PP) == (pte_lo & PTE_PP)) { mtx_unlock(&moea_table_mutex); return (0); @@ -1856,7 +1859,7 @@ if (flags & PVO_FAKE) pvo->pvo_vaddr |= PVO_FAKE; - moea_pte_create(&pvo->pvo_pte, sr, va, pa | pte_lo); + moea_pte_create(&pvo->pvo_pte.pte, sr, va, pa | pte_lo); /* * Remember if the list was empty and therefore will be the first @@ -1866,14 +1869,14 @@ first = 1; LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink); - if (pvo->pvo_pte.pte_lo & PVO_WIRED) + if (pvo->pvo_pte.pte.pte_lo & PVO_WIRED) pm->pm_stats.wired_count++; pm->pm_stats.resident_count++; /* * We hope this succeeds but it isn't required. */ - i = moea_pte_insert(ptegidx, &pvo->pvo_pte); + i = moea_pte_insert(ptegidx, &pvo->pvo_pte.pte); if (i >= 0) { PVO_PTEGIDX_SET(pvo, i); } else { @@ -1896,7 +1899,7 @@ */ pt = moea_pvo_to_pte(pvo, pteidx); if (pt != NULL) { - moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + moea_pte_unset(pt, &pvo->pvo_pte.pte, pvo->pvo_vaddr); mtx_unlock(&moea_table_mutex); PVO_PTEGIDX_CLR(pvo); } else { @@ -1907,7 +1910,7 @@ * Update our statistics. */ pvo->pvo_pmap->pm_stats.resident_count--; - if (pvo->pvo_pte.pte_lo & PVO_WIRED) + if (pvo->pvo_pte.pte.pte_lo & PVO_WIRED) pvo->pvo_pmap->pm_stats.wired_count--; /* @@ -1916,9 +1919,9 @@ if ((pvo->pvo_vaddr & (PVO_MANAGED|PVO_FAKE)) == PVO_MANAGED) { struct vm_page *pg; - pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN); + pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN); if (pg != NULL) { - moea_attr_save(pg, pvo->pvo_pte.pte_lo & + moea_attr_save(pg, pvo->pvo_pte.pte.pte_lo & (PTE_REF | PTE_CHG)); } } @@ -1951,7 +1954,7 @@ * noticing the HID bit. */ pteidx = ptegidx * 8 + PVO_PTEGIDX_GET(pvo); - if (pvo->pvo_pte.pte_hi & PTE_HID) + if (pvo->pvo_pte.pte.pte_hi & PTE_HID) pteidx ^= moea_pteg_mask * 8; return (pteidx); @@ -2001,23 +2004,23 @@ pt = &moea_pteg_table[pteidx >> 3].pt[pteidx & 7]; mtx_lock(&moea_table_mutex); - if ((pvo->pvo_pte.pte_hi & PTE_VALID) && !PVO_PTEGIDX_ISSET(pvo)) { + if ((pvo->pvo_pte.pte.pte_hi & PTE_VALID) && !PVO_PTEGIDX_ISSET(pvo)) { panic("moea_pvo_to_pte: pvo %p has valid pte in pvo but no " "valid pte index", pvo); } - if ((pvo->pvo_pte.pte_hi & PTE_VALID) == 0 && PVO_PTEGIDX_ISSET(pvo)) { + if ((pvo->pvo_pte.pte.pte_hi & PTE_VALID) == 0 && PVO_PTEGIDX_ISSET(pvo)) { panic("moea_pvo_to_pte: pvo %p has valid pte index in pvo " "pvo but no valid pte", pvo); } - if ((pt->pte_hi ^ (pvo->pvo_pte.pte_hi & ~PTE_VALID)) == PTE_VALID) { - if ((pvo->pvo_pte.pte_hi & PTE_VALID) == 0) { + if ((pt->pte_hi ^ (pvo->pvo_pte.pte.pte_hi & ~PTE_VALID)) == PTE_VALID) { + if ((pvo->pvo_pte.pte.pte_hi & PTE_VALID) == 0) { panic("moea_pvo_to_pte: pvo %p has valid pte in " "moea_pteg_table %p but invalid in pvo", pvo, pt); } - if (((pt->pte_lo ^ pvo->pvo_pte.pte_lo) & ~(PTE_CHG|PTE_REF)) + if (((pt->pte_lo ^ pvo->pvo_pte.pte.pte_lo) & ~(PTE_CHG|PTE_REF)) != 0) { panic("moea_pvo_to_pte: pvo %p pte does not match " "pte %p in moea_pteg_table", pvo, pt); @@ -2027,7 +2030,7 @@ return (pt); } - if (pvo->pvo_pte.pte_hi & PTE_VALID) { + if (pvo->pvo_pte.pte.pte_hi & PTE_VALID) { panic("moea_pvo_to_pte: pvo %p has invalid pte %p in " "moea_pteg_table but valid in pvo", pvo, pt); } @@ -2072,13 +2075,13 @@ */ MOEA_PVO_CHECK(pvo); if (source_pvo == NULL && - moea_pte_match(&pvo->pvo_pte, sr, addr, - pvo->pvo_pte.pte_hi & PTE_HID)) { + moea_pte_match(&pvo->pvo_pte.pte, sr, addr, + pvo->pvo_pte.pte.pte_hi & PTE_HID)) { /* * Now found an entry to be spilled into the pteg. * The PTE is now valid, so we know it's active. */ - j = moea_pte_insert(ptegidx, &pvo->pvo_pte); + j = moea_pte_insert(ptegidx, &pvo->pvo_pte.pte); if (j >= 0) { PVO_PTEGIDX_SET(pvo, j); @@ -2099,7 +2102,7 @@ * so save the R & C bits of the PTE. */ if ((pt->pte_hi & PTE_HID) == 0 && victim_pvo == NULL && - moea_pte_compare(pt, &pvo->pvo_pte)) { + moea_pte_compare(pt, &pvo->pvo_pte.pte)) { victim_pvo = pvo; if (source_pvo != NULL) break; @@ -2127,7 +2130,7 @@ * We also need the pvo entry of the victim we are * replacing so save the R & C bits of the PTE. */ - if (moea_pte_compare(pt, &pvo->pvo_pte)) { + if (moea_pte_compare(pt, &pvo->pvo_pte.pte)) { victim_pvo = pvo; break; } @@ -2143,10 +2146,10 @@ * though it's valid. If we don't, we lose any ref/chg bit changes * contained in the TLB entry. */ - source_pvo->pvo_pte.pte_hi &= ~PTE_HID; + source_pvo->pvo_pte.pte.pte_hi &= ~PTE_HID; - moea_pte_unset(pt, &victim_pvo->pvo_pte, victim_pvo->pvo_vaddr); - moea_pte_set(pt, &source_pvo->pvo_pte); + moea_pte_unset(pt, &victim_pvo->pvo_pte.pte, victim_pvo->pvo_vaddr); + moea_pte_set(pt, &source_pvo->pvo_pte.pte); PVO_PTEGIDX_CLR(victim_pvo); PVO_PTEGIDX_SET(source_pvo, i); @@ -2213,7 +2216,7 @@ * See if we saved the bit off. If so, cache it and return * success. */ - if (pvo->pvo_pte.pte_lo & ptebit) { + if (pvo->pvo_pte.pte.pte_lo & ptebit) { moea_attr_save(m, ptebit); MOEA_PVO_CHECK(pvo); /* sanity check */ return (TRUE); @@ -2236,9 +2239,9 @@ */ pt = moea_pvo_to_pte(pvo, -1); if (pt != NULL) { - moea_pte_synch(pt, &pvo->pvo_pte); + moea_pte_synch(pt, &pvo->pvo_pte.pte); mtx_unlock(&moea_table_mutex); - if (pvo->pvo_pte.pte_lo & ptebit) { + if (pvo->pvo_pte.pte.pte_lo & ptebit) { moea_attr_save(m, ptebit); MOEA_PVO_CHECK(pvo); /* sanity check */ return (TRUE); @@ -2281,15 +2284,15 @@ MOEA_PVO_CHECK(pvo); /* sanity check */ pt = moea_pvo_to_pte(pvo, -1); if (pt != NULL) { - moea_pte_synch(pt, &pvo->pvo_pte); - if (pvo->pvo_pte.pte_lo & ptebit) { + moea_pte_synch(pt, &pvo->pvo_pte.pte); + if (pvo->pvo_pte.pte.pte_lo & ptebit) { count++; moea_pte_clear(pt, PVO_VADDR(pvo), ptebit); } mtx_unlock(&moea_table_mutex); } - rv |= pvo->pvo_pte.pte_lo; - pvo->pvo_pte.pte_lo &= ~ptebit; + rv |= pvo->pvo_pte.pte.pte_lo; + pvo->pvo_pte.pte.pte_lo &= ~ptebit; MOEA_PVO_CHECK(pvo); /* sanity check */ } ==== //depot/projects/ppc-g5/sys/powerpc/aim/ofw_machdep.c#2 (text+ko) ==== @@ -62,6 +62,12 @@ static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3]; static struct mem_region OFfree[OFMEM_REGIONS + 3]; +struct mem_region64 { + vm_offset_t mr_start_hi; + vm_offset_t mr_start_lo; + vm_size_t mr_size; +}; + extern register_t ofmsr[5]; extern struct pmap ofw_pmap; static int (*ofwcall)(void *); @@ -146,15 +152,35 @@ * Get memory. */ if ((phandle = OF_finddevice("/memory")) == -1 - || (msz = OF_getprop(phandle, "reg", - OFmem, sizeof OFmem[0] * OFMEM_REGIONS)) - <= 0 || (asz = OF_getprop(phandle, "available", OFavail, sizeof OFavail[0] * OFMEM_REGIONS)) <= 0) panic("no memory?"); + + if (ppc64) { + struct mem_region64 OFmem64[OFMEM_REGIONS + 1]; + if ((msz = OF_getprop(phandle, "reg", + OFmem64, sizeof OFmem64[0] * OFMEM_REGIONS)) <= 0) + panic("Physical memory map not found"); + + for (i = 0; i < msz/sizeof(OFmem64[0]); i++) { + if (OFmem64[i].mr_start_hi == 0) { + OFmem[i].mr_start = OFmem64[i].mr_start_lo; + OFmem[i].mr_size = OFmem64[i].mr_size; + } else { + OFmem[i].mr_size = 0; + } + } + msz = i*sizeof(OFmem[0]); + } else { + if ((msz = OF_getprop(phandle, "reg", + OFmem, sizeof OFmem[0] * OFMEM_REGIONS)) <= 0) + panic("Physical memory map not found"); + } + *memp = OFmem; *memsz = msz / sizeof(struct mem_region); + /* * OFavail may have overlapping regions - collapse these @@ -229,8 +255,10 @@ /* * Clear battable[] translations */ - __asm __volatile("mtdbatu 2, %0\n" - "mtdbatu 3, %0" : : "r" (0)); + if (!ppc64) { + __asm __volatile("mtdbatu 2, %0\n" + "mtdbatu 3, %0" : : "r" (0)); + } isync(); } ==== //depot/projects/ppc-g5/sys/powerpc/aim/trap_subr.S#2 (text+ko) ==== @@ -228,6 +228,45 @@ mfsprg2 %r2; /* restore r2 & r3 */ \ mfsprg3 %r3 +/* + * The next two routines are 64-bit glue code. The first is used to test if + * we are on a 64-bit system. By copying it to the illegal instruction + * handler, we can test for 64-bit mode by trying to execute a 64-bit + * instruction and seeing what happens. The second gets copied in front + * of all the other handlers to restore 32-bit bridge mode when traps + * are taken. + */ + +/* 64-bit test code. Sets SPRG2 to 0 if an illegal instruction is executed */ + + .globl CNAME(testppc64),CNAME(testppc64size) +CNAME(testppc64): + mtsprg1 %r31 + mfsrr0 %r31 + addi %r31, %r31, 4 + mtsrr0 %r31 + + li %r31, 0 + mtsprg2 %r31 + mfsprg1 %r31 + + rfi +CNAME(testppc64size) = .-CNAME(testppc64) + + +/* 64-bit bridge mode restore snippet. Gets copied in front of everything else + * on 64-bit systems. */ + + .globl CNAME(restorebridge),CNAME(restorebridgesize) +CNAME(restorebridge): + mtsprg1 %r31 + mfmsr %r31 + clrldi %r31,%r31,1 + mtmsrd %r31 + mfsprg1 %r31 + isync +CNAME(restorebridgesize) = .-CNAME(restorebridge) + #ifdef SMP /* * Processor reset exception handler. These are typically @@ -490,8 +529,15 @@ b trapexit /* test ast ret value ? */ 1: FRAME_LEAVE(PC_TEMPSAVE) + + .globl CNAME(rfi_patch1) /* replace rfi with rfid on ppc64 */ +CNAME(rfi_patch1): rfi + .globl CNAME(rfid_patch) +CNAME(rfid_patch): + rfid + /* * Temporary: vector-unavailable traps are directed to vector-assist traps */ @@ -552,6 +598,8 @@ b realtrap dbleave: FRAME_LEAVE(PC_DBSAVE) + .globl CNAME(rfi_patch2) /* replace rfi with rfid on ppc64 */ +CNAME(rfi_patch2): rfi /* ==== //depot/projects/ppc-g5/sys/powerpc/aim/uio_machdep.c#2 (text+ko) ==== @@ -45,15 +45,17 @@ #include #include #include +#include #include #include +#include +#include #include -#include /* - * Implement uiomove(9) from physical memory using the direct map to + * Implement uiomove(9) from physical memory using sf_bufs to * avoid the creation and destruction of ephemeral mappings. */ int @@ -63,14 +65,17 @@ struct iovec *iov; void *cp; vm_offset_t page_offset; + vm_page_t m; size_t cnt; int error = 0; int save = 0; + struct sf_buf *sf; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomove_fromphys: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, ("uiomove_fromphys proc")); + save = td->td_pflags & TDP_DEADLKTREAT; td->td_pflags |= TDP_DEADLKTREAT; while (n > 0 && uio->uio_resid) { @@ -85,31 +90,37 @@ cnt = n; page_offset = offset & PAGE_MASK; cnt = min(cnt, PAGE_SIZE - page_offset); - cp = (char *)VM_PAGE_TO_PHYS(ma[offset >> PAGE_SHIFT]) + - page_offset; + + m = ma[offset >> PAGE_SHIFT]; + sf = sf_buf_alloc(m, 0); + cp = (char*)sf_buf_kva(sf) + page_offset; + switch (uio->uio_segflg) { - case UIO_USERSPACE: - if (ticks - PCPU_GET(switchticks) >= hogticks) - uio_yield(); - if (uio->uio_rw == UIO_READ) - error = copyout(cp, iov->iov_base, cnt); - else - error = copyin(iov->iov_base, cp, cnt); - if (error) - goto out; - if (uio->uio_rw == UIO_WRITE && - pmap_page_executable(ma[offset >> PAGE_SHIFT])) - __syncicache(cp, cnt); - break; - case UIO_SYSSPACE: - if (uio->uio_rw == UIO_READ) - bcopy(cp, iov->iov_base, cnt); - else - bcopy(iov->iov_base, cp, cnt); - break; - case UIO_NOCOPY: - break; + case UIO_USERSPACE: + if (ticks - PCPU_GET(switchticks) >= hogticks) + uio_yield(); + if (uio->uio_rw == UIO_READ) + error = copyout(cp, iov->iov_base, cnt); + else + error = copyin(iov->iov_base, cp, cnt); + if (error) { + sf_buf_free(sf); + goto out; + } + if (uio->uio_rw == UIO_WRITE && + pmap_page_executable(m)) + __syncicache(cp, cnt); + break; + case UIO_SYSSPACE: + if (uio->uio_rw == UIO_READ) + bcopy(cp, iov->iov_base, cnt); + else + bcopy(iov->iov_base, cp, cnt); + break; + case UIO_NOCOPY: + break; } + sf_buf_free(sf); iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; ==== //depot/projects/ppc-g5/sys/powerpc/aim/uma_machdep.c#2 (text+ko) ==== @@ -35,9 +35,13 @@ #include #include #include +#include #include +#include +#include #include #include +#include #include static int hw_uma_mdpages; @@ -51,6 +55,13 @@ void *va; vm_page_t m; int pflags; + + if (!hw_direct_map) { + *flags = UMA_SLAB_KMEM; + va = (void *)kmem_malloc(kmem_map, bytes, wait); + + return va; + } *flags = UMA_SLAB_PRIV; if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT) @@ -83,6 +94,12 @@ { vm_page_t m; + if (!hw_direct_map) { + kmem_free(kmem_map, (vm_offset_t)mem, size); + + return; + } + m = PHYS_TO_VM_PAGE((u_int32_t)mem); m->wire_count--; vm_page_free(m); ==== //depot/projects/ppc-g5/sys/powerpc/aim/vm_machdep.c#2 (text+ko) ==== @@ -101,6 +101,37 @@ #include /* + * On systems without a direct mapped region (e.g. PPC64), + * we use the same code as the Book E implementation. Since + * we need to have runtime detection of this, define some machinery + * for sf_bufs in this case, and ignore it on systems with direct maps. + */ + +#ifndef NSFBUFS +#define NSFBUFS (512 + maxusers * 16) +#endif + +static void sf_buf_init(void *arg); +SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); + +LIST_HEAD(sf_head, sf_buf); + +/* A hash table of active sendfile(2) buffers */ +static struct sf_head *sf_buf_active; +static u_long sf_buf_hashmask; + +#define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask) + +static TAILQ_HEAD(, sf_buf) sf_buf_freelist; +static u_int sf_buf_alloc_want; + +/* + * A lock used to synchronize access to the hash table and free list + */ +static struct mtx sf_buf_lock; + + +/* * Finish a fork operation, with process p2 nearly set up. * Copy and update the pcb, set up the stack so that the child * ready to run and return to user mode. @@ -202,24 +233,122 @@ } /* - * Allocate an sf_buf for the given vm_page. On this machine, however, there - * is no sf_buf object. Instead, an opaque pointer to the given vm_page is - * returned. + * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) + */ +static void +sf_buf_init(void *arg) +{ + struct sf_buf *sf_bufs; + vm_offset_t sf_base; + int i; + + /* Don't bother on systems with a direct map */ >>> TRUNCATED FOR MAIL (1000 lines) <<<