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

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

Unify handling of compressed init data and use regular tar + gzip to achieve it

There are two issues this commit solves.

First is that architecture-specific code duplicates most of the init binary
handling in each architecture, each with miniscule and confusing variations.
After this commit, the init binary expansion is almost entirely handled by
unified generic code.

Second is that the way we used to generate the incorporated data is somewhat
convoluted. Previously we have a Python script which generates a zip archive
with individual deflate-compressed files and accompanying header and C files
which contain structures describing the archive contents.
The zip file is then extracted and the individual deflate-compressed files are
included in the binary via assembler code.
Since gas doesn't take particular care to be consistent between architectures,
the assembly portions are also not uniform and the build script needs to know
particulars of the architecture's assembly.

Instead of doing that, after this commit we first gzip each included file, then
we pack the gzipped files into a tar archive, and then we include the archive
into the binary using objcopy.
Linker script provides symbols for the start and end of the archive,
and the payload is in a self-describing format, so there is no need for any
generated code.

Note that we are doing the opposite of the conventional .tar.gz format.
It would be somewhat inconvenient to use .tar.gz since the uncompressed files
need to be aligned to page size, so we'd have to first decompress the entire
payload to determine the final position of the files (and hence the required
amount of memory).

  • Property mode set to 100644
File size: 8.0 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 <payload.h>
45
46/* The lowest ID (read from the VER register) of some US3 CPU model */
47#define FIRST_US3_CPU 0x14
48
49/* The greatest ID (read from the VER register) of some US3 CPU model */
50#define LAST_US3_CPU 0x19
51
52/* UltraSPARC IIIi processor implementation code */
53#define US_IIIi_CODE 0x15
54
55#define OBP_BIAS 0x400000
56
57#define BALLOC_MAX_SIZE 131072
58
59#define TOP2ADDR(top) (((void *) KERNEL_ADDRESS) + (top))
60
61/** UltraSPARC architecture */
62static uint8_t arch;
63
64/** UltraSPARC subarchitecture */
65static uint8_t subarch;
66
67/** Mask of the MID field inside the ICBUS_CONFIG register
68 *
69 * Shifted by MID_SHIFT bits to the right
70 *
71 */
72static uint16_t mid_mask;
73
74static bootinfo_t bootinfo;
75
76/** Detect the UltraSPARC architecture
77 *
78 * Detection is done by inspecting the property called "compatible"
79 * in the OBP root node. Currently sun4u and sun4v are supported.
80 * Set global variable "arch" to the correct value.
81 *
82 */
83static void arch_detect(void)
84{
85 phandle root = ofw_find_device("/");
86 char compatible[OFW_TREE_PROPERTY_MAX_VALUELEN];
87
88 if (ofw_get_property(root, "compatible", compatible,
89 OFW_TREE_PROPERTY_MAX_VALUELEN) <= 0) {
90 printf("Warning: Unable to determine architecture, assuming sun4u.\n");
91 arch = ARCH_SUN4U;
92 return;
93 }
94
95 if (str_cmp(compatible, "sun4v") != 0) {
96 /*
97 * As not all sun4u machines have "sun4u" in their "compatible"
98 * OBP property (e.g. Serengeti's OBP "compatible" property is
99 * "SUNW,Serengeti"), we will by default fallback to sun4u if
100 * an unknown value of the "compatible" property is encountered.
101 */
102 if (str_cmp(compatible, "sun4u") != 0)
103 printf("Warning: Unknown architecture, assuming sun4u.\n");
104 arch = ARCH_SUN4U;
105 } else
106 arch = ARCH_SUN4V;
107}
108
109/** Detect the subarchitecture (US, US3) of sun4u
110 *
111 * Set the global variables "subarch" and "mid_mask" to
112 * correct values.
113 *
114 */
115static void sun4u_subarch_detect(void)
116{
117 uint64_t ver;
118 asm volatile (
119 "rdpr %%ver, %[ver]\n"
120 : [ver] "=r" (ver)
121 );
122
123 ver = (ver << 16) >> 48;
124
125 if ((ver >= FIRST_US3_CPU) && (ver <= LAST_US3_CPU)) {
126 subarch = SUBARCH_US3;
127
128 if (ver == US_IIIi_CODE)
129 mid_mask = (1 << 5) - 1;
130 else
131 mid_mask = (1 << 10) - 1;
132
133 } else if (ver < FIRST_US3_CPU) {
134 subarch = SUBARCH_US;
135 mid_mask = (1 << 5) - 1;
136 } else {
137 printf("Warning: This CPU is not supported.");
138 subarch = SUBARCH_UNKNOWN;
139 }
140}
141
142/** Perform sun4u-specific SMP initialization.
143 *
144 */
145static void sun4u_smp(void)
146{
147#ifdef CONFIG_AP
148 printf("Checking for secondary processors ...\n");
149 ofw_cpu(mid_mask, bootinfo.physmem_start);
150#endif
151}
152
153/** Perform sun4v-specific fixups.
154 *
155 */
156static void sun4v_fixups(void)
157{
158 /*
159 * When SILO booted, the OBP had established a virtual to physical
160 * memory mapping. This mapping is not an identity since the
161 * physical memory starts at non-zero address.
162 *
163 * However, the mapping even does not map virtual address 0
164 * onto the starting address of the physical memory, but onto an
165 * address which is 0x400000 (OBP_BIAS) bytes higher.
166 *
167 * The reason is that the OBP had already used the memory just
168 * at the beginning of the physical memory. Thus that memory cannot
169 * be used by SILO (nor the bootloader).
170 *
171 * So far, we solve it by a nasty workaround:
172 *
173 * We pretend that the physical memory starts 0x400000 (OBP_BIAS)
174 * bytes further than it actually does (and hence pretend that the
175 * physical memory is 0x400000 bytes smaller). Of course, the value
176 * 0x400000 will most probably depend on the machine and OBP version
177 * (the workaround works on Simics).
178 *
179 * A proper solution would be to inspect the "available" property
180 * of the "/memory" node to find out which parts of memory
181 * are used by OBP and redesign the algorithm of copying
182 * kernel/init tasks/ramdisk from the bootable image to memory.
183 */
184 bootinfo.physmem_start += OBP_BIAS;
185 bootinfo.memmap.zones[0].start += OBP_BIAS;
186 bootinfo.memmap.zones[0].size -= OBP_BIAS;
187 bootinfo.memmap.total -= OBP_BIAS;
188}
189
190void bootstrap(void)
191{
192 version_print();
193
194 arch_detect();
195 if (arch == ARCH_SUN4U)
196 sun4u_subarch_detect();
197 else
198 subarch = SUBARCH_UNKNOWN;
199
200 bootinfo.physmem_start = ofw_get_physmem_start();
201 ofw_memmap(&bootinfo.memmap);
202
203 if (arch == ARCH_SUN4V)
204 sun4v_fixups();
205
206 void *bootinfo_pa = ofw_translate(&bootinfo);
207 void *kernel_address_pa = ofw_translate((void *) KERNEL_ADDRESS);
208 void *loader_address_pa = ofw_translate((void *) LOADER_ADDRESS);
209
210 printf("\nMemory statistics (total %" PRIu64 " MB, starting at %p)\n",
211 bootinfo.memmap.total >> 20, (void *) bootinfo.physmem_start);
212 printf(" %p|%p: boot info structure\n", &bootinfo, (void *) bootinfo_pa);
213 printf(" %p|%p: kernel entry point\n",
214 (void *) KERNEL_ADDRESS, (void *) kernel_address_pa);
215 printf(" %p|%p: loader entry point\n",
216 (void *) LOADER_ADDRESS, (void *) loader_address_pa);
217
218 /*
219 * At this point, we claim and map the physical memory that we
220 * are going to use. We should be safe in case of the virtual
221 * address space because the OpenFirmware, according to its
222 * SPARC binding, should restrict its use of virtual memory to
223 * addresses from [0xffd00000; 0xffefffff] and [0xfe000000;
224 * 0xfeffffff].
225 */
226
227 size_t sz = ALIGN_UP(payload_uncompressed_size(), PAGE_SIZE);
228 ofw_claim_phys((void *) (bootinfo.physmem_start + KERNEL_ADDRESS), sz);
229 ofw_map((void *) (bootinfo.physmem_start + KERNEL_ADDRESS),
230 (void *) KERNEL_ADDRESS, sz, -1);
231
232 /* Extract components. */
233
234 // TODO: Cache-coherence callback?
235 extract_payload(&bootinfo.taskmap, (void *) KERNEL_ADDRESS,
236 (void *) KERNEL_ADDRESS + sz, KERNEL_ADDRESS, NULL);
237
238 /*
239 * Claim and map the physical memory for the boot allocator.
240 * Initialize the boot allocator.
241 */
242 printf("Setting up boot allocator ...\n");
243 void *balloc_base = (void *) KERNEL_ADDRESS + sz;
244 ofw_claim_phys(bootinfo.physmem_start + balloc_base, BALLOC_MAX_SIZE);
245 ofw_map(bootinfo.physmem_start + balloc_base, balloc_base,
246 BALLOC_MAX_SIZE, -1);
247 balloc_init(&bootinfo.ballocs, balloc_base, (uintptr_t) balloc_base,
248 BALLOC_MAX_SIZE);
249
250 printf("Setting up screens ...\n");
251 ofw_setup_screens();
252
253 printf("Canonizing OpenFirmware device tree ...\n");
254 bootinfo.ofw_root = ofw_tree_build();
255
256 if (arch == ARCH_SUN4U)
257 sun4u_smp();
258
259 printf("Booting the kernel ...\n");
260 jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, subarch,
261 (void *) KERNEL_ADDRESS);
262}
Note: See TracBrowser for help on using the repository browser.