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 2006 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/machsystm.h> 30 #include <sys/cpu.h> 31 #include <sys/intreg.h> 32 #include <sys/machcpuvar.h> 33 #include <vm/hat_sfmmu.h> 34 #include <sys/error.h> 35 #include <sys/hypervisor_api.h> 36 37 /* 38 * XXX needs to be set by some algorithm that derives this 39 * from the partition description 40 */ 41 int cpu_q_entries = 128; 42 int dev_q_entries = 128; 43 44 /* 45 * Once the partition description if finallized 46 * cpu_q_entries and dev_q_entries will be set 47 * and be garaunteed to be two's power multiples. 48 */ 49 #define INTR_CPU_Q 0x3c 50 #define INTR_DEV_Q 0x3d 51 #define INTR_REPORT_SIZE 64 52 #define INTR_CPU_Q_SIZE (cpu_q_entries * INTR_REPORT_SIZE) 53 #define INTR_DEV_Q_SIZE (dev_q_entries * INTR_REPORT_SIZE) 54 55 /* 56 * XXX - This needs to be rewritten with prom calls to 57 * let OBP know the queues are allocated 58 */ 59 void 60 cpu_intrq_register(struct cpu *cpu) 61 { 62 struct machcpu *mcpup = &cpu->cpu_m; 63 uint64_t ret; 64 65 ret = hv_cpu_qconf(INTR_CPU_Q, mcpup->cpu_q_base_pa, cpu_q_entries); 66 if (ret != H_EOK) 67 cmn_err(CE_PANIC, "cpu%d: cpu_mondo queue configuration " 68 "failed, error %lu", cpu->cpu_id, ret); 69 70 ret = hv_cpu_qconf(INTR_DEV_Q, mcpup->dev_q_base_pa, dev_q_entries); 71 if (ret != H_EOK) 72 cmn_err(CE_PANIC, "cpu%d: dev_mondo queue configuration " 73 "failed, error %lu", cpu->cpu_id, ret); 74 75 ret = hv_cpu_qconf(CPU_RQ, mcpup->cpu_rq_base_pa, CPU_RQ_ENTRIES); 76 if (ret != H_EOK) 77 cmn_err(CE_PANIC, "cpu%d: resumable error queue configuration " 78 "failed, error %lu", cpu->cpu_id, ret); 79 80 ret = hv_cpu_qconf(CPU_NRQ, mcpup->cpu_nrq_base_pa, 81 CPU_NRQ_ENTRIES); 82 if (ret != H_EOK) 83 cmn_err(CE_PANIC, "cpu%d: non-resumable error queue " 84 "configuration failed, error %lu", cpu->cpu_id, ret); 85 } 86 87 void 88 cpu_intrq_setup(struct cpu *cpu) 89 { 90 struct machcpu *mcpup = &cpu->cpu_m; 91 int cpu_list_size; 92 93 /* 94 * Allocate mondo data for xcalls. 95 */ 96 mcpup->mondo_data = contig_mem_alloc(INTR_REPORT_SIZE); 97 if (mcpup->mondo_data == NULL) 98 cmn_err(CE_PANIC, "cpu%d: cpu mondo_data allocation failed", 99 cpu->cpu_id); 100 101 /* 102 * Allocate a percpu list of NCPU for xcalls 103 */ 104 cpu_list_size = NCPU * sizeof (uint16_t); 105 if (cpu_list_size < INTR_REPORT_SIZE) 106 cpu_list_size = INTR_REPORT_SIZE; 107 108 mcpup->cpu_list = contig_mem_alloc(cpu_list_size); 109 if (mcpup->cpu_list == NULL) 110 cmn_err(CE_PANIC, "cpu%d: cpu cpu_list allocation failed", 111 cpu->cpu_id); 112 mcpup->cpu_list_ra = va_to_pa(mcpup->cpu_list); 113 114 /* 115 * va_to_pa() is too expensive to call for every crosscall 116 * so we do it here at init time and save it in machcpu. 117 */ 118 mcpup->mondo_data_ra = va_to_pa(mcpup->mondo_data); 119 120 /* 121 * Allocate sun4v interrupt and error queues. 122 */ 123 mcpup->cpu_q_va = contig_mem_alloc(INTR_CPU_Q_SIZE); 124 if (mcpup->cpu_q_va == NULL) 125 cmn_err(CE_PANIC, "cpu%d: cpu intrq allocation failed", 126 cpu->cpu_id); 127 mcpup->cpu_q_base_pa = va_to_pa(mcpup->cpu_q_va); 128 mcpup->cpu_q_size = INTR_CPU_Q_SIZE; 129 130 mcpup->dev_q_va = contig_mem_alloc(INTR_DEV_Q_SIZE); 131 if (mcpup->dev_q_va == NULL) 132 cmn_err(CE_PANIC, "cpu%d: dev intrq allocation failed", 133 cpu->cpu_id); 134 mcpup->dev_q_base_pa = va_to_pa(mcpup->dev_q_va); 135 mcpup->dev_q_size = INTR_DEV_Q_SIZE; 136 137 /* Allocate resumable queue and its kernel buffer */ 138 mcpup->cpu_rq_va = contig_mem_alloc(2 * CPU_RQ_SIZE); 139 if (mcpup->cpu_rq_va == NULL) 140 cmn_err(CE_PANIC, "cpu%d: resumable queue allocation failed", 141 cpu->cpu_id); 142 mcpup->cpu_rq_base_pa = va_to_pa(mcpup->cpu_rq_va); 143 mcpup->cpu_rq_size = CPU_RQ_SIZE; 144 /* zero out the memory */ 145 bzero(mcpup->cpu_rq_va, 2 * CPU_RQ_SIZE); 146 147 /* Allocate nonresumable queue here */ 148 mcpup->cpu_nrq_va = contig_mem_alloc(2 * CPU_NRQ_SIZE); 149 if (mcpup->cpu_nrq_va == NULL) 150 cmn_err(CE_PANIC, "cpu%d: nonresumable queue " 151 "allocation failed", cpu->cpu_id); 152 mcpup->cpu_nrq_base_pa = va_to_pa(mcpup->cpu_nrq_va); 153 mcpup->cpu_nrq_size = CPU_NRQ_SIZE; 154 /* zero out the memory */ 155 bzero(mcpup->cpu_nrq_va, 2 * CPU_NRQ_SIZE); 156 157 } 158