PERFORCE change 148545 for review
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Tue Aug 26 19:56:01 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=148545
Change 148545 by nwhitehorn at 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 <machine/md_var.h>
#if defined(_KERNEL) || defined(_STANDALONE)
-#ifndef CACHELINESIZE
-#error "Must know the size of a cache line"
-#endif
+int cacheline_size = 32;
#else
#include <stdlib.h>
+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 <sys/proc.h>
#include <sys/systm.h>
#include <sys/uio.h>
+#include <sys/sf_buf.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
+#include <machine/cpu.h>
+#include <machine/vmparam.h>
#include <machine/md_var.h>
-#include <machine/vmparam.h>
/*
- * 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 <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
#include <vm/vm_pageout.h>
+#include <vm/vm_extern.h>
+#include <vm/uma.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
+#include <machine/md_var.h>
#include <machine/vmparam.h>
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 <vm/vm_extern.h>
/*
+ * 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) <<<
More information about the p4-projects
mailing list