Mercurial > illumos > illumos-gate
changeset 3177:6d48ee59c4fc
6488843 Hashed Cache index mode support for Huron
6489149 colorequivszc[] may be set incorrectly on sun4v
6489393 MTYPE_START/MTYPE_NEXT DR race in ASSERT macro
6493685 randomize effective process user stack start address to avoid thrashing caches on sun4v platforms
author | dp78419 |
---|---|
date | Mon, 27 Nov 2006 13:18:12 -0800 |
parents | a38e922f22b0 |
children | 6f68dd70b05d |
files | usr/src/uts/common/os/exec.c usr/src/uts/common/sys/vmsystm.h usr/src/uts/i86pc/vm/vm_machdep.c usr/src/uts/sun4/vm/vm_dep.c usr/src/uts/sun4/vm/vm_dep.h usr/src/uts/sun4u/vm/mach_vm_dep.c usr/src/uts/sun4v/cpu/niagara2.c usr/src/uts/sun4v/vm/mach_vm_dep.c |
diffstat | 8 files changed, 276 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/os/exec.c Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/common/os/exec.c Mon Nov 27 13:18:12 2006 -0800 @@ -1576,6 +1576,10 @@ * * User Stack * +---------------+ <--- curproc->p_usrstack + * | | + * | slew | + * | | + * +---------------+ * | NULL | * +---------------+ * | | @@ -1622,9 +1626,9 @@ user_t *up = PTOU(p); char *usrstack; rctl_entity_p_t e; - struct as *as; extern int use_stk_lpg; + size_t sp_slew; args->from_model = p->p_model; if (p->p_model == DATAMODEL_NATIVE) { @@ -1788,7 +1792,18 @@ p->p_flag |= SAUTOLPG; /* kernel controls page sizes */ mutex_exit(&p->p_lock); - exec_set_sp(size); + /* + * Some platforms may choose to randomize real stack start by adding a + * small slew (not more than a few hundred bytes) to the top of the + * stack. This helps avoid cache thrashing when identical processes + * simultaneously share caches that don't provide enough associativity + * (e.g. sun4v systems). In this case stack slewing makes the same hot + * stack variables in different processes to live in different cache + * sets increasing effective associativity. + */ + sp_slew = exec_get_spslew(); + ASSERT(P2PHASE(sp_slew, args->stk_align) == 0); + exec_set_sp(size + sp_slew); as = as_alloc(); p->p_as = as; @@ -1800,7 +1815,7 @@ /* * Finally, write out the contents of the new stack. */ - error = stk_copyout(args, usrstack, auxvpp, up); + error = stk_copyout(args, usrstack - sp_slew, auxvpp, up); kmem_free(args->stk_base, args->stk_size); return (error); }
--- a/usr/src/uts/common/sys/vmsystm.h Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/common/sys/vmsystm.h Mon Nov 27 13:18:12 2006 -0800 @@ -149,6 +149,8 @@ extern void *boot_virt_alloc(void *addr, size_t size); +extern size_t exec_get_spslew(void); + #endif /* _KERNEL */ #ifdef __cplusplus
--- a/usr/src/uts/i86pc/vm/vm_machdep.c Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/i86pc/vm/vm_machdep.c Mon Nov 27 13:18:12 2006 -0800 @@ -2140,3 +2140,9 @@ void dcache_flushall() {} + +size_t +exec_get_spslew(void) +{ + return (0); +}
--- a/usr/src/uts/sun4/vm/vm_dep.c Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/sun4/vm/vm_dep.c Mon Nov 27 13:18:12 2006 -0800 @@ -897,8 +897,10 @@ if (do_pg_coloring == 0) { page_colors = 1; - for (i = 0; i < mmu_page_sizes; i++) + for (i = 0; i < mmu_page_sizes; i++) { + colorequivszc[i] = 0; hw_page_array[i].hp_colors = 1; + } return; } @@ -925,6 +927,7 @@ hw_page_array[i].hp_colors = (page_colors_mask >> (hw_page_array[i].hp_shift - hw_page_array[0].hp_shift)) + 1; + colorequivszc[i] = 0; } /* @@ -935,8 +938,8 @@ * The value of cpu_page_colors determines if additional color bins * need to be checked for a particular color in the page_get routines. */ - if ((cpu_page_colors == 0) && (cpu_setsize < ecache_setsize)) { - + if (cpu_setsize > 0 && cpu_page_colors == 0 && + cpu_setsize < ecache_setsize) { cpu_page_colors = cpu_setsize / MMU_PAGESIZE; a = lowbit(page_colors) - lowbit(cpu_page_colors); ASSERT(a > 0); @@ -944,7 +947,6 @@ for (i = 0; i < mmu_page_sizes; i++) { if ((colors = hw_page_array[i].hp_colors) <= 1) { - colorequivszc[i] = 0; continue; } while ((colors >> a) == 0)
--- a/usr/src/uts/sun4/vm/vm_dep.h Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/sun4/vm/vm_dep.h Mon Nov 27 13:18:12 2006 -0800 @@ -361,7 +361,9 @@ */ #define MTYPE_START(mnode, mtype, flags) { \ if (plcnt[mnode][mtype].plc_mt_pgmax == 0) { \ - ASSERT(MNODETYPE_PGCNT(mnode, mtype) == 0); \ + ASSERT(mtype == MTYPE_RELOC || \ + MNODETYPE_PGCNT(mnode, mtype) == 0 || \ + plcnt[mnode][mtype].plc_mt_pgmax != 0); \ MTYPE_NEXT(mnode, mtype, flags); \ } \ } @@ -374,7 +376,8 @@ if (!(flags & (PG_NORELOC | PGI_NOCAGE | PGI_RELOCONLY)) && \ (kcage_freemem >= kcage_lotsfree)) { \ if (plcnt[mnode][MTYPE_NORELOC].plc_mt_pgmax == 0) { \ - ASSERT(MNODETYPE_PGCNT(mnode, MTYPE_NORELOC) == 0); \ + ASSERT(MNODETYPE_PGCNT(mnode, MTYPE_NORELOC) == 0 || \ + plcnt[mnode][MTYPE_NORELOC].plc_mt_pgmax != 0); \ mtype = -1; \ } else { \ mtype = MTYPE_NORELOC; \ @@ -389,7 +392,6 @@ * get the ecache setsize for the current cpu. */ #define CPUSETSIZE() (cpunodes[CPU->cpu_id].ecache_setsize) -#define CPUASSOC() (cpunodes[CPU->cpu_id].ecache_associativity) extern struct cpu cpu0; #define CPU0 &cpu0 @@ -475,9 +477,7 @@ pfn = ((uintptr_t)addr >> MMU_PAGESHIFT) + \ (((uintptr_t)addr >> page_coloring_shift) << \ (vac_shift - MMU_PAGESHIFT)); \ - if ((szc) == 0 || \ - (szc == 1 && &page_pfn_2_color_cpu == NULL && \ - CPUASSOC() > PNUM_SIZE(1))) { \ + if ((szc) == 0 || &page_pfn_2_color_cpu == NULL) { \ pfn += slew; \ bin = PFN_2_COLOR(pfn, szc); \ } else { \
--- a/usr/src/uts/sun4u/vm/mach_vm_dep.c Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/sun4u/vm/mach_vm_dep.c Mon Nov 27 13:18:12 2006 -0800 @@ -326,3 +326,9 @@ { /* not applicable to sun4u */ } + +size_t +exec_get_spslew(void) +{ + return (0); +}
--- a/usr/src/uts/sun4v/cpu/niagara2.c Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/sun4v/cpu/niagara2.c Mon Nov 27 13:18:12 2006 -0800 @@ -34,6 +34,7 @@ #include <sys/elf_SPARC.h> #include <vm/hat_sfmmu.h> #include <vm/page.h> +#include <vm/vm_dep.h> #include <sys/cpuvar.h> #include <sys/async.h> #include <sys/cmn_err.h> @@ -124,6 +125,13 @@ * Niagara2 has a performance counter overflow interrupt */ cpc_has_overflow_intr = 1; + + /* + * Enable 4M pages for OOB. + */ + max_uheap_lpsize = MMU_PAGESIZE4M; + max_ustack_lpsize = MMU_PAGESIZE4M; + max_privmap_lpsize = MMU_PAGESIZE4M; } /* @@ -230,3 +238,213 @@ tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_time = 0; } } + +/* NI2 L2$ index is pa[32:28]^pa[17:13].pa[19:18]^pa[12:11].pa[10:6] */ +uint_t +page_pfn_2_color_cpu(pfn_t pfn, uchar_t szc) +{ + uint_t color; + + ASSERT(szc <= TTE256M); + + pfn = PFN_BASE(pfn, szc); + color = ((pfn >> 15) ^ pfn) & 0x1f; + if (szc >= TTE4M) + return (color); + + color = (color << 2) | ((pfn >> 5) & 0x3); + + return (szc <= TTE64K ? color : (color >> 1)); +} + +#if TTE256M != 5 +#error TTE256M is not 5 +#endif + +uint_t +page_get_nsz_color_mask_cpu(uchar_t szc, uint_t mask) +{ + static uint_t ni2_color_masks[5] = {0x63, 0x1e, 0x3e, 0x1f, 0x1f}; + ASSERT(szc < TTE256M); + + mask &= ni2_color_masks[szc]; + return ((szc == TTE64K || szc == TTE512K) ? (mask >> 1) : mask); +} + +uint_t +page_get_nsz_color_cpu(uchar_t szc, uint_t color) +{ + ASSERT(szc < TTE256M); + return ((szc == TTE64K || szc == TTE512K) ? (color >> 1) : color); +} + +uint_t +page_get_color_shift_cpu(uchar_t szc, uchar_t nszc) +{ + ASSERT(nszc > szc); + ASSERT(nszc <= TTE256M); + + if (szc <= TTE64K) + return ((nszc >= TTE4M) ? 2 : ((nszc >= TTE512K) ? 1 : 0)); + if (szc == TTE512K) + return (1); + + return (0); +} + +/*ARGSUSED*/ +pfn_t +page_next_pfn_for_color_cpu(pfn_t pfn, uchar_t szc, uint_t color, + uint_t ceq_mask, uint_t color_mask) +{ + pfn_t pstep = PNUM_SIZE(szc); + pfn_t npfn, pfn_ceq_mask, pfn_color; + pfn_t tmpmask, mask = (pfn_t)-1; + + ASSERT((color & ~ceq_mask) == 0); + + if (((page_pfn_2_color_cpu(pfn, szc) ^ color) & ceq_mask) == 0) { + + /* we start from the page with correct color */ + if (szc >= TTE512K) { + if (szc >= TTE4M) { + /* page color is PA[32:28] */ + pfn_ceq_mask = ceq_mask << 15; + } else { + /* page color is PA[32:28].PA[19:19] */ + pfn_ceq_mask = ((ceq_mask & 1) << 6) | + ((ceq_mask >> 1) << 15); + } + pfn = ADD_MASKED(pfn, pstep, pfn_ceq_mask, mask); + return (pfn); + } else { + /* + * We deal 64K or 8K page. Check if we could the + * satisfy the request without changing PA[32:28] + */ + pfn_ceq_mask = ((ceq_mask & 3) << 5) | (ceq_mask >> 2); + npfn = ADD_MASKED(pfn, pstep, pfn_ceq_mask, mask); + + if ((((npfn ^ pfn) >> 15) & 0x1f) == 0) + return (npfn); + + /* + * for next pfn we have to change bits PA[32:28] + * set PA[63:28] and PA[19:18] of the next pfn + */ + npfn = (pfn >> 15) << 15; + npfn |= (ceq_mask & color & 3) << 5; + pfn_ceq_mask = (szc == TTE8K) ? 0 : + (ceq_mask & 0x1c) << 13; + npfn = ADD_MASKED(npfn, (1 << 15), pfn_ceq_mask, mask); + + /* + * set bits PA[17:13] to match the color + */ + ceq_mask >>= 2; + color = (color >> 2) & ceq_mask; + npfn |= ((npfn >> 15) ^ color) & ceq_mask; + return (npfn); + } + } + + /* + * we start from the page with incorrect color - rare case + */ + if (szc >= TTE512K) { + if (szc >= TTE4M) { + /* page color is in bits PA[32:28] */ + npfn = ((pfn >> 20) << 20) | (color << 15); + pfn_ceq_mask = (ceq_mask << 15) | 0x7fff; + } else { + /* try get the right color by changing bit PA[19:19] */ + npfn = pfn + pstep; + if (((page_pfn_2_color_cpu(npfn, szc) ^ color) & + ceq_mask) == 0) + return (npfn); + + /* page color is PA[32:28].PA[19:19] */ + pfn_ceq_mask = ((ceq_mask & 1) << 6) | + ((ceq_mask >> 1) << 15) | (0xff << 7); + pfn_color = ((color & 1) << 6) | ((color >> 1) << 15); + npfn = ((pfn >> 20) << 20) | pfn_color; + } + + while (npfn <= pfn) { + npfn = ADD_MASKED(npfn, pstep, pfn_ceq_mask, mask); + } + return (npfn); + } + + /* + * We deal 64K or 8K page of incorrect color. + * Try correcting color without changing PA[32:28] + */ + + pfn_ceq_mask = ((ceq_mask & 3) << 5) | (ceq_mask >> 2); + pfn_color = ((color & 3) << 5) | (color >> 2); + npfn = (pfn & ~(pfn_t)0x7f); + npfn |= (((pfn >> 15) & 0x1f) ^ pfn_color) & pfn_ceq_mask; + npfn = (szc == TTE64K) ? (npfn & ~(pfn_t)0x7) : npfn; + + if (((page_pfn_2_color_cpu(npfn, szc) ^ color) & ceq_mask) == 0) { + + /* the color is fixed - find the next page */ + while (npfn <= pfn) { + npfn = ADD_MASKED(npfn, pstep, pfn_ceq_mask, mask); + } + if ((((npfn ^ pfn) >> 15) & 0x1f) == 0) + return (npfn); + } + + /* to fix the color need to touch PA[32:28] */ + npfn = (szc == TTE8K) ? ((pfn >> 15) << 15) : + (((pfn >> 18) << 18) | ((color & 0x1c) << 13)); + tmpmask = (szc == TTE8K) ? 0 : (ceq_mask & 0x1c) << 13; + + while (npfn <= pfn) { + npfn = ADD_MASKED(npfn, (1 << 15), tmpmask, mask); + } + + /* set bits PA[19:13] to match the color */ + npfn |= (((npfn >> 15) & 0x1f) ^ pfn_color) & pfn_ceq_mask; + npfn = (szc == TTE64K) ? (npfn & ~(pfn_t)0x7) : npfn; + + ASSERT(((page_pfn_2_color_cpu(npfn, szc) ^ color) & ceq_mask) == 0); + + return (npfn); +} + +/* + * init page coloring + */ +void +page_coloring_init_cpu() +{ + int i; + uint_t colors; + + hw_page_array[0].hp_colors = 1 << 7; + hw_page_array[1].hp_colors = 1 << 7; + hw_page_array[2].hp_colors = 1 << 6; + + for (i = 3; i < mmu_page_sizes; i++) { + hw_page_array[i].hp_colors = 1 << 5; + } + + if (colorequiv > 1) { + int a = lowbit(colorequiv) - 1; + + if (a > 15) + a = 15; + + for (i = 0; i < mmu_page_sizes; i++) { + if ((colors = hw_page_array[i].hp_colors) <= 1) { + continue; + } + while ((colors >> a) == 0) + a--; + colorequivszc[i] = (a << 4); + } + } +}
--- a/usr/src/uts/sun4v/vm/mach_vm_dep.c Mon Nov 27 13:17:04 2006 -0800 +++ b/usr/src/uts/sun4v/vm/mach_vm_dep.c Mon Nov 27 13:18:12 2006 -0800 @@ -51,6 +51,8 @@ #include <sys/error.h> #include <sys/machsystm.h> #include <vm/seg_kmem.h> +#include <sys/stack.h> +#include <sys/atomic.h> uint_t page_colors = 0; uint_t page_colors_mask = 0; @@ -507,3 +509,15 @@ contig_mem_slab_arena, 0, VM_SLEEP | VM_BESTFIT); } + + +static uint_t sp_color_stride = 16; +static uint_t sp_color_mask = 0x1f; +static uint_t sp_current_color = (uint_t)-1; + +size_t +exec_get_spslew(void) +{ + uint_t spcolor = atomic_inc_32_nv(&sp_current_color); + return ((size_t)((spcolor & sp_color_mask) * SA(sp_color_stride))); +}