1*1ae08745Sheppo /* 2*1ae08745Sheppo * CDDL HEADER START 3*1ae08745Sheppo * 4*1ae08745Sheppo * The contents of this file are subject to the terms of the 5*1ae08745Sheppo * Common Development and Distribution License (the "License"). 6*1ae08745Sheppo * You may not use this file except in compliance with the License. 7*1ae08745Sheppo * 8*1ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 10*1ae08745Sheppo * See the License for the specific language governing permissions 11*1ae08745Sheppo * and limitations under the License. 12*1ae08745Sheppo * 13*1ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 14*1ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 16*1ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 17*1ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 18*1ae08745Sheppo * 19*1ae08745Sheppo * CDDL HEADER END 20*1ae08745Sheppo */ 21*1ae08745Sheppo 22*1ae08745Sheppo /* 23*1ae08745Sheppo * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1ae08745Sheppo * Use is subject to license terms. 25*1ae08745Sheppo */ 26*1ae08745Sheppo 27*1ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI" 28*1ae08745Sheppo 29*1ae08745Sheppo #include <sys/types.h> 30*1ae08745Sheppo #include <sys/machsystm.h> 31*1ae08745Sheppo #include <sys/machparam.h> 32*1ae08745Sheppo #include <sys/cmn_err.h> 33*1ae08745Sheppo #include <sys/cpuvar.h> 34*1ae08745Sheppo #include <sys/note.h> 35*1ae08745Sheppo #include <sys/hypervisor_api.h> 36*1ae08745Sheppo #include <sys/lpad.h> 37*1ae08745Sheppo 38*1ae08745Sheppo typedef struct { 39*1ae08745Sheppo uint64_t inuse; 40*1ae08745Sheppo uint64_t buf[LPAD_SIZE / sizeof (uint64_t)]; 41*1ae08745Sheppo } lpad_t; 42*1ae08745Sheppo 43*1ae08745Sheppo /* 44*1ae08745Sheppo * A global pool of landing pad memory. Currently, CPUs are only 45*1ae08745Sheppo * brought into the system one at a time, so the pool is only a 46*1ae08745Sheppo * single landing pad. In the future, it may be desirable to bring 47*1ae08745Sheppo * CPUs into the systems in parallel. At that time, the size of 48*1ae08745Sheppo * the pool can be increased by changing the pool size constant. 49*1ae08745Sheppo */ 50*1ae08745Sheppo #define LPAD_POOL_SIZE 1 51*1ae08745Sheppo 52*1ae08745Sheppo static lpad_t lpad_pool[LPAD_POOL_SIZE]; 53*1ae08745Sheppo 54*1ae08745Sheppo #ifdef DEBUG 55*1ae08745Sheppo static int lpad_dbg = 0; 56*1ae08745Sheppo 57*1ae08745Sheppo #define LPAD_DBG if (lpad_dbg) printf 58*1ae08745Sheppo #define LPAD_DUMP_DATA lpad_dump_data 59*1ae08745Sheppo 60*1ae08745Sheppo static void lpad_dump_data(uint64_t *lpd_start, uint64_t *lpd_end); 61*1ae08745Sheppo 62*1ae08745Sheppo #else /* DEBUG */ 63*1ae08745Sheppo 64*1ae08745Sheppo #define LPAD_DBG _NOTE(CONSTCOND) if (0) printf 65*1ae08745Sheppo #define LPAD_DUMP_DATA 66*1ae08745Sheppo #endif /* DEBUG */ 67*1ae08745Sheppo 68*1ae08745Sheppo extern void mach_cpu_startup(uint64_t rabase, uint64_t memsize); 69*1ae08745Sheppo extern void mach_cpu_startup_end(void); 70*1ae08745Sheppo extern int promif_in_cif(void); 71*1ae08745Sheppo 72*1ae08745Sheppo static lpad_t *lpad_alloc(void); 73*1ae08745Sheppo 74*1ae08745Sheppo uint64_t * 75*1ae08745Sheppo lpad_setup(int cpuid, uint64_t pc, uint64_t arg) 76*1ae08745Sheppo { 77*1ae08745Sheppo lpad_t *lpp; 78*1ae08745Sheppo uint64_t textsz; 79*1ae08745Sheppo uint64_t datasz; 80*1ae08745Sheppo lpad_data_t *lpd; 81*1ae08745Sheppo lpad_map_t *lpm; 82*1ae08745Sheppo 83*1ae08745Sheppo /* external parameters */ 84*1ae08745Sheppo extern caddr_t textva; 85*1ae08745Sheppo extern caddr_t datava; 86*1ae08745Sheppo extern tte_t ktext_tte; 87*1ae08745Sheppo extern tte_t kdata_tte; 88*1ae08745Sheppo extern caddr_t mmu_fault_status_area; 89*1ae08745Sheppo 90*1ae08745Sheppo LPAD_DBG("lpad_setup...\n"); 91*1ae08745Sheppo 92*1ae08745Sheppo if ((cpuid < 0) || (cpuid > NCPU)) { 93*1ae08745Sheppo cmn_err(CE_PANIC, "lpad_setup: invalid cpuid"); 94*1ae08745Sheppo } 95*1ae08745Sheppo 96*1ae08745Sheppo /* allocate our landing pad */ 97*1ae08745Sheppo if ((lpp = lpad_alloc()) == NULL) { 98*1ae08745Sheppo cmn_err(CE_PANIC, "lpad_setup: unable to allocate lpad"); 99*1ae08745Sheppo } 100*1ae08745Sheppo 101*1ae08745Sheppo /* calculate the size of our text */ 102*1ae08745Sheppo textsz = (uint64_t)mach_cpu_startup_end - (uint64_t)mach_cpu_startup; 103*1ae08745Sheppo 104*1ae08745Sheppo LPAD_DBG("lpad textsz=%ld\n", textsz); 105*1ae08745Sheppo 106*1ae08745Sheppo ASSERT(textsz <= LPAD_TEXT_SIZE); 107*1ae08745Sheppo 108*1ae08745Sheppo /* copy over text section */ 109*1ae08745Sheppo bcopy((void *)mach_cpu_startup, lpp->buf, textsz); 110*1ae08745Sheppo 111*1ae08745Sheppo lpd = (lpad_data_t *)(((caddr_t)lpp->buf) + LPAD_TEXT_SIZE); 112*1ae08745Sheppo lpm = (lpad_map_t *)lpd->map; 113*1ae08745Sheppo 114*1ae08745Sheppo ASSERT(mmu_fault_status_area); 115*1ae08745Sheppo 116*1ae08745Sheppo bzero(lpd, LPAD_TEXT_SIZE); 117*1ae08745Sheppo lpd->magic = LPAD_MAGIC_VAL; 118*1ae08745Sheppo lpd->inuse = &(lpp->inuse); 119*1ae08745Sheppo lpd->mmfsa_ra = va_to_pa(mmu_fault_status_area) + (MMFSA_SIZE * cpuid); 120*1ae08745Sheppo lpd->pc = pc; 121*1ae08745Sheppo lpd->arg = arg; 122*1ae08745Sheppo 123*1ae08745Sheppo /* 124*1ae08745Sheppo * List of mappings: 125*1ae08745Sheppo * 126*1ae08745Sheppo * - permanent inst/data mapping for kernel text 127*1ae08745Sheppo * - permanent data mapping for kernel data 128*1ae08745Sheppo * - non-permanent inst mapping for kernel data, 129*1ae08745Sheppo * required for landing pad text 130*1ae08745Sheppo */ 131*1ae08745Sheppo lpd->nmap = 3; 132*1ae08745Sheppo 133*1ae08745Sheppo /* verify the lpad has enough room for the data */ 134*1ae08745Sheppo datasz = sizeof (lpad_data_t); 135*1ae08745Sheppo datasz += (lpd->nmap - 1) * sizeof (lpad_map_t); 136*1ae08745Sheppo 137*1ae08745Sheppo ASSERT(datasz <= LPAD_DATA_SIZE); 138*1ae08745Sheppo 139*1ae08745Sheppo /* 140*1ae08745Sheppo * Kernel Text Mapping 141*1ae08745Sheppo */ 142*1ae08745Sheppo lpm->va = (uint64_t)textva; 143*1ae08745Sheppo lpm->tte = ktext_tte; 144*1ae08745Sheppo lpm->flag_mmuflags = (MAP_ITLB | MAP_DTLB); 145*1ae08745Sheppo lpm->flag_perm = 1; 146*1ae08745Sheppo lpm++; 147*1ae08745Sheppo 148*1ae08745Sheppo /* 149*1ae08745Sheppo * Kernel Data Mapping 150*1ae08745Sheppo */ 151*1ae08745Sheppo lpm->va = (uint64_t)datava; 152*1ae08745Sheppo lpm->tte = kdata_tte; 153*1ae08745Sheppo lpm->flag_mmuflags = MAP_DTLB; 154*1ae08745Sheppo lpm->flag_perm = 1; 155*1ae08745Sheppo lpm++; 156*1ae08745Sheppo 157*1ae08745Sheppo /* 158*1ae08745Sheppo * Landing Pad Text Mapping 159*1ae08745Sheppo * 160*1ae08745Sheppo * Because this mapping should not be permanent, 161*1ae08745Sheppo * the permanent mapping above cannot be used. 162*1ae08745Sheppo */ 163*1ae08745Sheppo lpm->va = (uint64_t)datava; 164*1ae08745Sheppo lpm->tte = kdata_tte; 165*1ae08745Sheppo lpm->flag_mmuflags = MAP_ITLB; 166*1ae08745Sheppo lpm->flag_perm = 0; 167*1ae08745Sheppo lpm++; 168*1ae08745Sheppo 169*1ae08745Sheppo ASSERT(((uint64_t)lpm - (uint64_t)lpd) == datasz); 170*1ae08745Sheppo 171*1ae08745Sheppo LPAD_DBG("copied %ld bytes of data into lpad\n", datasz); 172*1ae08745Sheppo 173*1ae08745Sheppo LPAD_DUMP_DATA((uint64_t *)lpd, (uint64_t *)lpm); 174*1ae08745Sheppo 175*1ae08745Sheppo return (lpp->buf); 176*1ae08745Sheppo } 177*1ae08745Sheppo 178*1ae08745Sheppo static lpad_t * 179*1ae08745Sheppo lpad_alloc(void) 180*1ae08745Sheppo { 181*1ae08745Sheppo int idx; 182*1ae08745Sheppo 183*1ae08745Sheppo /* 184*1ae08745Sheppo * No locking is required for the global lpad pool since 185*1ae08745Sheppo * it should only be accessed while in the CIF which is 186*1ae08745Sheppo * single threaded. If this assumption changes, locking 187*1ae08745Sheppo * would be required. 188*1ae08745Sheppo */ 189*1ae08745Sheppo ASSERT(promif_in_cif()); 190*1ae08745Sheppo 191*1ae08745Sheppo /* 192*1ae08745Sheppo * Wait until an lpad buffer becomes available. 193*1ae08745Sheppo */ 194*1ae08745Sheppo for (;;) { 195*1ae08745Sheppo LPAD_DBG("checking lpad pool:\n"); 196*1ae08745Sheppo 197*1ae08745Sheppo /* walk the lpad buffer array */ 198*1ae08745Sheppo for (idx = 0; idx < LPAD_POOL_SIZE; idx++) { 199*1ae08745Sheppo 200*1ae08745Sheppo LPAD_DBG("\tchecking lpad_pool[%d]\n", idx); 201*1ae08745Sheppo 202*1ae08745Sheppo if (lpad_pool[idx].inuse == 0) { 203*1ae08745Sheppo LPAD_DBG("found empty lpad (%d)\n", idx); 204*1ae08745Sheppo 205*1ae08745Sheppo /* mark the buffer as busy */ 206*1ae08745Sheppo lpad_pool[idx].inuse = 1; 207*1ae08745Sheppo 208*1ae08745Sheppo return (&lpad_pool[idx]); 209*1ae08745Sheppo } 210*1ae08745Sheppo } 211*1ae08745Sheppo } 212*1ae08745Sheppo } 213*1ae08745Sheppo 214*1ae08745Sheppo #ifdef DEBUG 215*1ae08745Sheppo static void 216*1ae08745Sheppo lpad_dump_data(uint64_t *lpd_start, uint64_t *lpd_end) 217*1ae08745Sheppo { 218*1ae08745Sheppo uint64_t *lp; 219*1ae08745Sheppo uint_t offset = 0; 220*1ae08745Sheppo 221*1ae08745Sheppo if (lpad_dbg == 0) 222*1ae08745Sheppo return; 223*1ae08745Sheppo 224*1ae08745Sheppo printf("lpad data:\n"); 225*1ae08745Sheppo 226*1ae08745Sheppo for (lp = lpd_start; lp < lpd_end; lp++) { 227*1ae08745Sheppo printf("\t0x%02x 0x%016lx\n", offset, *lp); 228*1ae08745Sheppo offset += sizeof (uint64_t); 229*1ae08745Sheppo } 230*1ae08745Sheppo } 231*1ae08745Sheppo #endif /* DEBUG */ 232