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 2004 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 /*
30 * Following is STARFIRE specific code
31 */
32
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/archsystm.h>
36 #include <sys/machsystm.h>
37 #include <sys/vmem.h>
38 #include <sys/mman.h>
39 #include <sys/vm.h>
40
41 #include <sys/cmn_err.h>
42 #include <sys/cpu_sgnblk_defs.h>
43 #include <sys/starfire.h>
44
45 #include <vm/seg.h>
46 #include <vm/seg_kmem.h>
47 #include <vm/seg_kp.h>
48 #include <sys/vtrace.h>
49 #include <sys/cpu_sgn.h>
50
51 /*
52 * SIGBCPU represents the cpu maintaining the primary
53 * sigblock (bbsram). This bbsram is used for CVC
54 * and maintains the post2obp structure. It starts
55 * out as the bootproc (cpu0).
56 */
57 struct cpu *SIGBCPU = &cpu0;
58
59 cpu_sgnblk_t *cpu_sgnblkp[NCPU];
60
61 /*
62 * Mapin the the cpu's signature block.
63 */
64 void
cpu_sgn_mapin(int cpuid)65 cpu_sgn_mapin(int cpuid)
66 {
67 uint64_t bbsram_physaddr;
68 uint64_t cpu_sgnblk_physaddr;
69 uint32_t cpu_sgnblk_offset;
70 caddr_t cvaddr;
71 pgcnt_t num_pages;
72 pfn_t pfn;
73
74 ASSERT(cpu_sgnblkp[cpuid] == NULL);
75
76 /*
77 * Construct the physical base address of the bbsram
78 * in PSI space associated with this cpu in question.
79 */
80 cpu_sgnblk_physaddr = bbsram_physaddr =
81 STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE;
82
83 /*
84 * The cpu_sgnblk pointer offsets are stored in the
85 * undefined hardware trap slot 0x7f which is located
86 * at offset 0xfe0. There are 2 of them since the
87 * bbsram is shared among the 2 cpus residing on the
88 * a PC. We need to determine the CPU in question whether
89 * it is in port 0 or 1. CPU on port 0 has its
90 * signature blkptr stored in 0xfe0 while the cpu_sgnblk
91 * ptr of local port 1's CPU is in offset 0xfe8.
92 */
93 if (cpuid & 0x1) {
94 /* CPU is in local port 1 */
95 bbsram_physaddr |= 0xfe8ULL;
96 } else {
97 /* CPU is in local port 0 */
98 bbsram_physaddr |= 0xfe0ULL;
99 }
100
101 /*
102 * Read in the cpu_sgnblk pointer offset. Add it to the bbsram
103 * base address to get the base address of the cpu_sgnblk.
104 */
105 cpu_sgnblk_offset = ldphysio(bbsram_physaddr);
106 cpu_sgnblk_physaddr += cpu_sgnblk_offset;
107
108 pfn = (pfn_t)(cpu_sgnblk_physaddr >> MMU_PAGESHIFT);
109
110 num_pages = mmu_btopr(((cpu_sgnblk_physaddr &
111 MMU_PAGEOFFSET) + sizeof (cpu_sgnblk_t)));
112
113 /*
114 * Map in the cpu_sgnblk
115 */
116 cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP);
117
118 hat_devload(kas.a_hat, cvaddr, ptob(num_pages),
119 pfn, PROT_READ | PROT_WRITE, HAT_LOAD_LOCK);
120
121 cpu_sgnblkp[cpuid] = ((cpu_sgnblk_t *)(cvaddr +
122 (uint32_t)(cpu_sgnblk_offset & MMU_PAGEOFFSET)));
123 }
124
125 void
cpu_sgn_mapout(int cpuid)126 cpu_sgn_mapout(int cpuid)
127 {
128 ulong_t cvaddr, num_pages;
129 uint32_t cpu_sgnblk_offset;
130 uint64_t cpu_sgnblk_physaddr;
131 uint64_t bbsram_physaddr;
132
133 if ((cvaddr = (ulong_t)cpu_sgnblkp[cpuid]) == NULL) {
134 cmn_err(CE_WARN, "cpu_sgn_mapout: ERROR: "
135 "cpu_sgnblkp[%d] = NULL\n", cpuid);
136 } else {
137 cvaddr &= ~MMU_PAGEOFFSET;
138
139 /*
140 * Construct the physical base address of the bbsram
141 * in PSI space associated with this cpu in question.
142 */
143 bbsram_physaddr = STARFIRE_UPAID2UPS(cpuid) |
144 STARFIRE_PSI_BASE;
145 cpu_sgnblk_physaddr = bbsram_physaddr;
146
147 /*
148 * The cpu_sgnblk pointer offsets are stored in the
149 * undefined hardware trap slot 0x7f which is located
150 * at offset 0xfe0. There are 2 of them since the
151 * bbsram is shared among the 2 cpus residing on the
152 * a PC. We need to determine the CPU in question whether
153 * it is in port 0 or 1. CPU on port 0 has its
154 * signature blkptr stored in 0xfe0 while the cpu_sgnblk
155 * ptr of local port 1's CPU is in offset 0xfe8.
156 */
157 if (cpuid & 0x1) {
158 /* CPU is in local port 1 */
159 bbsram_physaddr |= 0xfe8ULL;
160 } else {
161 /* CPU is in local port 0 */
162 bbsram_physaddr |= 0xfe0ULL;
163 }
164
165 /*
166 * Read in the cpu_sgnblk pointer offset. Add it to the bbsram
167 * base address to get the base address of the cpu_sgnblk.
168 */
169 cpu_sgnblk_offset = ldphysio(bbsram_physaddr);
170 cpu_sgnblk_physaddr += cpu_sgnblk_offset;
171
172 num_pages = mmu_btopr(((uint_t)(cpu_sgnblk_physaddr &
173 MMU_PAGEOFFSET) + sizeof (cpu_sgnblk_t)));
174
175 hat_unload(kas.a_hat, (caddr_t)cvaddr, ptob(num_pages),
176 HAT_UNLOAD_UNLOCK);
177 vmem_free(heap_arena, (caddr_t)cvaddr, ptob(num_pages));
178
179 cpu_sgnblkp[cpuid] = NULL;
180 }
181 }
182