source: mainline/boot/arch/sparc64/src/main.c@ a35b458

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
3 * Copyright (c) 2006 Jakub Jermar
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <arch/main.h>
31#include <arch/arch.h>
32#include <arch/asm.h>
33#include <arch/ofw.h>
34#include <genarch/ofw.h>
35#include <genarch/ofw_tree.h>
36#include <halt.h>
37#include <printf.h>
38#include <memstr.h>
39#include <version.h>
40#include <macros.h>
41#include <align.h>
42#include <str.h>
43#include <errno.h>
44#include <inflate.h>
45#include "../../components.h"
46
47/* The lowest ID (read from the VER register) of some US3 CPU model */
48#define FIRST_US3_CPU 0x14
49
50/* The greatest ID (read from the VER register) of some US3 CPU model */
51#define LAST_US3_CPU 0x19
52
53/* UltraSPARC IIIi processor implementation code */
54#define US_IIIi_CODE 0x15
55
56#define OBP_BIAS 0x400000
57
58#define BALLOC_MAX_SIZE 131072
59
60#define TOP2ADDR(top) (((void *) KERNEL_ADDRESS) + (top))
61
62/** UltraSPARC architecture */
63static uint8_t arch;
64
65/** UltraSPARC subarchitecture */
66static uint8_t subarch;
67
68/** Mask of the MID field inside the ICBUS_CONFIG register
69 *
70 * Shifted by MID_SHIFT bits to the right
71 *
72 */
73static uint16_t mid_mask;
74
75static bootinfo_t bootinfo;
76
77/** Detect the UltraSPARC architecture
78 *
79 * Detection is done by inspecting the property called "compatible"
80 * in the OBP root node. Currently sun4u and sun4v are supported.
81 * Set global variable "arch" to the correct value.
82 *
83 */
84static void arch_detect(void)
85{
86 phandle root = ofw_find_device("/");
87 char compatible[OFW_TREE_PROPERTY_MAX_VALUELEN];
88
89 if (ofw_get_property(root, "compatible", compatible,
90 OFW_TREE_PROPERTY_MAX_VALUELEN) <= 0) {
91 printf("Warning: Unable to determine architecture, assuming sun4u.\n");
92 arch = ARCH_SUN4U;
93 return;
94 }
95
96 if (str_cmp(compatible, "sun4v") != 0) {
97 /*
98 * As not all sun4u machines have "sun4u" in their "compatible"
99 * OBP property (e.g. Serengeti's OBP "compatible" property is
100 * "SUNW,Serengeti"), we will by default fallback to sun4u if
101 * an unknown value of the "compatible" property is encountered.
102 */
103 if (str_cmp(compatible, "sun4u") != 0)
104 printf("Warning: Unknown architecture, assuming sun4u.\n");
105 arch = ARCH_SUN4U;
106 } else
107 arch = ARCH_SUN4V;
108}
109
110
111/** Detect the subarchitecture (US, US3) of sun4u
112 *
113 * Set the global variables "subarch" and "mid_mask" to
114 * correct values.
115 *
116 */
117static void sun4u_subarch_detect(void)
118{
119 uint64_t ver;
120 asm volatile (
121 "rdpr %%ver, %[ver]\n"
122 : [ver] "=r" (ver)
123 );
124
125 ver = (ver << 16) >> 48;
126
127 if ((ver >= FIRST_US3_CPU) && (ver <= LAST_US3_CPU)) {
128 subarch = SUBARCH_US3;
129
130 if (ver == US_IIIi_CODE)
131 mid_mask = (1 << 5) - 1;
132 else
133 mid_mask = (1 << 10) - 1;
134
135 } else if (ver < FIRST_US3_CPU) {
136 subarch = SUBARCH_US;
137 mid_mask = (1 << 5) - 1;
138 } else {
139 printf("Warning: This CPU is not supported.");
140 subarch = SUBARCH_UNKNOWN;
141 }
142}
143
144/** Perform sun4u-specific SMP initialization.
145 *
146 */
147static void sun4u_smp(void)
148{
149#ifdef CONFIG_AP
150 printf("Checking for secondary processors ...\n");
151 ofw_cpu(mid_mask, bootinfo.physmem_start);
152#endif
153}
154
155/** Perform sun4v-specific fixups.
156 *
157 */
158static void sun4v_fixups(void)
159{
160 /*
161 * When SILO booted, the OBP had established a virtual to physical
162 * memory mapping. This mapping is not an identity since the
163 * physical memory starts at non-zero address.
164 *
165 * However, the mapping even does not map virtual address 0
166 * onto the starting address of the physical memory, but onto an
167 * address which is 0x400000 (OBP_BIAS) bytes higher.
168 *
169 * The reason is that the OBP had already used the memory just
170 * at the beginning of the physical memory. Thus that memory cannot
171 * be used by SILO (nor the bootloader).
172 *
173 * So far, we solve it by a nasty workaround:
174 *
175 * We pretend that the physical memory starts 0x400000 (OBP_BIAS)
176 * bytes further than it actually does (and hence pretend that the
177 * physical memory is 0x400000 bytes smaller). Of course, the value
178 * 0x400000 will most probably depend on the machine and OBP version
179 * (the workaround works on Simics).
180 *
181 * A proper solution would be to inspect the "available" property
182 * of the "/memory" node to find out which parts of memory
183 * are used by OBP and redesign the algorithm of copying
184 * kernel/init tasks/ramdisk from the bootable image to memory.
185 */
186 bootinfo.physmem_start += OBP_BIAS;
187 bootinfo.memmap.zones[0].start += OBP_BIAS;
188 bootinfo.memmap.zones[0].size -= OBP_BIAS;
189 bootinfo.memmap.total -= OBP_BIAS;
190}
191
192void bootstrap(void)
193{
194 version_print();
195
196 arch_detect();
197 if (arch == ARCH_SUN4U)
198 sun4u_subarch_detect();
199 else
200 subarch = SUBARCH_UNKNOWN;
201
202 bootinfo.physmem_start = ofw_get_physmem_start();
203 ofw_memmap(&bootinfo.memmap);
204
205 if (arch == ARCH_SUN4V)
206 sun4v_fixups();
207
208 void *bootinfo_pa = ofw_translate(&bootinfo);
209 void *kernel_address_pa = ofw_translate((void *) KERNEL_ADDRESS);
210 void *loader_address_pa = ofw_translate((void *) LOADER_ADDRESS);
211
212 printf("\nMemory statistics (total %" PRIu64 " MB, starting at %p)\n",
213 bootinfo.memmap.total >> 20, (void *) bootinfo.physmem_start);
214 printf(" %p|%p: boot info structure\n", &bootinfo, (void *) bootinfo_pa);
215 printf(" %p|%p: kernel entry point\n",
216 (void *) KERNEL_ADDRESS, (void *) kernel_address_pa);
217 printf(" %p|%p: loader entry point\n",
218 (void *) LOADER_ADDRESS, (void *) loader_address_pa);
219
220 size_t i;
221 for (i = 0; i < COMPONENTS; i++)
222 printf(" %p|%p: %s image (%zu/%zu bytes)\n", components[i].addr,
223 ofw_translate(components[i].addr), components[i].name,
224 components[i].inflated, components[i].size);
225
226 void *dest[COMPONENTS];
227 size_t top = KERNEL_ADDRESS;
228 size_t cnt = 0;
229 bootinfo.taskmap.cnt = 0;
230 for (i = 0; i < min(COMPONENTS, TASKMAP_MAX_RECORDS); i++) {
231 top = ALIGN_UP(top, PAGE_SIZE);
232
233 if (i > 0) {
234 bootinfo.taskmap.tasks[bootinfo.taskmap.cnt].addr =
235 (void *) top;
236 bootinfo.taskmap.tasks[bootinfo.taskmap.cnt].size =
237 components[i].inflated;
238
239 str_cpy(bootinfo.taskmap.tasks[bootinfo.taskmap.cnt].name,
240 BOOTINFO_TASK_NAME_BUFLEN, components[i].name);
241
242 bootinfo.taskmap.cnt++;
243 }
244
245 dest[i] = (void *) top;
246 top += components[i].inflated;
247 cnt++;
248 }
249
250 printf("\nInflating components ... ");
251
252 for (i = cnt; i > 0; i--) {
253 printf("%s ", components[i - 1].name);
254
255 /*
256 * At this point, we claim and map the physical memory that we
257 * are going to use. We should be safe in case of the virtual
258 * address space because the OpenFirmware, according to its
259 * SPARC binding, should restrict its use of virtual memory to
260 * addresses from [0xffd00000; 0xffefffff] and [0xfe000000;
261 * 0xfeffffff].
262 */
263 ofw_claim_phys(bootinfo.physmem_start + dest[i - 1],
264 ALIGN_UP(components[i - 1].inflated, PAGE_SIZE));
265
266 ofw_map(bootinfo.physmem_start + dest[i - 1], dest[i - 1],
267 ALIGN_UP(components[i - 1].inflated, PAGE_SIZE), -1);
268
269 int err = inflate(components[i - 1].addr, components[i - 1].size,
270 dest[i - 1], components[i - 1].inflated);
271
272 if (err != EOK) {
273 printf("\n%s: Inflating error %d, halting.\n",
274 components[i - 1].name, err);
275 halt();
276 }
277 }
278
279 printf(".\n");
280
281 /*
282 * Claim and map the physical memory for the boot allocator.
283 * Initialize the boot allocator.
284 */
285 printf("Setting up boot allocator ...\n");
286 void *balloc_base = (void *) ALIGN_UP(top, PAGE_SIZE);
287 ofw_claim_phys(bootinfo.physmem_start + balloc_base, BALLOC_MAX_SIZE);
288 ofw_map(bootinfo.physmem_start + balloc_base, balloc_base,
289 BALLOC_MAX_SIZE, -1);
290 balloc_init(&bootinfo.ballocs, balloc_base, (uintptr_t) balloc_base,
291 BALLOC_MAX_SIZE);
292
293 printf("Setting up screens ...\n");
294 ofw_setup_screens();
295
296 printf("Canonizing OpenFirmware device tree ...\n");
297 bootinfo.ofw_root = ofw_tree_build();
298
299 if (arch == ARCH_SUN4U)
300 sun4u_smp();
301
302 printf("Booting the kernel ...\n");
303 jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, subarch,
304 (void *) KERNEL_ADDRESS);
305}
Note: See TracBrowser for help on using the repository browser.