at v2.6.12 250 lines 9.3 kB view raw
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 <linux/config.h> 10#include <linux/types.h> 11#include <linux/threads.h> 12#include <linux/module.h> 13#include <linux/bitops.h> 14#include <asm/processor.h> 15#include <asm/ptrace.h> 16#include <asm/naca.h> 17#include <asm/abs_addr.h> 18#include <asm/iSeries/ItLpNaca.h> 19#include <asm/lppaca.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/* The LpQueue is used to pass event data from the hypervisor to 32 * the partition. This is where I/O interrupt events are communicated. 33 */ 34 35/* May be filled in by the hypervisor so cannot end up in the BSS */ 36struct ItLpQueue xItLpQueue __attribute__((__section__(".data"))); 37 38 39/* The HvReleaseData is the root of the information shared between 40 * the hypervisor and Linux. 41 */ 42 43struct HvReleaseData hvReleaseData = { 44 .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ 45 .xSize = sizeof(struct HvReleaseData), 46 .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas), 47 .xSlicNacaAddr = &naca, /* 64-bit Naca address */ 48 .xMsNucDataOffset = 0x4800, /* offset of LparMap within loadarea (see head.S) */ 49 .xTagsMode = 1, /* tags inactive */ 50 .xAddressSize = 0, /* 64 bit */ 51 .xNoSharedProcs = 0, /* shared processors */ 52 .xNoHMT = 0, /* HMT allowed */ 53 .xRsvd2 = 6, /* TEMP: This allows non-GA driver */ 54 .xVrmIndex = 4, /* We are v5r2m0 */ 55 .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */ 56 .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */ 57 .xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */ 58 0xa7, 0x40, 0xf2, 0x4b, 59 0xf4, 0x4b, 0xf6, 0xf4 }, 60}; 61 62extern void system_reset_iSeries(void); 63extern void machine_check_iSeries(void); 64extern void data_access_iSeries(void); 65extern void instruction_access_iSeries(void); 66extern void hardware_interrupt_iSeries(void); 67extern void alignment_iSeries(void); 68extern void program_check_iSeries(void); 69extern void fp_unavailable_iSeries(void); 70extern void decrementer_iSeries(void); 71extern void trap_0a_iSeries(void); 72extern void trap_0b_iSeries(void); 73extern void system_call_iSeries(void); 74extern void single_step_iSeries(void); 75extern void trap_0e_iSeries(void); 76extern void performance_monitor_iSeries(void); 77extern void data_access_slb_iSeries(void); 78extern void instruction_access_slb_iSeries(void); 79 80struct ItLpNaca itLpNaca = { 81 .xDesc = 0xd397d581, /* "LpNa" ebcdic */ 82 .xSize = 0x0400, /* size of ItLpNaca */ 83 .xIntHdlrOffset = 0x0300, /* offset to int array */ 84 .xMaxIntHdlrEntries = 19, /* # ents */ 85 .xPrimaryLpIndex = 0, /* Part # of primary */ 86 .xServiceLpIndex = 0, /* Part # of serv */ 87 .xLpIndex = 0, /* Part # of me */ 88 .xMaxLpQueues = 0, /* # of LP queues */ 89 .xLpQueueOffset = 0x100, /* offset of start of LP queues */ 90 .xPirEnvironMode = 0, /* Piranha stuff */ 91 .xPirConsoleMode = 0, 92 .xPirDasdMode = 0, 93 .xLparInstalled = 0, 94 .xSysPartitioned = 0, 95 .xHwSyncedTBs = 0, 96 .xIntProcUtilHmt = 0, 97 .xSpVpdFormat = 0, 98 .xIntProcRatio = 0, 99 .xPlicVrmIndex = 0, /* VRM index of PLIC */ 100 .xMinSupportedSlicVrmInd = 0, /* min supported SLIC */ 101 .xMinCompatableSlicVrmInd = 0, /* min compat SLIC */ 102 .xLoadAreaAddr = 0, /* 64-bit addr of load area */ 103 .xLoadAreaChunks = 0, /* chunks for load area */ 104 .xPaseSysCallCRMask = 0, /* PASE mask */ 105 .xSlicSegmentTablePtr = 0, /* seg table */ 106 .xOldLpQueue = { 0 }, /* Old LP Queue */ 107 .xInterruptHdlr = { 108 (u64)system_reset_iSeries, /* 0x100 System Reset */ 109 (u64)machine_check_iSeries, /* 0x200 Machine Check */ 110 (u64)data_access_iSeries, /* 0x300 Data Access */ 111 (u64)instruction_access_iSeries, /* 0x400 Instruction Access */ 112 (u64)hardware_interrupt_iSeries, /* 0x500 External */ 113 (u64)alignment_iSeries, /* 0x600 Alignment */ 114 (u64)program_check_iSeries, /* 0x700 Program Check */ 115 (u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */ 116 (u64)decrementer_iSeries, /* 0x900 Decrementer */ 117 (u64)trap_0a_iSeries, /* 0xa00 Trap 0A */ 118 (u64)trap_0b_iSeries, /* 0xb00 Trap 0B */ 119 (u64)system_call_iSeries, /* 0xc00 System Call */ 120 (u64)single_step_iSeries, /* 0xd00 Single Step */ 121 (u64)trap_0e_iSeries, /* 0xe00 Trap 0E */ 122 (u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */ 123 0, /* int 0x1000 */ 124 0, /* int 0x1010 */ 125 0, /* int 0x1020 CPU ctls */ 126 (u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */ 127 (u64)data_access_slb_iSeries, /* 0x380 D-SLB */ 128 (u64)instruction_access_slb_iSeries /* 0x480 I-SLB */ 129 } 130}; 131EXPORT_SYMBOL(itLpNaca); 132 133/* May be filled in by the hypervisor so cannot end up in the BSS */ 134struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data"))); 135 136/* May be filled in by the hypervisor so cannot end up in the BSS */ 137struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data"))); 138EXPORT_SYMBOL(xItExtVpdPanel); 139 140#define maxPhysicalProcessors 32 141 142struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = { 143 { 144 .xInstCacheOperandSize = 32, 145 .xDataCacheOperandSize = 32, 146 .xProcFreq = 50000000, 147 .xTimeBaseFreq = 50000000, 148 .xPVR = 0x3600 149 } 150}; 151 152/* Space for Main Store Vpd 27,200 bytes */ 153/* May be filled in by the hypervisor so cannot end up in the BSS */ 154u64 xMsVpd[3400] __attribute__((__section__(".data"))); 155 156/* Space for Recovery Log Buffer */ 157/* May be filled in by the hypervisor so cannot end up in the BSS */ 158u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data"))); 159 160struct SpCommArea xSpCommArea = { 161 .xDesc = 0xE2D7C3C2, 162 .xFormat = 1, 163}; 164 165/* The LparMap data is now located at offset 0x6000 in head.S 166 * It was put there so that the HvReleaseData could address it 167 * with a 32-bit offset as required by the iSeries hypervisor 168 * 169 * The Naca has a pointer to the ItVpdAreas. The hypervisor finds 170 * the Naca via the HvReleaseData area. The HvReleaseData has the 171 * offset into the Naca of the pointer to the ItVpdAreas. 172 */ 173struct ItVpdAreas itVpdAreas = { 174 .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */ 175 .xSlicSize = sizeof(struct ItVpdAreas), 176 .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */ 177 .xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */ 178 .xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */ 179 .xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */ 180 .xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks), 181 .xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs), 182 .xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens), 183 .xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens), 184 .xSlicMaxSlotLabels = 0, /* max slot labels */ 185 .xSlicMaxLpQueues = 1, /* max LP queues */ 186 .xPlicDmaLens = { 0 }, /* DMA lengths */ 187 .xPlicDmaToks = { 0 }, /* DMA tokens */ 188 .xSlicVpdLens = { /* 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 .xSlicVpdAdrs = { /* 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 226struct msChunks msChunks; 227EXPORT_SYMBOL(msChunks); 228 229/* Depending on whether this is called from iSeries or pSeries setup 230 * code, the location of the msChunks struct may or may not have 231 * to be reloc'd, so we force the caller to do that for us by passing 232 * in a pointer to the structure. 233 */ 234unsigned long 235msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size) 236{ 237 unsigned long offset = reloc_offset(); 238 struct msChunks *_msChunks = PTRRELOC(&msChunks); 239 240 _msChunks->num_chunks = num_chunks; 241 _msChunks->chunk_size = chunk_size; 242 _msChunks->chunk_shift = __ilog2(chunk_size); 243 _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1; 244 245 mem = _ALIGN(mem, sizeof(msChunks_entry)); 246 _msChunks->abs = (msChunks_entry *)(mem + offset); 247 mem += num_chunks * sizeof(msChunks_entry); 248 249 return mem; 250}