summaryrefslogtreecommitdiff
path: root/arch/ppc64/kernel/LparData.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2005-07-27 11:44:21 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-27 16:25:58 -0700
commit488f84994c55927eef587a0827dc957c908a0bad (patch)
tree34bdc42927e2eb559bd64039ed87508a440dffc6 /arch/ppc64/kernel/LparData.c
parent533f08172e21521a74e15cdef8a13c929596d506 (diff)
[PATCH] ppc64: remove another fixed address constraint
Presently the LparMap, one of the structures the kernel shares with the legacy iSeries hypervisor has a fixed offset address in head.S. This patch changes this so the LparMap is a normally initialized structure, without fixed address. This allows us to use macros to compute some of the values in the structure, which wasn't previously possible because the assembler always uses signed-% which gets the wrong answers for the computations in question. Unfortunately, a gcc bug means that doing this requires another structure (hvReleaseData) to be initialized in asm instead of C, but on the whole the result is cleaner than before. Signed-off-by: David Gibson <dwg@au1.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc64/kernel/LparData.c')
-rw-r--r--arch/ppc64/kernel/LparData.c88
1 files changed, 82 insertions, 6 deletions
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index 6ffcf67dd507..76cfd1449d52 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -33,17 +33,36 @@
* the hypervisor and Linux.
*/
+/*
+ * WARNING - magic here
+ *
+ * Ok, this is a horrid hack below, but marginally better than the
+ * alternatives. What we really want is just to initialize
+ * hvReleaseData in C as in the #if 0 section here. However, gcc
+ * refuses to believe that (u32)&x is a constant expression, so will
+ * not allow the xMsNucDataOffset field to be properly initialized.
+ * So, we declare hvReleaseData in inline asm instead. We use inline
+ * asm, rather than a .S file, because the assembler won't generate
+ * the necessary relocation for the LparMap either, unless that symbol
+ * is declared in the same source file. Finally, we put the asm in a
+ * dummy, attribute-used function, instead of at file scope, because
+ * file scope asms don't allow contraints. We want to use the "i"
+ * constraints to put sizeof() and offsetof() expressions in there,
+ * because including asm/offsets.h in C code then stringifying causes
+ * all manner of warnings.
+ */
+#if 0
struct HvReleaseData hvReleaseData = {
.xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
.xSize = sizeof(struct HvReleaseData),
.xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
.xSlicNacaAddr = &naca, /* 64-bit Naca address */
- .xMsNucDataOffset = 0x4800, /* offset of LparMap within loadarea (see head.S) */
- .xTagsMode = 1, /* tags inactive */
- .xAddressSize = 0, /* 64 bit */
- .xNoSharedProcs = 0, /* shared processors */
- .xNoHMT = 0, /* HMT allowed */
- .xRsvd2 = 6, /* TEMP: This allows non-GA driver */
+ .xMsNucDataOffset = (u32)((unsigned long)&xLparMap - KERNELBASE),
+ .xFlags = HVREL_TAGSINACTIVE /* tags inactive */
+ /* 64 bit */
+ /* shared processors */
+ /* HMT allowed */
+ | 6, /* TEMP: This allows non-GA driver */
.xVrmIndex = 4, /* We are v5r2m0 */
.xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */
.xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */
@@ -51,6 +70,63 @@ struct HvReleaseData hvReleaseData = {
0xa7, 0x40, 0xf2, 0x4b,
0xf4, 0x4b, 0xf6, 0xf4 },
};
+#endif
+
+
+extern struct HvReleaseData hvReleaseData;
+
+static void __attribute_used__ hvReleaseData_wrapper(void)
+{
+ /* This doesn't appear to need any alignment (even 4 byte) */
+ asm volatile (
+ " lparMapPhys = xLparMap - %3\n"
+ " .data\n"
+ " .globl hvReleaseData\n"
+ "hvReleaseData:\n"
+ " .long 0xc8a5d9c4\n" /* xDesc */
+ /* "HvRD" in ebcdic */
+ " .short %0\n" /* xSize */
+ " .short %1\n" /* xVpdAreasPtrOffset */
+ " .llong naca\n" /* xSlicNacaAddr */
+ " .long lparMapPhys\n" /* xMsNucDataOffset */
+ " .long 0\n" /* xRsvd1 */
+ " .short %2\n" /* xFlags */
+ " .short 4\n" /* xVrmIndex - v5r2m0 */
+ " .short 3\n" /* xMinSupportedPlicVrmIndex - v5r1m0 */
+ " .short 3\n" /* xMinCompatablePlicVrmIndex - v5r1m0 */
+ " .long 0xd38995a4\n" /* xVrmName */
+ " .long 0xa740f24b\n" /* "Linux 2.4.64" ebcdic */
+ " .long 0xf44bf6f4\n"
+ " . = hvReleaseData + %0\n"
+ " .previous\n"
+ : : "i"(sizeof(hvReleaseData)),
+ "i"(offsetof(struct naca_struct, xItVpdAreas)),
+ "i"(HVREL_TAGSINACTIVE /* tags inactive, 64 bit, */
+ /* shared processors, HMT allowed */
+ | 6), /* TEMP: This allows non-GA drivers */
+ "i"(KERNELBASE)
+ );
+}
+
+struct LparMap __attribute__((aligned (16))) xLparMap = {
+ .xNumberEsids = HvEsidsToMap,
+ .xNumberRanges = HvRangesToMap,
+ .xSegmentTableOffs = STAB0_PAGE,
+
+ .xEsids = {
+ { .xKernelEsid = GET_ESID(KERNELBASE),
+ .xKernelVsid = KERNEL_VSID(KERNELBASE), },
+ { .xKernelEsid = GET_ESID(VMALLOCBASE),
+ .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
+ },
+
+ .xRanges = {
+ { .xPages = HvPagesToMap,
+ .xOffset = 0,
+ .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
+ },
+ },
+};
extern void system_reset_iSeries(void);
extern void machine_check_iSeries(void);