aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2005-08-19 00:52:31 -0400
committerPaul Mackerras <paulus@samba.org>2005-08-28 20:53:33 -0400
commit2e2446ea0758cd57dd065962d9544e3f4d44ea2b (patch)
tree745b7fb19e2fb48265aed6eb8ee33217a9e3f22a /arch
parent19dbd0f6a74f7529d6d49dd50ad6b31adbe0598d (diff)
[PATCH] Remove NACA fixed address constraint
Comments in head.S suggest that the iSeries naca has a fixed address, because tools expect to find it there. The only tool which appears to access the naca is addRamDisk, but both the in-kernel version and the version used in RHEL and SuSE in fact locate the NACA the same way as the hypervisor does, by following the pointer in the hvReleaseData structure. Since the requirement for a fixed address seems to be obsolete, this patch removes the naca from head.S and replaces it with a normal C initializer. For good measure, it removes an old version of addRamDisk.c which was sitting, unused, in the ppc32 tree. Signed-off-by: David Gibson <dwg@au1.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/ppc/boot/utils/addRamDisk.c203
-rw-r--r--arch/ppc64/kernel/LparData.c11
-rw-r--r--arch/ppc64/kernel/head.S17
3 files changed, 12 insertions, 219 deletions
diff --git a/arch/ppc/boot/utils/addRamDisk.c b/arch/ppc/boot/utils/addRamDisk.c
deleted file mode 100644
index 93400dfcce7f..000000000000
--- a/arch/ppc/boot/utils/addRamDisk.c
+++ /dev/null
@@ -1,203 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <netinet/in.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <string.h>
8
9#define ElfHeaderSize (64 * 1024)
10#define ElfPages (ElfHeaderSize / 4096)
11#define KERNELBASE (0xc0000000)
12
13void get4k(FILE *file, char *buf )
14{
15 unsigned j;
16 unsigned num = fread(buf, 1, 4096, file);
17 for ( j=num; j<4096; ++j )
18 buf[j] = 0;
19}
20
21void put4k(FILE *file, char *buf )
22{
23 fwrite(buf, 1, 4096, file);
24}
25
26void death(const char *msg, FILE *fdesc, const char *fname)
27{
28 printf(msg);
29 fclose(fdesc);
30 unlink(fname);
31 exit(1);
32}
33
34int main(int argc, char **argv)
35{
36 char inbuf[4096];
37 FILE *ramDisk = NULL;
38 FILE *inputVmlinux = NULL;
39 FILE *outputVmlinux = NULL;
40 unsigned i = 0;
41 u_int32_t ramFileLen = 0;
42 u_int32_t ramLen = 0;
43 u_int32_t roundR = 0;
44 u_int32_t kernelLen = 0;
45 u_int32_t actualKernelLen = 0;
46 u_int32_t round = 0;
47 u_int32_t roundedKernelLen = 0;
48 u_int32_t ramStartOffs = 0;
49 u_int32_t ramPages = 0;
50 u_int32_t roundedKernelPages = 0;
51 u_int32_t hvReleaseData = 0;
52 u_int32_t eyeCatcher = 0xc8a5d9c4;
53 u_int32_t naca = 0;
54 u_int32_t xRamDisk = 0;
55 u_int32_t xRamDiskSize = 0;
56 if ( argc < 2 ) {
57 printf("Name of RAM disk file missing.\n");
58 exit(1);
59 }
60
61 if ( argc < 3 ) {
62 printf("Name of vmlinux file missing.\n");
63 exit(1);
64 }
65
66 if ( argc < 4 ) {
67 printf("Name of vmlinux output file missing.\n");
68 exit(1);
69 }
70
71 ramDisk = fopen(argv[1], "r");
72 if ( ! ramDisk ) {
73 printf("RAM disk file \"%s\" failed to open.\n", argv[1]);
74 exit(1);
75 }
76 inputVmlinux = fopen(argv[2], "r");
77 if ( ! inputVmlinux ) {
78 printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
79 exit(1);
80 }
81 outputVmlinux = fopen(argv[3], "w+");
82 if ( ! outputVmlinux ) {
83 printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
84 exit(1);
85 }
86 fseek(ramDisk, 0, SEEK_END);
87 ramFileLen = ftell(ramDisk);
88 fseek(ramDisk, 0, SEEK_SET);
89 printf("%s file size = %d\n", argv[1], ramFileLen);
90
91 ramLen = ramFileLen;
92
93 roundR = 4096 - (ramLen % 4096);
94 if ( roundR ) {
95 printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR);
96 ramLen += roundR;
97 }
98
99 printf("Rounded RAM disk size is %d\n", ramLen);
100 fseek(inputVmlinux, 0, SEEK_END);
101 kernelLen = ftell(inputVmlinux);
102 fseek(inputVmlinux, 0, SEEK_SET);
103 printf("kernel file size = %d\n", kernelLen);
104 if ( kernelLen == 0 ) {
105 printf("You must have a linux kernel specified as argv[2]\n");
106 exit(1);
107 }
108
109 actualKernelLen = kernelLen - ElfHeaderSize;
110
111 printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);
112
113 round = actualKernelLen % 4096;
114 roundedKernelLen = actualKernelLen;
115 if ( round )
116 roundedKernelLen += (4096 - round);
117
118 printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen);
119
120 ramStartOffs = roundedKernelLen;
121 ramPages = ramLen / 4096;
122
123 printf("RAM disk pages to copy = %d\n", ramPages);
124
125 // Copy 64K ELF header
126 for (i=0; i<(ElfPages); ++i) {
127 get4k( inputVmlinux, inbuf );
128 put4k( outputVmlinux, inbuf );
129 }
130
131 roundedKernelPages = roundedKernelLen / 4096;
132
133 fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
134
135 for ( i=0; i<roundedKernelPages; ++i ) {
136 get4k( inputVmlinux, inbuf );
137 put4k( outputVmlinux, inbuf );
138 }
139
140 for ( i=0; i<ramPages; ++i ) {
141 get4k( ramDisk, inbuf );
142 put4k( outputVmlinux, inbuf );
143 }
144
145 /* Close the input files */
146 fclose(ramDisk);
147 fclose(inputVmlinux);
148 /* And flush the written output file */
149 fflush(outputVmlinux);
150
151 /* fseek to the hvReleaseData pointer */
152 fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
153 if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
154 death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]);
155 }
156 hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
157 printf("hvReleaseData is at %08x\n", hvReleaseData);
158
159 /* fseek to the hvReleaseData */
160 fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
161 if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
162 death("Could not read hvReleaseData\n", outputVmlinux, argv[3]);
163 }
164 /* Check hvReleaseData sanity */
165 if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
166 death("hvReleaseData is invalid\n", outputVmlinux, argv[3]);
167 }
168 /* Get the naca pointer */
169 naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE;
170 printf("naca is at %08x\n", naca);
171
172 /* fseek to the naca */
173 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
174 if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
175 death("Could not read naca\n", outputVmlinux, argv[3]);
176 }
177 xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
178 xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
179 /* Make sure a RAM disk isn't already present */
180 if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
181 death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]);
182 }
183 /* Fill in the values */
184 *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
185 *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
186
187 /* Write out the new naca */
188 fflush(outputVmlinux);
189 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
190 if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
191 death("Could not write naca\n", outputVmlinux, argv[3]);
192 }
193 printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",
194 ramPages, ramStartOffs);
195
196 /* Done */
197 fclose(outputVmlinux);
198 /* Set permission to executable */
199 chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
200
201 return 0;
202}
203
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index 1c11031c838e..3b9a2600fec2 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -51,6 +51,17 @@ struct HvReleaseData hvReleaseData = {
51 0xf4, 0x4b, 0xf6, 0xf4 }, 51 0xf4, 0x4b, 0xf6, 0xf4 },
52}; 52};
53 53
54/*
55 * The NACA. The first dword of the naca is required by the iSeries
56 * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
57 * through the pointer in hvReleaseData.
58 */
59struct naca_struct naca = {
60 .xItVpdAreas = &itVpdAreas,
61 .xRamDisk = 0,
62 .xRamDiskSize = 0,
63};
64
54extern void system_reset_iSeries(void); 65extern void system_reset_iSeries(void);
55extern void machine_check_iSeries(void); 66extern void machine_check_iSeries(void);
56extern void data_access_iSeries(void); 67extern void data_access_iSeries(void);
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index accaa052d31f..13c03648a602 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -30,7 +30,6 @@
30#include <asm/processor.h> 30#include <asm/processor.h>
31#include <asm/page.h> 31#include <asm/page.h>
32#include <asm/mmu.h> 32#include <asm/mmu.h>
33#include <asm/naca.h>
34#include <asm/systemcfg.h> 33#include <asm/systemcfg.h>
35#include <asm/ppc_asm.h> 34#include <asm/ppc_asm.h>
36#include <asm/offsets.h> 35#include <asm/offsets.h>
@@ -511,24 +510,10 @@ _GLOBAL(do_stab_bolted_pSeries)
511 mfspr r12,SPRG2 510 mfspr r12,SPRG2
512 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) 511 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
513 512
514
515 /* Space for the naca. Architected to be located at real address
516 * NACA_PHYS_ADDR. Various tools rely on this location being fixed.
517 * The first dword of the naca is required by iSeries LPAR to
518 * point to itVpdAreas. On pSeries native, this value is not used.
519 */
520 . = NACA_PHYS_ADDR
521 .globl __end_interrupts
522__end_interrupts:
523#ifdef CONFIG_PPC_ISERIES
524 .globl naca
525naca:
526 .llong itVpdAreas
527 .llong 0 /* xRamDisk */
528 .llong 0 /* xRamDiskSize */
529 513
530 . = 0x6100 514 . = 0x6100
531 515
516#ifdef CONFIG_PPC_ISERIES
532/*** ISeries-LPAR interrupt handlers ***/ 517/*** ISeries-LPAR interrupt handlers ***/
533 518
534 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) 519 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC)