xref: /illumos-gate/usr/src/uts/sun4v/os/intrq.c (revision 22defd95)
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