diff options
-rw-r--r-- | arch/ppc64/kernel/LparData.c | 88 | ||||
-rw-r--r-- | arch/ppc64/kernel/head.S | 33 | ||||
-rw-r--r-- | include/asm-ppc64/iSeries/HvReleaseData.h | 11 | ||||
-rw-r--r-- | include/asm-ppc64/iSeries/LparMap.h | 23 | ||||
-rw-r--r-- | include/asm-ppc64/mmu.h | 3 |
5 files changed, 109 insertions, 49 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 @@ | |||
33 | * the hypervisor and Linux. | 33 | * the hypervisor and Linux. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | /* | ||
37 | * WARNING - magic here | ||
38 | * | ||
39 | * Ok, this is a horrid hack below, but marginally better than the | ||
40 | * alternatives. What we really want is just to initialize | ||
41 | * hvReleaseData in C as in the #if 0 section here. However, gcc | ||
42 | * refuses to believe that (u32)&x is a constant expression, so will | ||
43 | * not allow the xMsNucDataOffset field to be properly initialized. | ||
44 | * So, we declare hvReleaseData in inline asm instead. We use inline | ||
45 | * asm, rather than a .S file, because the assembler won't generate | ||
46 | * the necessary relocation for the LparMap either, unless that symbol | ||
47 | * is declared in the same source file. Finally, we put the asm in a | ||
48 | * dummy, attribute-used function, instead of at file scope, because | ||
49 | * file scope asms don't allow contraints. We want to use the "i" | ||
50 | * constraints to put sizeof() and offsetof() expressions in there, | ||
51 | * because including asm/offsets.h in C code then stringifying causes | ||
52 | * all manner of warnings. | ||
53 | */ | ||
54 | #if 0 | ||
36 | struct HvReleaseData hvReleaseData = { | 55 | struct HvReleaseData hvReleaseData = { |
37 | .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ | 56 | .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ |
38 | .xSize = sizeof(struct HvReleaseData), | 57 | .xSize = sizeof(struct HvReleaseData), |
39 | .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas), | 58 | .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas), |
40 | .xSlicNacaAddr = &naca, /* 64-bit Naca address */ | 59 | .xSlicNacaAddr = &naca, /* 64-bit Naca address */ |
41 | .xMsNucDataOffset = 0x4800, /* offset of LparMap within loadarea (see head.S) */ | 60 | .xMsNucDataOffset = (u32)((unsigned long)&xLparMap - KERNELBASE), |
42 | .xTagsMode = 1, /* tags inactive */ | 61 | .xFlags = HVREL_TAGSINACTIVE /* tags inactive */ |
43 | .xAddressSize = 0, /* 64 bit */ | 62 | /* 64 bit */ |
44 | .xNoSharedProcs = 0, /* shared processors */ | 63 | /* shared processors */ |
45 | .xNoHMT = 0, /* HMT allowed */ | 64 | /* HMT allowed */ |
46 | .xRsvd2 = 6, /* TEMP: This allows non-GA driver */ | 65 | | 6, /* TEMP: This allows non-GA driver */ |
47 | .xVrmIndex = 4, /* We are v5r2m0 */ | 66 | .xVrmIndex = 4, /* We are v5r2m0 */ |
48 | .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */ | 67 | .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */ |
49 | .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */ | 68 | .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */ |
@@ -51,6 +70,63 @@ struct HvReleaseData hvReleaseData = { | |||
51 | 0xa7, 0x40, 0xf2, 0x4b, | 70 | 0xa7, 0x40, 0xf2, 0x4b, |
52 | 0xf4, 0x4b, 0xf6, 0xf4 }, | 71 | 0xf4, 0x4b, 0xf6, 0xf4 }, |
53 | }; | 72 | }; |
73 | #endif | ||
74 | |||
75 | |||
76 | extern struct HvReleaseData hvReleaseData; | ||
77 | |||
78 | static void __attribute_used__ hvReleaseData_wrapper(void) | ||
79 | { | ||
80 | /* This doesn't appear to need any alignment (even 4 byte) */ | ||
81 | asm volatile ( | ||
82 | " lparMapPhys = xLparMap - %3\n" | ||
83 | " .data\n" | ||
84 | " .globl hvReleaseData\n" | ||
85 | "hvReleaseData:\n" | ||
86 | " .long 0xc8a5d9c4\n" /* xDesc */ | ||
87 | /* "HvRD" in ebcdic */ | ||
88 | " .short %0\n" /* xSize */ | ||
89 | " .short %1\n" /* xVpdAreasPtrOffset */ | ||
90 | " .llong naca\n" /* xSlicNacaAddr */ | ||
91 | " .long lparMapPhys\n" /* xMsNucDataOffset */ | ||
92 | " .long 0\n" /* xRsvd1 */ | ||
93 | " .short %2\n" /* xFlags */ | ||
94 | " .short 4\n" /* xVrmIndex - v5r2m0 */ | ||
95 | " .short 3\n" /* xMinSupportedPlicVrmIndex - v5r1m0 */ | ||
96 | " .short 3\n" /* xMinCompatablePlicVrmIndex - v5r1m0 */ | ||
97 | " .long 0xd38995a4\n" /* xVrmName */ | ||
98 | " .long 0xa740f24b\n" /* "Linux 2.4.64" ebcdic */ | ||
99 | " .long 0xf44bf6f4\n" | ||
100 | " . = hvReleaseData + %0\n" | ||
101 | " .previous\n" | ||
102 | : : "i"(sizeof(hvReleaseData)), | ||
103 | "i"(offsetof(struct naca_struct, xItVpdAreas)), | ||
104 | "i"(HVREL_TAGSINACTIVE /* tags inactive, 64 bit, */ | ||
105 | /* shared processors, HMT allowed */ | ||
106 | | 6), /* TEMP: This allows non-GA drivers */ | ||
107 | "i"(KERNELBASE) | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | struct LparMap __attribute__((aligned (16))) xLparMap = { | ||
112 | .xNumberEsids = HvEsidsToMap, | ||
113 | .xNumberRanges = HvRangesToMap, | ||
114 | .xSegmentTableOffs = STAB0_PAGE, | ||
115 | |||
116 | .xEsids = { | ||
117 | { .xKernelEsid = GET_ESID(KERNELBASE), | ||
118 | .xKernelVsid = KERNEL_VSID(KERNELBASE), }, | ||
119 | { .xKernelEsid = GET_ESID(VMALLOCBASE), | ||
120 | .xKernelVsid = KERNEL_VSID(VMALLOCBASE), }, | ||
121 | }, | ||
122 | |||
123 | .xRanges = { | ||
124 | { .xPages = HvPagesToMap, | ||
125 | .xOffset = 0, | ||
126 | .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT), | ||
127 | }, | ||
128 | }, | ||
129 | }; | ||
54 | 130 | ||
55 | extern void system_reset_iSeries(void); | 131 | extern void system_reset_iSeries(void); |
56 | extern void machine_check_iSeries(void); | 132 | extern void machine_check_iSeries(void); |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 3f447712e3ff..74fc3bc68604 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -522,36 +522,9 @@ __end_interrupts: | |||
522 | #ifdef CONFIG_PPC_ISERIES | 522 | #ifdef CONFIG_PPC_ISERIES |
523 | .globl naca | 523 | .globl naca |
524 | naca: | 524 | naca: |
525 | .llong itVpdAreas | 525 | .llong itVpdAreas |
526 | 526 | .llong 0 /* xRamDisk */ | |
527 | /* | 527 | .llong 0 /* xRamDiskSize */ |
528 | * The iSeries LPAR map is at this fixed address | ||
529 | * so that the HvReleaseData structure can address | ||
530 | * it with a 32-bit offset. | ||
531 | * | ||
532 | * The VSID values below are dependent on the | ||
533 | * VSID generation algorithm. See include/asm/mmu_context.h. | ||
534 | */ | ||
535 | |||
536 | . = 0x4800 | ||
537 | |||
538 | .llong 2 /* # ESIDs to be mapped by hypervisor */ | ||
539 | .llong 1 /* # memory ranges to be mapped by hypervisor */ | ||
540 | .llong STAB0_PAGE /* Page # of segment table within load area */ | ||
541 | .llong 0 /* Reserved */ | ||
542 | .llong 0 /* Reserved */ | ||
543 | .llong 0 /* Reserved */ | ||
544 | .llong 0 /* Reserved */ | ||
545 | .llong 0 /* Reserved */ | ||
546 | .llong (KERNELBASE>>SID_SHIFT) | ||
547 | .llong 0x408f92c94 /* KERNELBASE VSID */ | ||
548 | /* We have to list the bolted VMALLOC segment here, too, so that it | ||
549 | * will be restored on shared processor switch */ | ||
550 | .llong (VMALLOCBASE>>SID_SHIFT) | ||
551 | .llong 0xf09b89af5 /* VMALLOCBASE VSID */ | ||
552 | .llong 8192 /* # pages to map (32 MB) */ | ||
553 | .llong 0 /* Offset from start of loadarea to start of map */ | ||
554 | .llong 0x408f92c940000 /* VPN of first page to map */ | ||
555 | 528 | ||
556 | . = 0x6100 | 529 | . = 0x6100 |
557 | 530 | ||
diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h index 01a1f13ea4a0..c8162e5ccb21 100644 --- a/include/asm-ppc64/iSeries/HvReleaseData.h +++ b/include/asm-ppc64/iSeries/HvReleaseData.h | |||
@@ -39,6 +39,11 @@ | |||
39 | * know that this PLIC does not support running an OS "that old". | 39 | * know that this PLIC does not support running an OS "that old". |
40 | */ | 40 | */ |
41 | 41 | ||
42 | #define HVREL_TAGSINACTIVE 0x8000 | ||
43 | #define HVREL_32BIT 0x4000 | ||
44 | #define HVREL_NOSHAREDPROCS 0x2000 | ||
45 | #define HVREL_NOHMT 0x1000 | ||
46 | |||
42 | struct HvReleaseData { | 47 | struct HvReleaseData { |
43 | u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */ | 48 | u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */ |
44 | u16 xSize; /* Size of this control block x04-x05 */ | 49 | u16 xSize; /* Size of this control block x04-x05 */ |
@@ -46,11 +51,7 @@ struct HvReleaseData { | |||
46 | struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */ | 51 | struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */ |
47 | u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */ | 52 | u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */ |
48 | u32 xRsvd1; /* Reserved x14-x17 */ | 53 | u32 xRsvd1; /* Reserved x14-x17 */ |
49 | u16 xTagsMode:1; /* 0 == tags active, 1 == tags inactive */ | 54 | u16 xFlags; |
50 | u16 xAddressSize:1; /* 0 == 64-bit, 1 == 32-bit */ | ||
51 | u16 xNoSharedProcs:1; /* 0 == shared procs, 1 == no shared */ | ||
52 | u16 xNoHMT:1; /* 0 == allow HMT, 1 == no HMT */ | ||
53 | u16 xRsvd2:12; /* Reserved x18-x19 */ | ||
54 | u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */ | 55 | u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */ |
55 | u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */ | 56 | u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */ |
56 | u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */ | 57 | u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */ |
diff --git a/include/asm-ppc64/iSeries/LparMap.h b/include/asm-ppc64/iSeries/LparMap.h index 038e5df7e9f8..5c32e38c1c01 100644 --- a/include/asm-ppc64/iSeries/LparMap.h +++ b/include/asm-ppc64/iSeries/LparMap.h | |||
@@ -49,19 +49,26 @@ | |||
49 | * entry to map the Esid to the Vsid. | 49 | * entry to map the Esid to the Vsid. |
50 | */ | 50 | */ |
51 | 51 | ||
52 | #define HvEsidsToMap 2 | ||
53 | #define HvRangesToMap 1 | ||
54 | |||
52 | /* Hypervisor initially maps 32MB of the load area */ | 55 | /* Hypervisor initially maps 32MB of the load area */ |
53 | #define HvPagesToMap 8192 | 56 | #define HvPagesToMap 8192 |
54 | 57 | ||
55 | struct LparMap { | 58 | struct LparMap { |
56 | u64 xNumberEsids; // Number of ESID/VSID pairs (1) | 59 | u64 xNumberEsids; // Number of ESID/VSID pairs |
57 | u64 xNumberRanges; // Number of VA ranges to map (1) | 60 | u64 xNumberRanges; // Number of VA ranges to map |
58 | u64 xSegmentTableOffs; // Page number within load area of seg table (0) | 61 | u64 xSegmentTableOffs; // Page number within load area of seg table |
59 | u64 xRsvd[5]; | 62 | u64 xRsvd[5]; |
60 | u64 xKernelEsid; // Esid used to map kernel load (0x0C00000000) | 63 | struct { |
61 | u64 xKernelVsid; // Vsid used to map kernel load (0x0C00000000) | 64 | u64 xKernelEsid; // Esid used to map kernel load |
62 | u64 xPages; // Number of pages to be mapped (8192) | 65 | u64 xKernelVsid; // Vsid used to map kernel load |
63 | u64 xOffset; // Offset from start of load area (0) | 66 | } xEsids[HvEsidsToMap]; |
64 | u64 xVPN; // Virtual Page Number (0x000C000000000000) | 67 | struct { |
68 | u64 xPages; // Number of pages to be mapped | ||
69 | u64 xOffset; // Offset from start of load area | ||
70 | u64 xVPN; // Virtual Page Number | ||
71 | } xRanges[HvRangesToMap]; | ||
65 | }; | 72 | }; |
66 | 73 | ||
67 | extern struct LparMap xLparMap; | 74 | extern struct LparMap xLparMap; |
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index 889118036803..70348a851313 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h | |||
@@ -338,6 +338,9 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea) | |||
338 | | (ea >> SID_SHIFT)); | 338 | | (ea >> SID_SHIFT)); |
339 | } | 339 | } |
340 | 340 | ||
341 | #define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS) | ||
342 | #define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea)) | ||
343 | |||
341 | #endif /* __ASSEMBLY */ | 344 | #endif /* __ASSEMBLY */ |
342 | 345 | ||
343 | #endif /* _PPC64_MMU_H_ */ | 346 | #endif /* _PPC64_MMU_H_ */ |