From owner-svn-src-projects@FreeBSD.ORG Sun Sep 6 17:24:15 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C4D8A106566C; Sun, 6 Sep 2009 17:24:15 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B2B5F8FC16; Sun, 6 Sep 2009 17:24:15 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n86HOFZF089788; Sun, 6 Sep 2009 17:24:15 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n86HOF21089780; Sun, 6 Sep 2009 17:24:15 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <200909061724.n86HOF21089780@svn.freebsd.org> From: Nathan Whitehorn Date: Sun, 6 Sep 2009 17:24:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196895 - in projects/ppc64/sys/powerpc: aim aim64 include X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Sep 2009 17:24:15 -0000 Author: nwhitehorn Date: Sun Sep 6 17:24:15 2009 New Revision: 196895 URL: http://svn.freebsd.org/changeset/base/196895 Log: Add some basic ability to handle segment exceptions. Init still can't die gracefully without panicing the kernel. Modified: projects/ppc64/sys/powerpc/aim/copyinout.c projects/ppc64/sys/powerpc/aim/machdep.c projects/ppc64/sys/powerpc/aim/trap.c projects/ppc64/sys/powerpc/aim64/machdep.c projects/ppc64/sys/powerpc/aim64/mmu_oea64.c projects/ppc64/sys/powerpc/aim64/trap_subr.S projects/ppc64/sys/powerpc/include/pmap.h Modified: projects/ppc64/sys/powerpc/aim/copyinout.c ============================================================================== --- projects/ppc64/sys/powerpc/aim/copyinout.c Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/aim/copyinout.c Sun Sep 6 17:24:15 2009 (r196895) @@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include @@ -75,14 +77,15 @@ int setfault(faultbuf); /* defined in lo */ #ifdef __powerpc64__ -uint64_t va_to_vsid(pmap_t pm, const volatile void *va); - static __inline void -set_user_sr(register_t vsid) +set_user_sr(pmap_t pm, const void *addr) { - register_t esid, slb1, slb2; + register_t esid, vsid, slb1, slb2; esid = USER_SR; + PMAP_LOCK(pm); + vsid = va_to_vsid(pm, (vm_offset_t)addr); + PMAP_UNLOCK(pm); slb1 = vsid << 12; slb2 = (((esid << 1) | 1UL) << 27) | USER_SR; @@ -92,15 +95,12 @@ set_user_sr(register_t vsid) isync(); } #else -static __inline register_t -va_to_vsid(pmap_t pm, const volatile void *va) -{ - return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK); -} - static __inline void -set_user_sr(register_t vsid) +set_user_sr(pmap_t pm, const void *addr) { + register_t vsid; + + vsid = va_to_vsid(pm, (vm_offset_t)addr); isync(); __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid)); @@ -136,7 +136,7 @@ copyout(const void *kaddr, void *udaddr, if (l > len) l = len; - set_user_sr(va_to_vsid(pm,up)); + set_user_sr(pm,up); bcopy(kp, p, l); @@ -177,7 +177,7 @@ copyin(const void *udaddr, void *kaddr, if (l > len) l = len; - set_user_sr(va_to_vsid(pm,up)); + set_user_sr(pm,up); bcopy(p, kp, l); @@ -252,7 +252,7 @@ subyte(void *addr, int byte) return (-1); } - set_user_sr(va_to_vsid(pm,addr)); + set_user_sr(pm,addr); *p = (char)byte; @@ -278,7 +278,7 @@ suword32(void *addr, int word) return (-1); } - set_user_sr(va_to_vsid(pm,addr)); + set_user_sr(pm,addr); *p = word; @@ -304,7 +304,7 @@ suword(void *addr, long word) return (-1); } - set_user_sr(va_to_vsid(pm,addr)); + set_user_sr(pm,addr); *p = word; @@ -345,7 +345,7 @@ fubyte(const void *addr) return (-1); } - set_user_sr(va_to_vsid(pm,addr)); + set_user_sr(pm,addr); val = *p; @@ -370,7 +370,7 @@ fuword(const void *addr) return (-1); } - set_user_sr(va_to_vsid(pm,addr)); + set_user_sr(pm,addr); val = *p; @@ -403,7 +403,7 @@ casuword(volatile u_long *addr, u_long o p = (u_long *)((uintptr_t)USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); - set_user_sr(va_to_vsid(pm,addr)); + set_user_sr(pm,(const void *)(vm_offset_t)addr); if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; Modified: projects/ppc64/sys/powerpc/aim/machdep.c ============================================================================== --- projects/ppc64/sys/powerpc/aim/machdep.c Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/aim/machdep.c Sun Sep 6 17:24:15 2009 (r196895) @@ -1178,3 +1178,10 @@ db_trap_glue(struct trapframe *frame) return (0); } + +uint64_t +va_to_vsid(pmap_t pm, vm_offset_t va) +{ + return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK); +} + Modified: projects/ppc64/sys/powerpc/aim/trap.c ============================================================================== --- projects/ppc64/sys/powerpc/aim/trap.c Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/aim/trap.c Sun Sep 6 17:24:15 2009 (r196895) @@ -177,6 +177,27 @@ trap(struct trapframe *frame) sig = SIGTRAP; break; +#ifdef __powerpc64__ + case EXC_ISE: + case EXC_DSE: + /* + * Once we support more segments per process + * than the SLB size, we should reload the SLB + * cache here from the longer segment list. + * + * For now, we assume a miss, and call va_to_vsid() + * to allocate a new segment. This will then likely + * trigger a page fault immediately after. + */ + + PMAP_LOCK(&p->p_vmspace->vm_pmap); + (void)va_to_vsid(&p->p_vmspace->vm_pmap, + (type == EXC_ISE) ? frame->srr0 : + frame->cpu.aim.dar); + PMAP_UNLOCK(&p->p_vmspace->vm_pmap); + + break; +#endif case EXC_DSI: case EXC_ISI: sig = trap_pfault(frame, 1); @@ -286,10 +307,12 @@ printtrap(u_int vector, struct trapframe printf(" exception = 0x%x (%s)\n", vector >> 8, trapname(vector)); switch (vector) { + case EXC_DSE: case EXC_DSI: printf(" virtual address = 0x%" PRIxPTR "\n", frame->cpu.aim.dar); break; + case EXC_ISE: case EXC_ISI: printf(" virtual address = 0x%" PRIxPTR "\n", frame->srr0); break; Modified: projects/ppc64/sys/powerpc/aim64/machdep.c ============================================================================== --- projects/ppc64/sys/powerpc/aim64/machdep.c Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/aim64/machdep.c Sun Sep 6 17:24:15 2009 (r196895) @@ -1120,3 +1120,42 @@ db_trap_glue(struct trapframe *frame) return (0); } + +uintptr_t moea64_get_unique_vsid(void); + +uint64_t +va_to_vsid(pmap_t pm, vm_offset_t va) +{ + uint64_t slbe, slbv, i; + + slbe = (uintptr_t)va >> ADDR_SR_SHFT; + slbe = (slbe << SLBE_ESID_SHIFT) | SLBE_VALID; + slbv = 0; + + for (i = 0; i < sizeof(pm->pm_slb)/sizeof(pm->pm_slb[0]); i++) { + if (pm->pm_slb[i].slbe == (slbe | i)) { + slbv = pm->pm_slb[i].slbv; + break; + } + } + + /* XXX: Have a long list for processes mapping more than 16 GB */ + + /* + * If there is no vsid for this VA, we need to add a new entry + * to the PMAP's segment table. + */ + + if (slbv == 0) { + slbv = moea64_get_unique_vsid() << SLBV_VSID_SHIFT; + for (i = 0; i < sizeof(pm->pm_slb)/sizeof(pm->pm_slb[0]); i++) { + if (!(pm->pm_slb[i].slbe & SLBE_VALID)) { + pm->pm_slb[i].slbv = slbv; + pm->pm_slb[i].slbe = slbe | i; + break; + } + } + } + + return ((slbv & SLBV_VSID_MASK) >> SLBV_VSID_SHIFT); +} Modified: projects/ppc64/sys/powerpc/aim64/mmu_oea64.c ============================================================================== --- projects/ppc64/sys/powerpc/aim64/mmu_oea64.c Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/aim64/mmu_oea64.c Sun Sep 6 17:24:15 2009 (r196895) @@ -159,7 +159,7 @@ __FBSDID("$FreeBSD$"); #define MOEA_DEBUG #define TODO panic("%s: not implemented", __func__); -static uintptr_t moea64_get_unique_vsid(void); +uintptr_t moea64_get_unique_vsid(void); static __inline register_t cntlzd(volatile register_t a) { @@ -168,53 +168,6 @@ cntlzd(volatile register_t a) { return b; } -#ifdef __powerpc64__ -uint64_t va_to_vsid(pmap_t pm, vm_offset_t va); - -uint64_t -va_to_vsid(pmap_t pm, vm_offset_t va) -{ - uint64_t slbe, slbv, i; - - slbe = (uintptr_t)va >> ADDR_SR_SHFT; - slbe = (slbe << SLBE_ESID_SHIFT) | SLBE_VALID; - slbv = 0; - - for (i = 0; i < sizeof(pm->pm_slb)/sizeof(pm->pm_slb[0]); i++) { - if (pm->pm_slb[i].slbe == (slbe | i)) { - slbv = pm->pm_slb[i].slbv; - break; - } - } - - /* XXX: Have a long list for processes mapping more than 16 GB */ - - /* - * If there is no vsid for this VA, we need to add a new entry - * to the PMAP's segment table. - */ - - if (slbv == 0) { - slbv = moea64_get_unique_vsid() << SLBV_VSID_SHIFT; - for (i = 0; i < sizeof(pm->pm_slb)/sizeof(pm->pm_slb[0]); i++) { - if (!(pm->pm_slb[i].slbe & SLBE_VALID)) { - pm->pm_slb[i].slbv = slbv; - pm->pm_slb[i].slbe = slbe | i; - break; - } - } - } - - return ((slbv & SLBV_VSID_MASK) >> SLBV_VSID_SHIFT); -} -#else -static __inline uint64_t -va_to_vsid(pmap_t pm, vm_offset_t va) -{ - return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK); -} -#endif - #define TLBSYNC() __asm __volatile("tlbsync; ptesync"); #define SYNC() __asm __volatile("sync"); #define EIEIO() __asm __volatile("eieio"); @@ -1827,7 +1780,7 @@ moea64_page_wired_mappings(mmu_t mmu, vm static uintptr_t moea64_vsidcontext; -static uintptr_t +uintptr_t moea64_get_unique_vsid(void) { u_int entropy; register_t hash; Modified: projects/ppc64/sys/powerpc/aim64/trap_subr.S ============================================================================== --- projects/ppc64/sys/powerpc/aim64/trap_subr.S Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/aim64/trap_subr.S Sun Sep 6 17:24:15 2009 (r196895) @@ -228,15 +228,19 @@ nslb: bf 17,1f; /* branch if PSL_PR is false */ \ /* Restore user SRs */ \ GET_CPUINFO(%r3); \ + std %r27,(savearea+CPUSAVE_R27)(%r3); \ std %r28,(savearea+CPUSAVE_R28)(%r3); \ std %r29,(savearea+CPUSAVE_R29)(%r3); \ std %r30,(savearea+CPUSAVE_R30)(%r3); \ std %r31,(savearea+CPUSAVE_R31)(%r3); \ + mflr %r27; /* preserve LR */ \ RESTORE_USER_SRS(); /* uses r28-r31 */ \ + mtlr %r27; \ ld %r31,(savearea+CPUSAVE_R31)(%r3); \ ld %r30,(savearea+CPUSAVE_R30)(%r3); \ ld %r29,(savearea+CPUSAVE_R29)(%r3); \ ld %r28,(savearea+CPUSAVE_R28)(%r3); \ + ld %r27,(savearea+CPUSAVE_R27)(%r3); \ 1: mfsprg1 %r2; /* restore cr */ \ mtcr %r2; \ GET_CPUINFO(%r2); \ Modified: projects/ppc64/sys/powerpc/include/pmap.h ============================================================================== --- projects/ppc64/sys/powerpc/include/pmap.h Sun Sep 6 15:23:03 2009 (r196894) +++ projects/ppc64/sys/powerpc/include/pmap.h Sun Sep 6 17:24:15 2009 (r196895) @@ -122,6 +122,15 @@ struct md_page { #define pmap_page_is_mapped(m) (!LIST_EMPTY(&(m)->md.mdpg_pvoh)) #define pmap_page_set_memattr(m, ma) (void)0 +/* + * Return the VSID corresponding to a given virtual address. + * If no VSID is currently defined, it will allocate one, and add it to + * a free SLB slot if available. + * + * NB: The PMAP MUST be locked already. + */ +uint64_t va_to_vsid(pmap_t pm, vm_offset_t va); + #else struct pmap {