10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1991Sheppo * Common Development and Distribution License (the "License"). 6*1991Sheppo * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21*1991Sheppo 220Sstevel@tonic-gate /* 231342Sae112802 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/machsystm.h> 300Sstevel@tonic-gate #include <sys/cpu.h> 310Sstevel@tonic-gate #include <sys/intreg.h> 320Sstevel@tonic-gate #include <sys/machcpuvar.h> 330Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 340Sstevel@tonic-gate #include <sys/error.h> 350Sstevel@tonic-gate #include <sys/hypervisor_api.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate void 380Sstevel@tonic-gate cpu_intrq_register(struct cpu *cpu) 390Sstevel@tonic-gate { 400Sstevel@tonic-gate struct machcpu *mcpup = &cpu->cpu_m; 410Sstevel@tonic-gate uint64_t ret; 420Sstevel@tonic-gate 430Sstevel@tonic-gate ret = hv_cpu_qconf(INTR_CPU_Q, mcpup->cpu_q_base_pa, cpu_q_entries); 440Sstevel@tonic-gate if (ret != H_EOK) 450Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: cpu_mondo queue configuration " 460Sstevel@tonic-gate "failed, error %lu", cpu->cpu_id, ret); 470Sstevel@tonic-gate 480Sstevel@tonic-gate ret = hv_cpu_qconf(INTR_DEV_Q, mcpup->dev_q_base_pa, dev_q_entries); 490Sstevel@tonic-gate if (ret != H_EOK) 500Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: dev_mondo queue configuration " 510Sstevel@tonic-gate "failed, error %lu", cpu->cpu_id, ret); 520Sstevel@tonic-gate 53*1991Sheppo ret = hv_cpu_qconf(CPU_RQ, mcpup->cpu_rq_base_pa, cpu_rq_entries); 540Sstevel@tonic-gate if (ret != H_EOK) 550Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: resumable error queue configuration " 560Sstevel@tonic-gate "failed, error %lu", cpu->cpu_id, ret); 570Sstevel@tonic-gate 58*1991Sheppo ret = hv_cpu_qconf(CPU_NRQ, mcpup->cpu_nrq_base_pa, cpu_nrq_entries); 590Sstevel@tonic-gate if (ret != H_EOK) 600Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: non-resumable error queue " 610Sstevel@tonic-gate "configuration failed, error %lu", cpu->cpu_id, ret); 620Sstevel@tonic-gate } 630Sstevel@tonic-gate 640Sstevel@tonic-gate void 650Sstevel@tonic-gate cpu_intrq_setup(struct cpu *cpu) 660Sstevel@tonic-gate { 670Sstevel@tonic-gate struct machcpu *mcpup = &cpu->cpu_m; 680Sstevel@tonic-gate int cpu_list_size; 69*1991Sheppo uint64_t cpu_q_size; 70*1991Sheppo uint64_t dev_q_size; 71*1991Sheppo uint64_t cpu_rq_size; 72*1991Sheppo uint64_t cpu_nrq_size; 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * Allocate mondo data for xcalls. 760Sstevel@tonic-gate */ 770Sstevel@tonic-gate mcpup->mondo_data = contig_mem_alloc(INTR_REPORT_SIZE); 780Sstevel@tonic-gate if (mcpup->mondo_data == NULL) 790Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: cpu mondo_data allocation failed", 800Sstevel@tonic-gate cpu->cpu_id); 810Sstevel@tonic-gate 820Sstevel@tonic-gate /* 830Sstevel@tonic-gate * Allocate a percpu list of NCPU for xcalls 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate cpu_list_size = NCPU * sizeof (uint16_t); 860Sstevel@tonic-gate if (cpu_list_size < INTR_REPORT_SIZE) 870Sstevel@tonic-gate cpu_list_size = INTR_REPORT_SIZE; 880Sstevel@tonic-gate 890Sstevel@tonic-gate mcpup->cpu_list = contig_mem_alloc(cpu_list_size); 901342Sae112802 if (mcpup->cpu_list == NULL) 911342Sae112802 cmn_err(CE_PANIC, "cpu%d: cpu cpu_list allocation failed", 920Sstevel@tonic-gate cpu->cpu_id); 930Sstevel@tonic-gate mcpup->cpu_list_ra = va_to_pa(mcpup->cpu_list); 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * va_to_pa() is too expensive to call for every crosscall 970Sstevel@tonic-gate * so we do it here at init time and save it in machcpu. 980Sstevel@tonic-gate */ 990Sstevel@tonic-gate mcpup->mondo_data_ra = va_to_pa(mcpup->mondo_data); 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /* 1020Sstevel@tonic-gate * Allocate sun4v interrupt and error queues. 1030Sstevel@tonic-gate */ 104*1991Sheppo cpu_q_size = cpu_q_entries * INTR_REPORT_SIZE; 105*1991Sheppo mcpup->cpu_q_va = contig_mem_alloc(cpu_q_size); 1060Sstevel@tonic-gate if (mcpup->cpu_q_va == NULL) 1070Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: cpu intrq allocation failed", 1080Sstevel@tonic-gate cpu->cpu_id); 1090Sstevel@tonic-gate mcpup->cpu_q_base_pa = va_to_pa(mcpup->cpu_q_va); 110*1991Sheppo mcpup->cpu_q_size = cpu_q_size; 1110Sstevel@tonic-gate 112*1991Sheppo dev_q_size = dev_q_entries * INTR_REPORT_SIZE; 113*1991Sheppo mcpup->dev_q_va = contig_mem_alloc(dev_q_size); 1140Sstevel@tonic-gate if (mcpup->dev_q_va == NULL) 1150Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: dev intrq allocation failed", 1160Sstevel@tonic-gate cpu->cpu_id); 1170Sstevel@tonic-gate mcpup->dev_q_base_pa = va_to_pa(mcpup->dev_q_va); 118*1991Sheppo mcpup->dev_q_size = dev_q_size; 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* Allocate resumable queue and its kernel buffer */ 121*1991Sheppo cpu_rq_size = cpu_rq_entries * Q_ENTRY_SIZE; 122*1991Sheppo mcpup->cpu_rq_va = contig_mem_alloc(2 * cpu_rq_size); 1230Sstevel@tonic-gate if (mcpup->cpu_rq_va == NULL) 1240Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: resumable queue allocation failed", 1250Sstevel@tonic-gate cpu->cpu_id); 1260Sstevel@tonic-gate mcpup->cpu_rq_base_pa = va_to_pa(mcpup->cpu_rq_va); 127*1991Sheppo mcpup->cpu_rq_size = cpu_rq_size; 1280Sstevel@tonic-gate /* zero out the memory */ 129*1991Sheppo bzero(mcpup->cpu_rq_va, 2 * cpu_rq_size); 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* Allocate nonresumable queue here */ 132*1991Sheppo cpu_nrq_size = cpu_nrq_entries * Q_ENTRY_SIZE; 133*1991Sheppo mcpup->cpu_nrq_va = contig_mem_alloc(2 * cpu_nrq_size); 1340Sstevel@tonic-gate if (mcpup->cpu_nrq_va == NULL) 1350Sstevel@tonic-gate cmn_err(CE_PANIC, "cpu%d: nonresumable queue " 1360Sstevel@tonic-gate "allocation failed", cpu->cpu_id); 1370Sstevel@tonic-gate mcpup->cpu_nrq_base_pa = va_to_pa(mcpup->cpu_nrq_va); 138*1991Sheppo mcpup->cpu_nrq_size = cpu_nrq_size; 1390Sstevel@tonic-gate /* zero out the memory */ 140*1991Sheppo bzero(mcpup->cpu_nrq_va, 2 * cpu_nrq_size); 141*1991Sheppo } 142*1991Sheppo 143*1991Sheppo void 144*1991Sheppo cpu_intrq_cleanup(struct cpu *cpu) 145*1991Sheppo { 146*1991Sheppo struct machcpu *mcpup = &cpu->cpu_m; 147*1991Sheppo int cpu_list_size; 148*1991Sheppo uint64_t cpu_q_size; 149*1991Sheppo uint64_t dev_q_size; 150*1991Sheppo uint64_t cpu_rq_size; 151*1991Sheppo uint64_t cpu_nrq_size; 152*1991Sheppo 153*1991Sheppo /* 154*1991Sheppo * Free mondo data for xcalls. 155*1991Sheppo */ 156*1991Sheppo if (mcpup->mondo_data) { 157*1991Sheppo contig_mem_free(mcpup->mondo_data, INTR_REPORT_SIZE); 158*1991Sheppo mcpup->mondo_data = NULL; 159*1991Sheppo mcpup->mondo_data_ra = NULL; 160*1991Sheppo } 161*1991Sheppo 162*1991Sheppo /* 163*1991Sheppo * Free percpu list of NCPU for xcalls 164*1991Sheppo */ 165*1991Sheppo cpu_list_size = NCPU * sizeof (uint16_t); 166*1991Sheppo if (cpu_list_size < INTR_REPORT_SIZE) 167*1991Sheppo cpu_list_size = INTR_REPORT_SIZE; 168*1991Sheppo 169*1991Sheppo if (mcpup->cpu_list) { 170*1991Sheppo contig_mem_free(mcpup->cpu_list, cpu_list_size); 171*1991Sheppo mcpup->cpu_list = NULL; 172*1991Sheppo mcpup->cpu_list_ra = NULL; 173*1991Sheppo } 1740Sstevel@tonic-gate 175*1991Sheppo /* 176*1991Sheppo * Free sun4v interrupt and error queues. 177*1991Sheppo */ 178*1991Sheppo if (mcpup->cpu_q_va) { 179*1991Sheppo cpu_q_size = cpu_q_entries * INTR_REPORT_SIZE; 180*1991Sheppo contig_mem_free(mcpup->cpu_q_va, cpu_q_size); 181*1991Sheppo mcpup->cpu_q_va = NULL; 182*1991Sheppo mcpup->cpu_q_base_pa = NULL; 183*1991Sheppo mcpup->cpu_q_size = 0; 184*1991Sheppo } 185*1991Sheppo 186*1991Sheppo if (mcpup->dev_q_va) { 187*1991Sheppo dev_q_size = dev_q_entries * INTR_REPORT_SIZE; 188*1991Sheppo contig_mem_free(mcpup->dev_q_va, dev_q_size); 189*1991Sheppo mcpup->dev_q_va = NULL; 190*1991Sheppo mcpup->dev_q_base_pa = NULL; 191*1991Sheppo mcpup->dev_q_size = 0; 192*1991Sheppo } 193*1991Sheppo 194*1991Sheppo if (mcpup->cpu_rq_va) { 195*1991Sheppo cpu_rq_size = cpu_rq_entries * Q_ENTRY_SIZE; 196*1991Sheppo contig_mem_free(mcpup->cpu_rq_va, 2 * cpu_rq_size); 197*1991Sheppo mcpup->cpu_rq_va = NULL; 198*1991Sheppo mcpup->cpu_rq_base_pa = NULL; 199*1991Sheppo mcpup->cpu_rq_size = 0; 200*1991Sheppo } 201*1991Sheppo 202*1991Sheppo if (mcpup->cpu_nrq_va) { 203*1991Sheppo cpu_nrq_size = cpu_nrq_entries * Q_ENTRY_SIZE; 204*1991Sheppo contig_mem_free(mcpup->cpu_nrq_va, 2 * cpu_nrq_size); 205*1991Sheppo mcpup->cpu_nrq_va = NULL; 206*1991Sheppo mcpup->cpu_nrq_base_pa = NULL; 207*1991Sheppo mcpup->cpu_nrq_size = 0; 208*1991Sheppo } 2090Sstevel@tonic-gate } 210