1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/archsystm.h> 32 #include <sys/machparam.h> 33 #include <sys/machsystm.h> 34 #include <sys/cpu.h> 35 #include <sys/elf_SPARC.h> 36 #include <vm/hat_sfmmu.h> 37 #include <vm/page.h> 38 #include <sys/cpuvar.h> 39 #include <sys/async.h> 40 #include <sys/cmn_err.h> 41 #include <sys/debug.h> 42 #include <sys/dditypes.h> 43 #include <sys/sunddi.h> 44 #include <sys/cpu_module.h> 45 #include <sys/prom_debug.h> 46 #include <sys/vmsystm.h> 47 #include <sys/prom_plat.h> 48 #include <sys/sysmacros.h> 49 #include <sys/intreg.h> 50 #include <sys/machtrap.h> 51 #include <sys/ontrap.h> 52 #include <sys/ivintr.h> 53 #include <sys/atomic.h> 54 #include <sys/panic.h> 55 #include <sys/dtrace.h> 56 #include <vm/seg_spt.h> 57 58 #define S_VAC_SIZE MMU_PAGESIZE /* XXXQ? */ 59 60 /* 61 * Maximum number of contexts 62 */ 63 #define MAX_NCTXS (1 << 13) 64 65 uint_t root_phys_addr_lo_mask = 0xffffffffU; 66 67 void 68 cpu_setup(void) 69 { 70 extern int at_flags; 71 extern int disable_delay_tlb_flush, delay_tlb_flush; 72 extern int mmu_exported_pagesize_mask; 73 extern int get_cpu_pagesizes(void); 74 75 cache |= (CACHE_PTAG | CACHE_IOCOHERENT); 76 77 at_flags = EF_SPARC_32PLUS | EF_SPARC_SUN_US1; /* XXXQ */ 78 79 /* 80 * Use the maximum number of contexts available for Spitfire unless 81 * it has been tuned for debugging. 82 * We are checking against 0 here since this value can be patched 83 * while booting. It can not be patched via /etc/system since it 84 * will be patched too late and thus cause the system to panic. 85 */ 86 if (nctxs == 0) 87 nctxs = MAX_NCTXS; 88 89 if (use_page_coloring) { 90 do_pg_coloring = 1; 91 if (use_virtual_coloring) 92 do_virtual_coloring = 1; 93 } 94 /* 95 * Initalize supported page sizes information before the PD. 96 * If no information is available, then initialize the 97 * mmu_exported_pagesize_mask to a reasonable value for that processor. 98 */ 99 mmu_exported_pagesize_mask = get_cpu_pagesizes(); 100 if (mmu_exported_pagesize_mask <= 0) { 101 mmu_exported_pagesize_mask = (1 << TTE8K) | (1 << TTE64K) | 102 (1 << TTE4M); 103 } 104 105 /* 106 * Tune pp_slots to use up to 1/8th of the tlb entries. 107 */ 108 pp_slots = MIN(8, MAXPP_SLOTS); 109 110 /* 111 * Block stores invalidate all pages of the d$ so pagecopy 112 * et. al. do not need virtual translations with virtual 113 * coloring taken into consideration. 114 */ 115 pp_consistent_coloring = 0; 116 isa_list = 117 "sparcv9+vis sparcv9 " 118 "sparcv8plus+vis sparcv8plus " 119 "sparcv8 sparcv8-fsmuld sparcv7 sparc"; 120 121 /* 122 * On Spitfire, there's a hole in the address space 123 * that we must never map (the hardware only support 44-bits of 124 * virtual address). Later CPUs are expected to have wider 125 * supported address ranges. 126 * 127 * See address map on p23 of the UltraSPARC 1 user's manual. 128 */ 129 /* XXXQ get from machine description */ 130 hole_start = (caddr_t)0x80000000000ull; 131 hole_end = (caddr_t)0xfffff80000000000ull; 132 133 /* 134 * The kpm mapping window. 135 * kpm_size: 136 * The size of a single kpm range. 137 * The overall size will be: kpm_size * vac_colors. 138 * kpm_vbase: 139 * The virtual start address of the kpm range within the kernel 140 * virtual address space. kpm_vbase has to be kpm_size aligned. 141 */ 142 kpm_size = (size_t)(2ull * 1024 * 1024 * 1024 * 1024); /* 2TB */ 143 kpm_size_shift = 41; 144 kpm_vbase = (caddr_t)0xfffffa0000000000ull; /* 16EB - 6TB */ 145 146 /* 147 * The traptrace code uses either %tick or %stick for 148 * timestamping. We have %stick so we can use it. 149 */ 150 traptrace_use_stick = 1; 151 152 /* 153 * sun4v provides demap_all 154 */ 155 if (!disable_delay_tlb_flush) 156 delay_tlb_flush = 1; 157 } 158 159 /* 160 * Set the magic constants of the implementation. 161 */ 162 void 163 cpu_fiximp(struct cpu_node *cpunode) 164 { 165 extern int vac_size, vac_shift; 166 extern uint_t vac_mask; 167 int i, a; 168 169 /* 170 * The assumption here is that fillsysinfo will eventually 171 * have code to fill this info in from the PD. 172 * We hard code this for now. 173 * Once the PD access library is done this code 174 * might need to be changed to get the info from the PD 175 */ 176 /* 177 * Page Coloring defaults for sun4v 178 */ 179 ecache_setsize = 0x100000; 180 ecache_alignsize = 64; 181 cpunode->ecache_setsize = 0x100000; 182 183 vac_size = S_VAC_SIZE; 184 vac_mask = MMU_PAGEMASK & (vac_size - 1); 185 i = 0; a = vac_size; 186 while (a >>= 1) 187 ++i; 188 vac_shift = i; 189 shm_alignment = vac_size; 190 vac = 0; 191 } 192 193 void 194 dtrace_flush_sec(uintptr_t addr) 195 { 196 pfn_t pfn; 197 proc_t *procp = ttoproc(curthread); 198 page_t *pp; 199 caddr_t va; 200 201 pfn = hat_getpfnum(procp->p_as->a_hat, (void *)addr); 202 if (pfn != -1) { 203 ASSERT(pf_is_memory(pfn)); 204 pp = page_numtopp_noreclaim(pfn, SE_SHARED); 205 if (pp != NULL) { 206 va = ppmapin(pp, PROT_READ | PROT_WRITE, (void *)addr); 207 /* sparc needs 8-byte align */ 208 doflush((caddr_t)((uintptr_t)va & -8l)); 209 ppmapout(va); 210 page_unlock(pp); 211 } 212 } 213 } 214 215 void 216 cpu_init_private(struct cpu *cp) 217 { 218 /* 219 * The cpu_ipipe field is initialized based on the execution 220 * unit sharing information from the Machine Description table. 221 * It defaults to the CPU id in the absence of such information. 222 */ 223 cp->cpu_m.cpu_ipipe = (id_t)(cp->cpu_id); 224 } 225 226 void 227 cpu_uninit_private(struct cpu *cp) 228 { 229 } 230 231 /* 232 * Invalidate a TSB. Since this needs to work on all sun4v 233 * architecture compliant processors, we use the old method of 234 * walking the TSB, setting each tag to TSBTAG_INVALID. 235 */ 236 void 237 cpu_inv_tsb(caddr_t tsb_base, uint_t tsb_bytes) 238 { 239 struct tsbe *tsbaddr; 240 241 for (tsbaddr = (struct tsbe *)tsb_base; 242 (uintptr_t)tsbaddr < (uintptr_t)(tsb_base + tsb_bytes); 243 tsbaddr++) { 244 tsbaddr->tte_tag.tag_inthi = TSBTAG_INVALID; 245 } 246 } 247 248 /* 249 * Trapstat support for generic sun4v processor 250 */ 251 int 252 cpu_trapstat_conf(int cmd) 253 { 254 int status; 255 256 switch (cmd) { 257 case CPU_TSTATCONF_INIT: 258 case CPU_TSTATCONF_FINI: 259 case CPU_TSTATCONF_ENABLE: 260 case CPU_TSTATCONF_DISABLE: 261 status = ENOTSUP; 262 break; 263 264 default: 265 status = EINVAL; 266 break; 267 } 268 return (status); 269 } 270 271 /*ARGSUSED*/ 272 void 273 cpu_trapstat_data(void *buf, uint_t tstat_pgszs) 274 { 275 } 276