1 /*
2 * Copyright 2001 Mike Corrigan, IBM Corp
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9 #include <asm/types.h>
10 #include <asm/page.h>
11 #include <stddef.h>
12 #include <linux/threads.h>
13 #include <asm/processor.h>
14 #include <asm/ptrace.h>
15 #include <asm/naca.h>
16 #include <asm/abs_addr.h>
17 #include <asm/bitops.h>
18 #include <asm/iSeries/ItLpNaca.h>
19 #include <asm/iSeries/ItLpPaca.h>
20 #include <asm/iSeries/ItLpRegSave.h>
21 #include <asm/paca.h>
22 #include <asm/iSeries/HvReleaseData.h>
23 #include <asm/iSeries/LparMap.h>
24 #include <asm/iSeries/ItVpdAreas.h>
25 #include <asm/iSeries/ItIplParmsReal.h>
26 #include <asm/iSeries/ItExtVpdPanel.h>
27 #include <asm/iSeries/ItLpQueue.h>
28 #include <asm/iSeries/IoHriProcessorVpd.h>
29 #include <asm/iSeries/ItSpCommArea.h>
30
31 extern char _start_boltedStacks[];
32
33 /* The LparMap data is now located at offset 0x6000 in head.S
34 * It was put there so that the HvReleaseData could address it
35 * with a 32-bit offset as required by the iSeries hypervisor
36 *
37 * The Naca has a pointer to the ItVpdAreas. The hypervisor finds
38 * the Naca via the HvReleaseData area. The HvReleaseData has the
39 * offset into the Naca of the pointer to the ItVpdAreas.
40 */
41
42 extern struct ItVpdAreas itVpdAreas;
43
44 /* The LpQueue is used to pass event data from the hypervisor to
45 * the partition. This is where I/O interrupt events are communicated.
46 * The ItLpQueue must be initialized (even though only to all zeros)
47 * If it were uninitialized (in .bss) it would get zeroed after the
48 * kernel gets control. The hypervisor will have filled in some fields
49 * before the kernel gets control. By initializing it we keep it out
50 * of the .bss
51 */
52
53 struct ItLpQueue xItLpQueue = {};
54
55
56 /* The HvReleaseData is the root of the information shared between
57 * the hypervisor and Linux.
58 */
59
60 struct HvReleaseData hvReleaseData = {
61 0xc8a5d9c4, /* desc = "HvRD" ebcdic */
62 sizeof(struct HvReleaseData),
63 offsetof(struct naca_struct, xItVpdAreas),
64 (struct naca_struct *)(KERNELBASE+0x4000), /* 64-bit Naca address */
65 0x6000, /* offset of LparMap within loadarea (see head.S) */
66 0,
67 1, /* tags inactive */
68 0, /* 64 bit */
69 0, /* shared processors */
70 0, /* HMT allowed */
71 6, /* TEMP: This allows non-GA driver */
72 4, /* We are v5r2m0 */
73 3, /* Min supported PLIC = v5r1m0 */
74 3, /* Min usable PLIC = v5r1m0 */
75 { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4 "*/
76 0xa7, 0x40, 0xf2, 0x4b,
77 0xf4, 0x4b, 0xf6, 0xf4 },
78 {0}
79 };
80
81 extern void SystemReset_Iseries(void);
82 extern void MachineCheck_Iseries(void);
83 extern void DataAccess_Iseries(void);
84 extern void InstructionAccess_Iseries(void);
85 extern void HardwareInterrupt_Iseries(void);
86 extern void Alignment_Iseries(void);
87 extern void ProgramCheck_Iseries(void);
88 extern void FPUnavailable_Iseries(void);
89 extern void Decrementer_Iseries(void);
90 extern void Trap_0a_Iseries(void);
91 extern void Trap_0b_Iseries(void);
92 extern void SystemCall_Iseries(void);
93 extern void SingleStep_Iseries(void);
94 extern void Trap_0e_Iseries(void);
95 extern void PerformanceMonitor_Iseries(void);
96 extern void DataAccessSLB_Iseries(void);
97 extern void InstructionAccessSLB_Iseries(void);
98
99 struct ItLpNaca itLpNaca = {
100 0xd397d581, /* desc = "LpNa" ebcdic */
101 0x0400, /* size of ItLpNaca */
102 0x0300, 19, /* offset to int array, # ents */
103 0, 0, 0, /* Part # of primary, serv, me */
104 0, 0x100, /* # of LP queues, offset */
105 0, 0, 0, /* Piranha stuff */
106 { 0,0,0,0,0 }, /* reserved */
107 0,0,0,0,0,0,0, /* stuff */
108 { 0,0,0,0,0 }, /* reserved */
109 0, /* reserved */
110 0, /* VRM index of PLIC */
111 0, 0, /* min supported, compat SLIC */
112 0, /* 64-bit addr of load area */
113 0, /* chunks for load area */
114 0, 0, /* PASE mask, seg table */
115 { 0 }, /* 64 reserved bytes */
116 { 0 }, /* 128 reserved bytes */
117 { 0 }, /* Old LP Queue */
118 { 0 }, /* 384 reserved bytes */
119 {
120 (u64)SystemReset_Iseries, /* 0x100 System Reset */
121 (u64)MachineCheck_Iseries, /* 0x200 Machine Check */
122 (u64)DataAccess_Iseries, /* 0x300 Data Access */
123 (u64)InstructionAccess_Iseries, /* 0x400 Instruction Access */
124 (u64)HardwareInterrupt_Iseries, /* 0x500 External */
125 (u64)Alignment_Iseries, /* 0x600 Alignment */
126 (u64)ProgramCheck_Iseries, /* 0x700 Program Check */
127 (u64)FPUnavailable_Iseries, /* 0x800 FP Unavailable */
128 (u64)Decrementer_Iseries, /* 0x900 Decrementer */
129 (u64)Trap_0a_Iseries, /* 0xa00 Trap 0A */
130 (u64)Trap_0b_Iseries, /* 0xb00 Trap 0B */
131 (u64)SystemCall_Iseries, /* 0xc00 System Call */
132 (u64)SingleStep_Iseries, /* 0xd00 Single Step */
133 (u64)Trap_0e_Iseries, /* 0xe00 Trap 0E */
134 (u64)PerformanceMonitor_Iseries,/* 0xf00 Performance Monitor */
135 0, /* int 0x1000 */
136 0, /* int 0x1010 */
137 0, /* int 0x1020 CPU ctls */
138 (u64)HardwareInterrupt_Iseries, /* SC Ret Hdlr */
139 (u64)DataAccessSLB_Iseries, /* 0x380 D-SLB */
140 (u64)InstructionAccessSLB_Iseries /* 0x480 I-SLB */
141 }
142 };
143
144 struct ItIplParmsReal xItIplParmsReal = {};
145
146 struct ItExtVpdPanel xItExtVpdPanel = {};
147
148 #define maxPhysicalProcessors 32
149
150 struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
151 {
152 xInstCacheOperandSize: 32,
153 xDataCacheOperandSize: 32,
154 xProcFreq: 50000000,
155 xTimeBaseFreq: 50000000,
156 xPVR: 0x3600
157 }
158 };
159
160
161 u64 xMsVpd[3400] = {}; /* Space for Main Store Vpd 27,200 bytes */
162
163 u64 xRecoveryLogBuffer[32] = {}; /* Space for Recovery Log Buffer */
164
165 struct SpCommArea xSpCommArea = {
166 0xE2D7C3C2,
167 1,
168 {0},
169 0, 0, 0, 0, {0}
170 };
171
172 struct ItVpdAreas itVpdAreas = {
173 0xc9a3e5c1, /* "ItVA" */
174 sizeof( struct ItVpdAreas ),
175 0, 0,
176 26, /* # VPD array entries */
177 10, /* # DMA array entries */
178 MAX_PROCESSORS*2, maxPhysicalProcessors, /* Max logical, physical procs */
179 offsetof(struct ItVpdAreas,xPlicDmaToks),/* offset to DMA toks */
180 offsetof(struct ItVpdAreas,xSlicVpdAdrs),/* offset to VPD addrs */
181 offsetof(struct ItVpdAreas,xPlicDmaLens),/* offset to DMA lens */
182 offsetof(struct ItVpdAreas,xSlicVpdLens),/* offset to VPD lens */
183 0, /* max slot labels */
184 1, /* max LP queues */
185 {0}, {0}, /* reserved */
186 {0}, /* DMA lengths */
187 {0}, /* DMA tokens */
188 { /* VPD lengths */
189 0,0,0, /* 0 - 2 */
190 sizeof(xItExtVpdPanel), /* 3 Extended VPD */
191 sizeof(struct paca_struct), /* 4 length of Paca */
192 0, /* 5 */
193 sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
194 26992, /* 7 length of MS VPD */
195 0, /* 8 */
196 sizeof(struct ItLpNaca),/* 9 length of LP Naca */
197 0, /* 10 */
198 256, /* 11 length of Recovery Log Buf */
199 sizeof(struct SpCommArea), /* 12 length of SP Comm Area */
200 0,0,0, /* 13 - 15 */
201 sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
202 0,0,0,0,0,0, /* 17 - 22 */
203 sizeof(struct ItLpQueue),/* 23 length of Lp Queue */
204 0,0 /* 24 - 25 */
205 },
206 { /* VPD addresses */
207 0,0,0, /* 0 - 2 */
208 &xItExtVpdPanel, /* 3 Extended VPD */
209 &paca[0], /* 4 first Paca */
210 0, /* 5 */
211 &xItIplParmsReal, /* 6 IPL parms */
212 &xMsVpd, /* 7 MS Vpd */
213 0, /* 8 */
214 &itLpNaca, /* 9 LpNaca */
215 0, /* 10 */
216 &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */
217 &xSpCommArea, /* 12 SP Comm Area */
218 0,0,0, /* 13 - 15 */
219 &xIoHriProcessorVpd, /* 16 Proc Vpd */
220 0,0,0,0,0,0, /* 17 - 22 */
221 &xItLpQueue, /* 23 Lp Queue */
222 0,0
223 }
224 };
225
226 struct msChunks msChunks = {0, 0, 0, 0, NULL};
227
228 /* Depending on whether this is called from iSeries or pSeries setup
229 * code, the location of the msChunks struct may or may not have
230 * to be reloc'd, so we force the caller to do that for us by passing
231 * in a pointer to the structure.
232 */
233 unsigned long
msChunks_alloc(unsigned long mem,unsigned long num_chunks,unsigned long chunk_size)234 msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size)
235 {
236 unsigned long offset = reloc_offset();
237 struct msChunks *_msChunks = PTRRELOC(&msChunks);
238
239 _msChunks->num_chunks = num_chunks;
240 _msChunks->chunk_size = chunk_size;
241 _msChunks->chunk_shift = __ilog2(chunk_size);
242 _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1;
243
244 mem = _ALIGN(mem, sizeof(msChunks_entry));
245 _msChunks->abs = (msChunks_entry *)(mem + offset);
246 mem += num_chunks * sizeof(msChunks_entry);
247
248 return mem;
249 }
250