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

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

Keep kernel in ELF format

By keeping kernel in an ELF file (instead of converting it to
a flat binary), we can use the information it contains, like
symbol table and debug info.

We can also later implement more advanced functionality, like
loading kernel at multiple discontiguous blocks, or loading
a position-independent kernel at a randomized address.

Currently the functionality is quite restricted, to keep changes
to a minimum. Code in boot/generic/src/kernel.c validates that
the kernel image was built with the same addresses as the boot
loader uses, giving an extra level of sanity checking compared
to a flat binary.

  • Property mode set to 100644
File size: 8.1 KB
RevLine 
[4872160]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>
[63a045c]44#include <payload.h>
[cfdeedc]45#include <kernel.h>
[4872160]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];
[a35b458]88
[4872160]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 }
[a35b458]95
[4872160]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 */
[9644c69]103 if (str_cmp(compatible, "sun4u") != 0)
104 printf("Warning: Unknown architecture, assuming sun4u.\n");
[4872160]105 arch = ARCH_SUN4U;
106 } else
107 arch = ARCH_SUN4V;
108}
109
110/** Detect the subarchitecture (US, US3) of sun4u
111 *
112 * Set the global variables "subarch" and "mid_mask" to
113 * correct values.
114 *
115 */
116static void sun4u_subarch_detect(void)
117{
118 uint64_t ver;
119 asm volatile (
[1433ecda]120 "rdpr %%ver, %[ver]\n"
121 : [ver] "=r" (ver)
[4872160]122 );
[a35b458]123
[4872160]124 ver = (ver << 16) >> 48;
[a35b458]125
[4872160]126 if ((ver >= FIRST_US3_CPU) && (ver <= LAST_US3_CPU)) {
127 subarch = SUBARCH_US3;
[a35b458]128
[4872160]129 if (ver == US_IIIi_CODE)
130 mid_mask = (1 << 5) - 1;
131 else
132 mid_mask = (1 << 10) - 1;
[a35b458]133
[4872160]134 } else if (ver < FIRST_US3_CPU) {
135 subarch = SUBARCH_US;
136 mid_mask = (1 << 5) - 1;
137 } else {
138 printf("Warning: This CPU is not supported.");
139 subarch = SUBARCH_UNKNOWN;
140 }
141}
142
143/** Perform sun4u-specific SMP initialization.
144 *
145 */
146static void sun4u_smp(void)
147{
148#ifdef CONFIG_AP
149 printf("Checking for secondary processors ...\n");
150 ofw_cpu(mid_mask, bootinfo.physmem_start);
151#endif
152}
153
154/** Perform sun4v-specific fixups.
155 *
156 */
157static void sun4v_fixups(void)
158{
159 /*
160 * When SILO booted, the OBP had established a virtual to physical
161 * memory mapping. This mapping is not an identity since the
162 * physical memory starts at non-zero address.
163 *
164 * However, the mapping even does not map virtual address 0
165 * onto the starting address of the physical memory, but onto an
166 * address which is 0x400000 (OBP_BIAS) bytes higher.
167 *
168 * The reason is that the OBP had already used the memory just
169 * at the beginning of the physical memory. Thus that memory cannot
170 * be used by SILO (nor the bootloader).
171 *
172 * So far, we solve it by a nasty workaround:
173 *
174 * We pretend that the physical memory starts 0x400000 (OBP_BIAS)
175 * bytes further than it actually does (and hence pretend that the
176 * physical memory is 0x400000 bytes smaller). Of course, the value
177 * 0x400000 will most probably depend on the machine and OBP version
178 * (the workaround works on Simics).
179 *
180 * A proper solution would be to inspect the "available" property
181 * of the "/memory" node to find out which parts of memory
182 * are used by OBP and redesign the algorithm of copying
[336d2f52]183 * kernel/init tasks/ramdisk from the bootable image to memory.
[4872160]184 */
185 bootinfo.physmem_start += OBP_BIAS;
186 bootinfo.memmap.zones[0].start += OBP_BIAS;
187 bootinfo.memmap.zones[0].size -= OBP_BIAS;
[e7c42ac0]188 bootinfo.memmap.total -= OBP_BIAS;
[4872160]189}
190
191void bootstrap(void)
192{
193 version_print();
[a35b458]194
[4872160]195 arch_detect();
196 if (arch == ARCH_SUN4U)
197 sun4u_subarch_detect();
198 else
199 subarch = SUBARCH_UNKNOWN;
[a35b458]200
[4872160]201 bootinfo.physmem_start = ofw_get_physmem_start();
202 ofw_memmap(&bootinfo.memmap);
[e7c42ac0]203
204 if (arch == ARCH_SUN4V)
205 sun4v_fixups();
[a35b458]206
[4872160]207 void *bootinfo_pa = ofw_translate(&bootinfo);
[b97b348]208 void *kernel_address_pa = ofw_translate((void *) KERNEL_ADDRESS);
[4872160]209 void *loader_address_pa = ofw_translate((void *) LOADER_ADDRESS);
[a35b458]210
[7e752b2]211 printf("\nMemory statistics (total %" PRIu64 " MB, starting at %p)\n",
212 bootinfo.memmap.total >> 20, (void *) bootinfo.physmem_start);
213 printf(" %p|%p: boot info structure\n", &bootinfo, (void *) bootinfo_pa);
214 printf(" %p|%p: kernel entry point\n",
215 (void *) KERNEL_ADDRESS, (void *) kernel_address_pa);
216 printf(" %p|%p: loader entry point\n",
217 (void *) LOADER_ADDRESS, (void *) loader_address_pa);
[a35b458]218
[63a045c]219 /*
220 * At this point, we claim and map the physical memory that we
221 * are going to use. We should be safe in case of the virtual
222 * address space because the OpenFirmware, according to its
223 * SPARC binding, should restrict its use of virtual memory to
224 * addresses from [0xffd00000; 0xffefffff] and [0xfe000000;
225 * 0xfeffffff].
226 */
[a35b458]227
[dcc2c5d]228 size_t sz = ALIGN_UP(payload_unpacked_size(), PAGE_SIZE);
[63a045c]229 ofw_claim_phys((void *) (bootinfo.physmem_start + KERNEL_ADDRESS), sz);
230 ofw_map((void *) (bootinfo.physmem_start + KERNEL_ADDRESS),
231 (void *) KERNEL_ADDRESS, sz, -1);
[a35b458]232
[63a045c]233 /* Extract components. */
[a35b458]234
[63a045c]235 // TODO: Cache-coherence callback?
236 extract_payload(&bootinfo.taskmap, (void *) KERNEL_ADDRESS,
237 (void *) KERNEL_ADDRESS + sz, KERNEL_ADDRESS, NULL);
[a35b458]238
[4872160]239 /*
240 * Claim and map the physical memory for the boot allocator.
241 * Initialize the boot allocator.
242 */
243 printf("Setting up boot allocator ...\n");
[63a045c]244 void *balloc_base = (void *) KERNEL_ADDRESS + sz;
[4872160]245 ofw_claim_phys(bootinfo.physmem_start + balloc_base, BALLOC_MAX_SIZE);
246 ofw_map(bootinfo.physmem_start + balloc_base, balloc_base,
247 BALLOC_MAX_SIZE, -1);
248 balloc_init(&bootinfo.ballocs, balloc_base, (uintptr_t) balloc_base,
249 BALLOC_MAX_SIZE);
[a35b458]250
[4872160]251 printf("Setting up screens ...\n");
252 ofw_setup_screens();
[a35b458]253
[4872160]254 printf("Canonizing OpenFirmware device tree ...\n");
255 bootinfo.ofw_root = ofw_tree_build();
[a35b458]256
[4872160]257 if (arch == ARCH_SUN4U)
258 sun4u_smp();
[a35b458]259
[cfdeedc]260 uintptr_t entry = check_kernel((void *) KERNEL_ADDRESS);
261
[4872160]262 printf("Booting the kernel ...\n");
[cfdeedc]263 jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo,
264 subarch, (void *) entry);
[4872160]265}
Note: See TracBrowser for help on using the repository browser.