diff options
Diffstat (limited to 'arch/ppc64/kernel/LparData.c')
-rw-r--r-- | arch/ppc64/kernel/LparData.c | 99 |
1 files changed, 84 insertions, 15 deletions
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c index badc5a44361..76cfd1449d5 100644 --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -28,29 +28,41 @@ #include <asm/iSeries/IoHriProcessorVpd.h> #include <asm/iSeries/ItSpCommArea.h> -/* The LpQueue is used to pass event data from the hypervisor to - * the partition. This is where I/O interrupt events are communicated. - */ - -/* May be filled in by the hypervisor so cannot end up in the BSS */ -struct ItLpQueue xItLpQueue __attribute__((__section__(".data"))); - /* The HvReleaseData is the root of the information shared between * 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 */ @@ -58,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); @@ -200,7 +269,7 @@ struct ItVpdAreas itVpdAreas = { 0,0,0, /* 13 - 15 */ sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */ 0,0,0,0,0,0, /* 17 - 22 */ - sizeof(struct ItLpQueue),/* 23 length of Lp Queue */ + sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */ 0,0 /* 24 - 25 */ }, .xSlicVpdAdrs = { /* VPD addresses */ @@ -218,7 +287,7 @@ struct ItVpdAreas itVpdAreas = { 0,0,0, /* 13 - 15 */ &xIoHriProcessorVpd, /* 16 Proc Vpd */ 0,0,0,0,0,0, /* 17 - 22 */ - &xItLpQueue, /* 23 Lp Queue */ + &hvlpevent_queue, /* 23 Lp Queue */ 0,0 } }; |