You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
powerpc: Remove the main legacy iSerie platform code
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
committed by
Benjamin Herrenschmidt
parent
2d4b971287
commit
8ee3e0d696
@@ -16,7 +16,6 @@ obj-$(CONFIG_FSL_SOC_BOOKE) += 85xx/
|
||||
obj-$(CONFIG_PPC_86xx) += 86xx/
|
||||
obj-$(CONFIG_PPC_POWERNV) += powernv/
|
||||
obj-$(CONFIG_PPC_PSERIES) += pseries/
|
||||
obj-$(CONFIG_PPC_ISERIES) += iseries/
|
||||
obj-$(CONFIG_PPC_MAPLE) += maple/
|
||||
obj-$(CONFIG_PPC_PASEMI) += pasemi/
|
||||
obj-$(CONFIG_PPC_CELL) += cell/
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
ccflags-y := -mno-minimal-toc
|
||||
|
||||
obj-y += exception.o
|
||||
obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
|
||||
hvcall.o proc.o htab.o iommu.o misc.o irq.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_VIOPATH) += viopath.o vio.o
|
||||
obj-$(CONFIG_MODULES) += ksyms.o
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Mike Corrigan IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _PLATFORMS_ISERIES_CALL_HPT_H
|
||||
#define _PLATFORMS_ISERIES_CALL_HPT_H
|
||||
|
||||
/*
|
||||
* This file contains the "hypervisor call" interface which is used to
|
||||
* drive the hypervisor from the OS.
|
||||
*/
|
||||
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#define HvCallHptGetHptAddress HvCallHpt + 0
|
||||
#define HvCallHptGetHptPages HvCallHpt + 1
|
||||
#define HvCallHptSetPp HvCallHpt + 5
|
||||
#define HvCallHptSetSwBits HvCallHpt + 6
|
||||
#define HvCallHptUpdate HvCallHpt + 7
|
||||
#define HvCallHptInvalidateNoSyncICache HvCallHpt + 8
|
||||
#define HvCallHptGet HvCallHpt + 11
|
||||
#define HvCallHptFindNextValid HvCallHpt + 12
|
||||
#define HvCallHptFindValid HvCallHpt + 13
|
||||
#define HvCallHptAddValidate HvCallHpt + 16
|
||||
#define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
|
||||
|
||||
|
||||
static inline u64 HvCallHpt_getHptAddress(void)
|
||||
{
|
||||
return HvCall0(HvCallHptGetHptAddress);
|
||||
}
|
||||
|
||||
static inline u64 HvCallHpt_getHptPages(void)
|
||||
{
|
||||
return HvCall0(HvCallHptGetHptPages);
|
||||
}
|
||||
|
||||
static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
|
||||
{
|
||||
HvCall2(HvCallHptSetPp, hpteIndex, value);
|
||||
}
|
||||
|
||||
static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
|
||||
{
|
||||
HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
|
||||
}
|
||||
|
||||
static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
|
||||
{
|
||||
HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
|
||||
}
|
||||
|
||||
static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
|
||||
u8 bitsoff)
|
||||
{
|
||||
u64 compressedStatus;
|
||||
|
||||
compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
|
||||
hpteIndex, bitson, bitsoff, 1);
|
||||
HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
|
||||
return compressedStatus;
|
||||
}
|
||||
|
||||
static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
|
||||
{
|
||||
return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
|
||||
}
|
||||
|
||||
static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
|
||||
u8 bitson, u8 bitsoff)
|
||||
{
|
||||
return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
|
||||
bitson, bitsoff);
|
||||
}
|
||||
|
||||
static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
|
||||
{
|
||||
HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
|
||||
}
|
||||
|
||||
static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
|
||||
struct hash_pte *hpte)
|
||||
{
|
||||
HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
|
||||
}
|
||||
|
||||
#endif /* _PLATFORMS_ISERIES_CALL_HPT_H */
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Provides the Hypervisor PCI calls for iSeries Linux Parition.
|
||||
* Copyright (C) 2001 <Wayne G Holm> <IBM Corporation>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Change Activity:
|
||||
* Created, Jan 9, 2001
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORMS_ISERIES_CALL_PCI_H
|
||||
#define _PLATFORMS_ISERIES_CALL_PCI_H
|
||||
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
|
||||
/*
|
||||
* DSA == Direct Select Address
|
||||
* this struct must be 64 bits in total
|
||||
*/
|
||||
struct HvCallPci_DsaAddr {
|
||||
u16 busNumber; /* PHB index? */
|
||||
u8 subBusNumber; /* PCI bus number? */
|
||||
u8 deviceId; /* device and function? */
|
||||
u8 barNumber;
|
||||
u8 reserved[3];
|
||||
};
|
||||
|
||||
union HvDsaMap {
|
||||
u64 DsaAddr;
|
||||
struct HvCallPci_DsaAddr Dsa;
|
||||
};
|
||||
|
||||
struct HvCallPci_LoadReturn {
|
||||
u64 rc;
|
||||
u64 value;
|
||||
};
|
||||
|
||||
enum HvCallPci_DeviceType {
|
||||
HvCallPci_NodeDevice = 1,
|
||||
HvCallPci_SpDevice = 2,
|
||||
HvCallPci_IopDevice = 3,
|
||||
HvCallPci_BridgeDevice = 4,
|
||||
HvCallPci_MultiFunctionDevice = 5,
|
||||
HvCallPci_IoaDevice = 6
|
||||
};
|
||||
|
||||
|
||||
struct HvCallPci_DeviceInfo {
|
||||
u32 deviceType; /* See DeviceType enum for values */
|
||||
};
|
||||
|
||||
struct HvCallPci_BusUnitInfo {
|
||||
u32 sizeReturned; /* length of data returned */
|
||||
u32 deviceType; /* see DeviceType enum for values */
|
||||
};
|
||||
|
||||
struct HvCallPci_BridgeInfo {
|
||||
struct HvCallPci_BusUnitInfo busUnitInfo; /* Generic bus unit info */
|
||||
u8 subBusNumber; /* Bus number of secondary bus */
|
||||
u8 maxAgents; /* Max idsels on secondary bus */
|
||||
u8 maxSubBusNumber; /* Max Sub Bus */
|
||||
u8 logicalSlotNumber; /* Logical Slot Number for IOA */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Maximum BusUnitInfo buffer size. Provided for clients so
|
||||
* they can allocate a buffer big enough for any type of bus
|
||||
* unit. Increase as needed.
|
||||
*/
|
||||
enum {HvCallPci_MaxBusUnitInfoSize = 128};
|
||||
|
||||
struct HvCallPci_BarParms {
|
||||
u64 vaddr;
|
||||
u64 raddr;
|
||||
u64 size;
|
||||
u64 protectStart;
|
||||
u64 protectEnd;
|
||||
u64 relocationOffset;
|
||||
u64 pciAddress;
|
||||
u64 reserved[3];
|
||||
};
|
||||
|
||||
enum HvCallPci_VpdType {
|
||||
HvCallPci_BusVpd = 1,
|
||||
HvCallPci_BusAdapterVpd = 2
|
||||
};
|
||||
|
||||
#define HvCallPciConfigLoad8 HvCallPci + 0
|
||||
#define HvCallPciConfigLoad16 HvCallPci + 1
|
||||
#define HvCallPciConfigLoad32 HvCallPci + 2
|
||||
#define HvCallPciConfigStore8 HvCallPci + 3
|
||||
#define HvCallPciConfigStore16 HvCallPci + 4
|
||||
#define HvCallPciConfigStore32 HvCallPci + 5
|
||||
#define HvCallPciEoi HvCallPci + 16
|
||||
#define HvCallPciGetBarParms HvCallPci + 18
|
||||
#define HvCallPciMaskFisr HvCallPci + 20
|
||||
#define HvCallPciUnmaskFisr HvCallPci + 21
|
||||
#define HvCallPciSetSlotReset HvCallPci + 25
|
||||
#define HvCallPciGetDeviceInfo HvCallPci + 27
|
||||
#define HvCallPciGetCardVpd HvCallPci + 28
|
||||
#define HvCallPciBarLoad8 HvCallPci + 40
|
||||
#define HvCallPciBarLoad16 HvCallPci + 41
|
||||
#define HvCallPciBarLoad32 HvCallPci + 42
|
||||
#define HvCallPciBarLoad64 HvCallPci + 43
|
||||
#define HvCallPciBarStore8 HvCallPci + 44
|
||||
#define HvCallPciBarStore16 HvCallPci + 45
|
||||
#define HvCallPciBarStore32 HvCallPci + 46
|
||||
#define HvCallPciBarStore64 HvCallPci + 47
|
||||
#define HvCallPciMaskInterrupts HvCallPci + 48
|
||||
#define HvCallPciUnmaskInterrupts HvCallPci + 49
|
||||
#define HvCallPciGetBusUnitInfo HvCallPci + 50
|
||||
|
||||
static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
|
||||
u8 deviceId, u32 offset, u16 *value)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
struct HvCallPci_LoadReturn retVal;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumber;
|
||||
dsa.subBusNumber = subBusNumber;
|
||||
dsa.deviceId = deviceId;
|
||||
|
||||
HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
|
||||
|
||||
*value = retVal.value;
|
||||
|
||||
return retVal.rc;
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
|
||||
u8 deviceId, u32 offset, u32 *value)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
struct HvCallPci_LoadReturn retVal;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumber;
|
||||
dsa.subBusNumber = subBusNumber;
|
||||
dsa.deviceId = deviceId;
|
||||
|
||||
HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
|
||||
|
||||
*value = retVal.value;
|
||||
|
||||
return retVal.rc;
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
|
||||
u8 deviceId, u32 offset, u8 value)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumber;
|
||||
dsa.subBusNumber = subBusNumber;
|
||||
dsa.deviceId = deviceId;
|
||||
|
||||
return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
struct HvCallPci_LoadReturn retVal;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
|
||||
HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
|
||||
|
||||
return retVal.rc;
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
dsa.barNumber = barNumberParm;
|
||||
|
||||
return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm, u64 fisrMask)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
|
||||
return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm, u64 fisrMask)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
|
||||
return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceNumberParm, u64 parms, u32 sizeofParms)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceNumberParm << 4;
|
||||
|
||||
return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm, u64 interruptMask)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
|
||||
return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm, u64 interruptMask)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
|
||||
return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
|
||||
}
|
||||
|
||||
static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
|
||||
u8 deviceIdParm, u64 parms, u32 sizeofParms)
|
||||
{
|
||||
struct HvCallPci_DsaAddr dsa;
|
||||
|
||||
*((u64*)&dsa) = 0;
|
||||
|
||||
dsa.busNumber = busNumberParm;
|
||||
dsa.subBusNumber = subBusParm;
|
||||
dsa.deviceId = deviceIdParm;
|
||||
|
||||
return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
|
||||
sizeofParms);
|
||||
}
|
||||
|
||||
static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
|
||||
u16 sizeParm)
|
||||
{
|
||||
u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
|
||||
sizeParm, HvCallPci_BusVpd);
|
||||
if (xRc == -1)
|
||||
return -1;
|
||||
else
|
||||
return xRc & 0xFFFF;
|
||||
}
|
||||
|
||||
#endif /* _PLATFORMS_ISERIES_CALL_PCI_H */
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Mike Corrigan IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _ISERIES_CALL_SM_H
|
||||
#define _ISERIES_CALL_SM_H
|
||||
|
||||
/*
|
||||
* This file contains the "hypervisor call" interface which is used to
|
||||
* drive the hypervisor from the OS.
|
||||
*/
|
||||
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
|
||||
#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
|
||||
|
||||
static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
|
||||
u64 indexIntoBitMap)
|
||||
{
|
||||
return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
|
||||
}
|
||||
|
||||
#endif /* _ISERIES_CALL_SM_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
* Low level routines for legacy iSeries support.
|
||||
*
|
||||
* Extracted from head_64.S
|
||||
*
|
||||
* PowerPC version
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
*
|
||||
* Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
|
||||
* Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
|
||||
* Adapted for Power Macintosh by Paul Mackerras.
|
||||
* Low-level exception handlers and MMU support
|
||||
* rewritten by Paul Mackerras.
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*
|
||||
* Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
|
||||
* Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
|
||||
*
|
||||
* This file contains the low-level support and setup for the
|
||||
* PowerPC-64 platform, including trap and interrupt dispatch.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <asm/reg.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#include "exception.h"
|
||||
|
||||
.text
|
||||
|
||||
.globl system_reset_iSeries
|
||||
system_reset_iSeries:
|
||||
bl .relative_toc
|
||||
mfspr r13,SPRN_SPRG3 /* Get alpaca address */
|
||||
LOAD_REG_ADDR(r23, alpaca)
|
||||
li r0,ALPACA_SIZE
|
||||
sub r23,r13,r23
|
||||
divdu r24,r23,r0 /* r24 has cpu number */
|
||||
cmpwi 0,r24,0 /* Are we processor 0? */
|
||||
bne 1f
|
||||
LOAD_REG_ADDR(r13, boot_paca)
|
||||
mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
|
||||
mfmsr r23
|
||||
ori r23,r23,MSR_RI
|
||||
mtmsrd r23 /* RI on */
|
||||
b .__start_initialization_iSeries /* Start up the first processor */
|
||||
1: mfspr r4,SPRN_CTRLF
|
||||
li r5,CTRL_RUNLATCH /* Turn off the run light */
|
||||
andc r4,r4,r5
|
||||
mtspr SPRN_CTRLT,r4
|
||||
|
||||
/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
|
||||
/* In the UP case we'll yield() later, and we will not access the paca anyway */
|
||||
#ifdef CONFIG_SMP
|
||||
iSeries_secondary_wait_paca:
|
||||
HMT_LOW
|
||||
LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
|
||||
ld r23,0(r23)
|
||||
|
||||
cmpdi 0,r23,0
|
||||
bne 2f /* go on when the master is ready */
|
||||
|
||||
/* Keep poking the Hypervisor until we're released */
|
||||
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
|
||||
lis r3,0x8002
|
||||
rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
|
||||
li r0,-1 /* r0=-1 indicates a Hypervisor call */
|
||||
sc /* Invoke the hypervisor via a system call */
|
||||
b iSeries_secondary_wait_paca
|
||||
|
||||
2:
|
||||
HMT_MEDIUM
|
||||
sync
|
||||
|
||||
LOAD_REG_ADDR(r3, nr_cpu_ids) /* get number of pacas allocated */
|
||||
lwz r3,0(r3) /* nr_cpus= or NR_CPUS can limit */
|
||||
cmpld 0,r24,r3 /* is our cpu number allocated? */
|
||||
bge iSeries_secondary_yield /* no, yield forever */
|
||||
|
||||
/* Load our paca now that it's been allocated */
|
||||
LOAD_REG_ADDR(r13, paca)
|
||||
ld r13,0(r13)
|
||||
mulli r0,r24,PACA_SIZE
|
||||
add r13,r13,r0
|
||||
mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
|
||||
mfmsr r23
|
||||
ori r23,r23,MSR_RI
|
||||
mtmsrd r23 /* RI on */
|
||||
|
||||
iSeries_secondary_smp_loop:
|
||||
lbz r23,PACAPROCSTART(r13) /* Test if this processor
|
||||
* should start */
|
||||
cmpwi 0,r23,0
|
||||
bne 3f /* go on when we are told */
|
||||
|
||||
HMT_LOW
|
||||
/* Let the Hypervisor know we are alive */
|
||||
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
|
||||
lis r3,0x8002
|
||||
rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
|
||||
li r0,-1 /* r0=-1 indicates a Hypervisor call */
|
||||
sc /* Invoke the hypervisor via a system call */
|
||||
mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
|
||||
b iSeries_secondary_smp_loop /* wait for signal to start */
|
||||
|
||||
3:
|
||||
HMT_MEDIUM
|
||||
sync
|
||||
LOAD_REG_ADDR(r3,current_set)
|
||||
sldi r28,r24,3 /* get current_set[cpu#] */
|
||||
ldx r3,r3,r28
|
||||
addi r1,r3,THREAD_SIZE
|
||||
subi r1,r1,STACK_FRAME_OVERHEAD
|
||||
|
||||
b __secondary_start /* Loop until told to go */
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
iSeries_secondary_yield:
|
||||
/* Yield the processor. This is required for non-SMP kernels
|
||||
which are running on multi-threaded machines. */
|
||||
HMT_LOW
|
||||
lis r3,0x8000
|
||||
rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
|
||||
addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */
|
||||
li r4,0 /* "yield timed" */
|
||||
li r5,-1 /* "yield forever" */
|
||||
li r0,-1 /* r0=-1 indicates a Hypervisor call */
|
||||
sc /* Invoke the hypervisor via a system call */
|
||||
mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
|
||||
b iSeries_secondary_yield /* If SMP not configured, secondaries
|
||||
* loop forever */
|
||||
|
||||
/*** ISeries-LPAR interrupt handlers ***/
|
||||
|
||||
STD_EXCEPTION_ISERIES(machine_check, PACA_EXMC)
|
||||
|
||||
.globl data_access_iSeries
|
||||
data_access_iSeries:
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13
|
||||
BEGIN_FTR_SECTION
|
||||
mfspr r13,SPRN_SPRG_PACA
|
||||
std r9,PACA_EXSLB+EX_R9(r13)
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
mfspr r10,SPRN_DAR
|
||||
mfspr r9,SPRN_DSISR
|
||||
srdi r10,r10,60
|
||||
rlwimi r10,r9,16,0x20
|
||||
mfcr r9
|
||||
cmpwi r10,0x2c
|
||||
beq .do_stab_bolted_iSeries
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXGEN+EX_R11(r13)
|
||||
ld r11,PACA_EXSLB+EX_R9(r13)
|
||||
std r12,PACA_EXGEN+EX_R12(r13)
|
||||
mfspr r12,SPRN_SPRG_SCRATCH0
|
||||
std r10,PACA_EXGEN+EX_R10(r13)
|
||||
std r11,PACA_EXGEN+EX_R9(r13)
|
||||
std r12,PACA_EXGEN+EX_R13(r13)
|
||||
EXCEPTION_PROLOG_ISERIES_1
|
||||
FTR_SECTION_ELSE
|
||||
EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0)
|
||||
EXCEPTION_PROLOG_ISERIES_1
|
||||
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
|
||||
b data_access_common
|
||||
|
||||
.do_stab_bolted_iSeries:
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
mfspr r10,SPRN_SPRG_SCRATCH0
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
EXCEPTION_PROLOG_ISERIES_1
|
||||
b .do_stab_bolted
|
||||
|
||||
.globl data_access_slb_iSeries
|
||||
data_access_slb_iSeries:
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
|
||||
mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
mfspr r3,SPRN_DAR
|
||||
std r9,PACA_EXSLB+EX_R9(r13)
|
||||
mfcr r9
|
||||
#ifdef __DISABLED__
|
||||
cmpdi r3,0
|
||||
bge slb_miss_user_iseries
|
||||
#endif
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
mfspr r10,SPRN_SPRG_SCRATCH0
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
ld r12,PACALPPACAPTR(r13)
|
||||
ld r12,LPPACASRR1(r12)
|
||||
b .slb_miss_realmode
|
||||
|
||||
STD_EXCEPTION_ISERIES(instruction_access, PACA_EXGEN)
|
||||
|
||||
.globl instruction_access_slb_iSeries
|
||||
instruction_access_slb_iSeries:
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
|
||||
mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
|
||||
std r3,PACA_EXSLB+EX_R3(r13)
|
||||
ld r3,PACALPPACAPTR(r13)
|
||||
ld r3,LPPACASRR0(r3) /* get SRR0 value */
|
||||
std r9,PACA_EXSLB+EX_R9(r13)
|
||||
mfcr r9
|
||||
#ifdef __DISABLED__
|
||||
cmpdi r3,0
|
||||
bge slb_miss_user_iseries
|
||||
#endif
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
std r11,PACA_EXSLB+EX_R11(r13)
|
||||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
mfspr r10,SPRN_SPRG_SCRATCH0
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
ld r12,PACALPPACAPTR(r13)
|
||||
ld r12,LPPACASRR1(r12)
|
||||
b .slb_miss_realmode
|
||||
|
||||
#ifdef __DISABLED__
|
||||
slb_miss_user_iseries:
|
||||
std r10,PACA_EXGEN+EX_R10(r13)
|
||||
std r11,PACA_EXGEN+EX_R11(r13)
|
||||
std r12,PACA_EXGEN+EX_R12(r13)
|
||||
mfspr r10,SPRG_SCRATCH0
|
||||
ld r11,PACA_EXSLB+EX_R9(r13)
|
||||
ld r12,PACA_EXSLB+EX_R3(r13)
|
||||
std r10,PACA_EXGEN+EX_R13(r13)
|
||||
std r11,PACA_EXGEN+EX_R9(r13)
|
||||
std r12,PACA_EXGEN+EX_R3(r13)
|
||||
EXCEPTION_PROLOG_ISERIES_1
|
||||
b slb_miss_user_common
|
||||
#endif
|
||||
|
||||
MASKABLE_EXCEPTION_ISERIES(hardware_interrupt)
|
||||
STD_EXCEPTION_ISERIES(alignment, PACA_EXGEN)
|
||||
STD_EXCEPTION_ISERIES(program_check, PACA_EXGEN)
|
||||
STD_EXCEPTION_ISERIES(fp_unavailable, PACA_EXGEN)
|
||||
MASKABLE_EXCEPTION_ISERIES(decrementer)
|
||||
STD_EXCEPTION_ISERIES(trap_0a, PACA_EXGEN)
|
||||
STD_EXCEPTION_ISERIES(trap_0b, PACA_EXGEN)
|
||||
|
||||
.globl system_call_iSeries
|
||||
system_call_iSeries:
|
||||
mr r9,r13
|
||||
mfspr r13,SPRN_SPRG_PACA
|
||||
EXCEPTION_PROLOG_ISERIES_1
|
||||
b system_call_common
|
||||
|
||||
STD_EXCEPTION_ISERIES(single_step, PACA_EXGEN)
|
||||
STD_EXCEPTION_ISERIES(trap_0e, PACA_EXGEN)
|
||||
STD_EXCEPTION_ISERIES(performance_monitor, PACA_EXGEN)
|
||||
|
||||
decrementer_iSeries_masked:
|
||||
/* We may not have a valid TOC pointer in here. */
|
||||
li r11,1
|
||||
ld r12,PACALPPACAPTR(r13)
|
||||
stb r11,LPPACADECRINT(r12)
|
||||
li r12,-1
|
||||
clrldi r12,r12,33 /* set DEC to 0x7fffffff */
|
||||
mtspr SPRN_DEC,r12
|
||||
/* fall through */
|
||||
|
||||
hardware_interrupt_iSeries_masked:
|
||||
mtcrf 0x80,r9 /* Restore regs */
|
||||
ld r12,PACALPPACAPTR(r13)
|
||||
ld r11,LPPACASRR0(r12)
|
||||
ld r12,LPPACASRR1(r12)
|
||||
mtspr SPRN_SRR0,r11
|
||||
mtspr SPRN_SRR1,r12
|
||||
ld r9,PACA_EXGEN+EX_R9(r13)
|
||||
ld r10,PACA_EXGEN+EX_R10(r13)
|
||||
ld r11,PACA_EXGEN+EX_R11(r13)
|
||||
ld r12,PACA_EXGEN+EX_R12(r13)
|
||||
ld r13,PACA_EXGEN+EX_R13(r13)
|
||||
rfid
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
_INIT_STATIC(__start_initialization_iSeries)
|
||||
/* Clear out the BSS */
|
||||
LOAD_REG_ADDR(r11,__bss_stop)
|
||||
LOAD_REG_ADDR(r8,__bss_start)
|
||||
sub r11,r11,r8 /* bss size */
|
||||
addi r11,r11,7 /* round up to an even double word */
|
||||
rldicl. r11,r11,61,3 /* shift right by 3 */
|
||||
beq 4f
|
||||
addi r8,r8,-8
|
||||
li r0,0
|
||||
mtctr r11 /* zero this many doublewords */
|
||||
3: stdu r0,8(r8)
|
||||
bdnz 3b
|
||||
4:
|
||||
LOAD_REG_ADDR(r1,init_thread_union)
|
||||
addi r1,r1,THREAD_SIZE
|
||||
li r0,0
|
||||
stdu r0,-STACK_FRAME_OVERHEAD(r1)
|
||||
|
||||
bl .iSeries_early_setup
|
||||
bl .early_setup
|
||||
|
||||
/* relocation is on at this point */
|
||||
|
||||
b .start_here_common
|
||||
@@ -1,58 +0,0 @@
|
||||
#ifndef _ASM_POWERPC_ISERIES_EXCEPTION_H
|
||||
#define _ASM_POWERPC_ISERIES_EXCEPTION_H
|
||||
/*
|
||||
* Extracted from head_64.S
|
||||
*
|
||||
* PowerPC version
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
*
|
||||
* Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
|
||||
* Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
|
||||
* Adapted for Power Macintosh by Paul Mackerras.
|
||||
* Low-level exception handlers and MMU support
|
||||
* rewritten by Paul Mackerras.
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
*
|
||||
* Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
|
||||
* Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
|
||||
*
|
||||
* This file contains the low-level support and setup for the
|
||||
* PowerPC-64 platform, including trap and interrupt dispatch.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <asm/exception-64s.h>
|
||||
|
||||
#define EXCEPTION_PROLOG_ISERIES_1 \
|
||||
mfmsr r10; \
|
||||
ld r12,PACALPPACAPTR(r13); \
|
||||
ld r11,LPPACASRR0(r12); \
|
||||
ld r12,LPPACASRR1(r12); \
|
||||
ori r10,r10,MSR_RI; \
|
||||
mtmsrd r10,1
|
||||
|
||||
#define STD_EXCEPTION_ISERIES(label, area) \
|
||||
.globl label##_iSeries; \
|
||||
label##_iSeries: \
|
||||
HMT_MEDIUM; \
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
|
||||
EXCEPTION_PROLOG_1(area, NOTEST, 0); \
|
||||
EXCEPTION_PROLOG_ISERIES_1; \
|
||||
b label##_common
|
||||
|
||||
#define MASKABLE_EXCEPTION_ISERIES(label) \
|
||||
.globl label##_iSeries; \
|
||||
label##_iSeries: \
|
||||
HMT_MEDIUM; \
|
||||
mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
|
||||
EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0); \
|
||||
lbz r10,PACASOFTIRQEN(r13); \
|
||||
cmpwi 0,r10,0; \
|
||||
beq- label##_iSeries_masked; \
|
||||
EXCEPTION_PROLOG_ISERIES_1; \
|
||||
b label##_common; \
|
||||
|
||||
#endif /* _ASM_POWERPC_ISERIES_EXCEPTION_H */
|
||||
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
* iSeries hashtable management.
|
||||
* Derived from pSeries_htab.c
|
||||
*
|
||||
* SMP scalability work:
|
||||
* Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "call_hpt.h"
|
||||
|
||||
static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp;
|
||||
|
||||
/*
|
||||
* Very primitive algorithm for picking up a lock
|
||||
*/
|
||||
static inline void iSeries_hlock(unsigned long slot)
|
||||
{
|
||||
if (slot & 0x8)
|
||||
slot = ~slot;
|
||||
spin_lock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
|
||||
}
|
||||
|
||||
static inline void iSeries_hunlock(unsigned long slot)
|
||||
{
|
||||
if (slot & 0x8)
|
||||
slot = ~slot;
|
||||
spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
|
||||
}
|
||||
|
||||
static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
||||
unsigned long pa, unsigned long rflags,
|
||||
unsigned long vflags, int psize, int ssize)
|
||||
{
|
||||
long slot;
|
||||
struct hash_pte lhpte;
|
||||
int secondary = 0;
|
||||
|
||||
BUG_ON(psize != MMU_PAGE_4K);
|
||||
|
||||
/*
|
||||
* The hypervisor tries both primary and secondary.
|
||||
* If we are being called to insert in the secondary,
|
||||
* it means we have already tried both primary and secondary,
|
||||
* so we return failure immediately.
|
||||
*/
|
||||
if (vflags & HPTE_V_SECONDARY)
|
||||
return -1;
|
||||
|
||||
iSeries_hlock(hpte_group);
|
||||
|
||||
slot = HvCallHpt_findValid(&lhpte, va >> HW_PAGE_SHIFT);
|
||||
if (unlikely(lhpte.v & HPTE_V_VALID)) {
|
||||
if (vflags & HPTE_V_BOLTED) {
|
||||
HvCallHpt_setSwBits(slot, 0x10, 0);
|
||||
HvCallHpt_setPp(slot, PP_RWXX);
|
||||
iSeries_hunlock(hpte_group);
|
||||
if (slot < 0)
|
||||
return 0x8 | (slot & 7);
|
||||
else
|
||||
return slot & 7;
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (slot == -1) { /* No available entry found in either group */
|
||||
iSeries_hunlock(hpte_group);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (slot < 0) { /* MSB set means secondary group */
|
||||
vflags |= HPTE_V_SECONDARY;
|
||||
secondary = 1;
|
||||
slot &= 0x7fffffffffffffff;
|
||||
}
|
||||
|
||||
|
||||
lhpte.v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M) |
|
||||
vflags | HPTE_V_VALID;
|
||||
lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags;
|
||||
|
||||
/* Now fill in the actual HPTE */
|
||||
HvCallHpt_addValidate(slot, secondary, &lhpte);
|
||||
|
||||
iSeries_hunlock(hpte_group);
|
||||
|
||||
return (secondary << 3) | (slot & 7);
|
||||
}
|
||||
|
||||
static unsigned long iSeries_hpte_getword0(unsigned long slot)
|
||||
{
|
||||
struct hash_pte hpte;
|
||||
|
||||
HvCallHpt_get(&hpte, slot);
|
||||
return hpte.v;
|
||||
}
|
||||
|
||||
static long iSeries_hpte_remove(unsigned long hpte_group)
|
||||
{
|
||||
unsigned long slot_offset;
|
||||
int i;
|
||||
unsigned long hpte_v;
|
||||
|
||||
/* Pick a random slot to start at */
|
||||
slot_offset = mftb() & 0x7;
|
||||
|
||||
iSeries_hlock(hpte_group);
|
||||
|
||||
for (i = 0; i < HPTES_PER_GROUP; i++) {
|
||||
hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset);
|
||||
|
||||
if (! (hpte_v & HPTE_V_BOLTED)) {
|
||||
HvCallHpt_invalidateSetSwBitsGet(hpte_group +
|
||||
slot_offset, 0, 0);
|
||||
iSeries_hunlock(hpte_group);
|
||||
return i;
|
||||
}
|
||||
|
||||
slot_offset++;
|
||||
slot_offset &= 0x7;
|
||||
}
|
||||
|
||||
iSeries_hunlock(hpte_group);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The HyperVisor expects the "flags" argument in this form:
|
||||
* bits 0..59 : reserved
|
||||
* bit 60 : N
|
||||
* bits 61..63 : PP2,PP1,PP0
|
||||
*/
|
||||
static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
|
||||
unsigned long va, int psize, int ssize, int local)
|
||||
{
|
||||
struct hash_pte hpte;
|
||||
unsigned long want_v;
|
||||
|
||||
iSeries_hlock(slot);
|
||||
|
||||
HvCallHpt_get(&hpte, slot);
|
||||
want_v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M);
|
||||
|
||||
if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) {
|
||||
/*
|
||||
* Hypervisor expects bits as NPPP, which is
|
||||
* different from how they are mapped in our PP.
|
||||
*/
|
||||
HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1));
|
||||
iSeries_hunlock(slot);
|
||||
return 0;
|
||||
}
|
||||
iSeries_hunlock(slot);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions used to find the PTE for a particular virtual address.
|
||||
* Only used during boot when bolting pages.
|
||||
*
|
||||
* Input : vpn : virtual page number
|
||||
* Output: PTE index within the page table of the entry
|
||||
* -1 on failure
|
||||
*/
|
||||
static long iSeries_hpte_find(unsigned long vpn)
|
||||
{
|
||||
struct hash_pte hpte;
|
||||
long slot;
|
||||
|
||||
/*
|
||||
* The HvCallHpt_findValid interface is as follows:
|
||||
* 0xffffffffffffffff : No entry found.
|
||||
* 0x00000000xxxxxxxx : Entry found in primary group, slot x
|
||||
* 0x80000000xxxxxxxx : Entry found in secondary group, slot x
|
||||
*/
|
||||
slot = HvCallHpt_findValid(&hpte, vpn);
|
||||
if (hpte.v & HPTE_V_VALID) {
|
||||
if (slot < 0) {
|
||||
slot &= 0x7fffffffffffffff;
|
||||
slot = -slot;
|
||||
}
|
||||
} else
|
||||
slot = -1;
|
||||
return slot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the page protection bits. Intended to be used to create
|
||||
* guard pages for kernel data structures on pages which are bolted
|
||||
* in the HPT. Assumes pages being operated on will not be stolen.
|
||||
* Does not work on large pages.
|
||||
*
|
||||
* No need to lock here because we should be the only user.
|
||||
*/
|
||||
static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
|
||||
int psize, int ssize)
|
||||
{
|
||||
unsigned long vsid,va,vpn;
|
||||
long slot;
|
||||
|
||||
BUG_ON(psize != MMU_PAGE_4K);
|
||||
|
||||
vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
|
||||
va = (vsid << 28) | (ea & 0x0fffffff);
|
||||
vpn = va >> HW_PAGE_SHIFT;
|
||||
slot = iSeries_hpte_find(vpn);
|
||||
if (slot == -1)
|
||||
panic("updateboltedpp: Could not find page to bolt\n");
|
||||
HvCallHpt_setPp(slot, newpp);
|
||||
}
|
||||
|
||||
static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
|
||||
int psize, int ssize, int local)
|
||||
{
|
||||
unsigned long hpte_v;
|
||||
unsigned long avpn = va >> 23;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
iSeries_hlock(slot);
|
||||
|
||||
hpte_v = iSeries_hpte_getword0(slot);
|
||||
|
||||
if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID))
|
||||
HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0);
|
||||
|
||||
iSeries_hunlock(slot);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void __init hpte_init_iSeries(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(iSeries_hlocks); i++)
|
||||
spin_lock_init(&iSeries_hlocks[i]);
|
||||
|
||||
ppc_md.hpte_invalidate = iSeries_hpte_invalidate;
|
||||
ppc_md.hpte_updatepp = iSeries_hpte_updatepp;
|
||||
ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
|
||||
ppc_md.hpte_insert = iSeries_hpte_insert;
|
||||
ppc_md.hpte_remove = iSeries_hpte_remove;
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* This file contains the code to perform calls to the
|
||||
* iSeries LPAR hypervisor
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h> /* XXX for STACK_FRAME_OVERHEAD */
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* Hypervisor call
|
||||
*
|
||||
* Invoke the iSeries hypervisor via the System Call instruction
|
||||
* Parameters are passed to this routine in registers r3 - r10
|
||||
*
|
||||
* r3 contains the HV function to be called
|
||||
* r4-r10 contain the operands to the hypervisor function
|
||||
*
|
||||
*/
|
||||
|
||||
_GLOBAL(HvCall)
|
||||
_GLOBAL(HvCall0)
|
||||
_GLOBAL(HvCall1)
|
||||
_GLOBAL(HvCall2)
|
||||
_GLOBAL(HvCall3)
|
||||
_GLOBAL(HvCall4)
|
||||
_GLOBAL(HvCall5)
|
||||
_GLOBAL(HvCall6)
|
||||
_GLOBAL(HvCall7)
|
||||
|
||||
|
||||
mfcr r0
|
||||
std r0,-8(r1)
|
||||
stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1)
|
||||
|
||||
/* r0 = 0xffffffffffffffff indicates a hypervisor call */
|
||||
|
||||
li r0,-1
|
||||
|
||||
/* Invoke the hypervisor */
|
||||
|
||||
sc
|
||||
|
||||
ld r1,0(r1)
|
||||
ld r0,-8(r1)
|
||||
mtcrf 0xff,r0
|
||||
|
||||
/* return to caller, return value in r3 */
|
||||
|
||||
blr
|
||||
|
||||
_GLOBAL(HvCall0Ret16)
|
||||
_GLOBAL(HvCall1Ret16)
|
||||
_GLOBAL(HvCall2Ret16)
|
||||
_GLOBAL(HvCall3Ret16)
|
||||
_GLOBAL(HvCall4Ret16)
|
||||
_GLOBAL(HvCall5Ret16)
|
||||
_GLOBAL(HvCall6Ret16)
|
||||
_GLOBAL(HvCall7Ret16)
|
||||
|
||||
mfcr r0
|
||||
std r0,-8(r1)
|
||||
std r31,-16(r1)
|
||||
stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1)
|
||||
|
||||
mr r31,r4
|
||||
li r0,-1
|
||||
mr r4,r5
|
||||
mr r5,r6
|
||||
mr r6,r7
|
||||
mr r7,r8
|
||||
mr r8,r9
|
||||
mr r9,r10
|
||||
|
||||
sc
|
||||
|
||||
std r3,0(r31)
|
||||
std r4,8(r31)
|
||||
|
||||
mr r3,r5
|
||||
|
||||
ld r1,0(r1)
|
||||
ld r0,-8(r1)
|
||||
mtcrf 0xff,r0
|
||||
ld r31,-16(r1)
|
||||
|
||||
blr
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Mike Corrigan IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/iseries/hv_call.h>
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
|
||||
|
||||
void HvCall_writeLogBuffer(const void *buffer, u64 len)
|
||||
{
|
||||
struct HvLpBufferList hv_buf;
|
||||
u64 left_this_page;
|
||||
u64 cur = virt_to_abs(buffer);
|
||||
|
||||
while (len) {
|
||||
hv_buf.addr = cur;
|
||||
left_this_page = ((cur & HW_PAGE_MASK) + HW_PAGE_SIZE) - cur;
|
||||
if (left_this_page > len)
|
||||
left_this_page = len;
|
||||
hv_buf.len = left_this_page;
|
||||
len -= left_this_page;
|
||||
HvCall2(HvCallBaseWriteLogBuffer,
|
||||
virt_to_abs(&hv_buf),
|
||||
left_this_page);
|
||||
cur = (cur & HW_PAGE_MASK) + HW_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Kyle A. Lucke, IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <asm/iseries/hv_lp_config.h>
|
||||
#include "it_lp_naca.h"
|
||||
|
||||
HvLpIndex HvLpConfig_getLpIndex_outline(void)
|
||||
{
|
||||
return HvLpConfig_getLpIndex();
|
||||
}
|
||||
EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline);
|
||||
|
||||
HvLpIndex HvLpConfig_getLpIndex(void)
|
||||
{
|
||||
return itLpNaca.xLpIndex;
|
||||
}
|
||||
EXPORT_SYMBOL(HvLpConfig_getLpIndex);
|
||||
|
||||
HvLpIndex HvLpConfig_getPrimaryLpIndex(void)
|
||||
{
|
||||
return itLpNaca.xPrimaryLpIndex;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(HvLpConfig_getPrimaryLpIndex);
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
|
||||
*
|
||||
* Rewrite, cleanup:
|
||||
*
|
||||
* Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
|
||||
* Copyright (C) 2006 Olof Johansson <olof@lixom.net>
|
||||
*
|
||||
* Dynamic DMA mapping support, iSeries-specific parts.
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/tce.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/iseries/hv_call_xm.h>
|
||||
#include <asm/iseries/hv_call_event.h>
|
||||
#include <asm/iseries/iommu.h>
|
||||
|
||||
static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
|
||||
unsigned long uaddr, enum dma_data_direction direction,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
u64 rc;
|
||||
u64 tce, rpn;
|
||||
|
||||
while (npages--) {
|
||||
rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
|
||||
tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
|
||||
|
||||
if (tbl->it_type == TCE_VB) {
|
||||
/* Virtual Bus */
|
||||
tce |= TCE_VALID|TCE_ALLIO;
|
||||
if (direction != DMA_TO_DEVICE)
|
||||
tce |= TCE_VB_WRITE;
|
||||
} else {
|
||||
/* PCI Bus */
|
||||
tce |= TCE_PCI_READ; /* Read allowed */
|
||||
if (direction != DMA_TO_DEVICE)
|
||||
tce |= TCE_PCI_WRITE;
|
||||
}
|
||||
|
||||
rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
|
||||
if (rc)
|
||||
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%llx\n",
|
||||
rc);
|
||||
index++;
|
||||
uaddr += TCE_PAGE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
|
||||
{
|
||||
u64 rc;
|
||||
|
||||
while (npages--) {
|
||||
rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
|
||||
if (rc)
|
||||
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%llx\n",
|
||||
rc);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure passed to HvCallXm_getTceTableParms
|
||||
*/
|
||||
struct iommu_table_cb {
|
||||
unsigned long itc_busno; /* Bus number for this tce table */
|
||||
unsigned long itc_start; /* Will be NULL for secondary */
|
||||
unsigned long itc_totalsize; /* Size (in pages) of whole table */
|
||||
unsigned long itc_offset; /* Index into real tce table of the
|
||||
start of our section */
|
||||
unsigned long itc_size; /* Size (in pages) of our section */
|
||||
unsigned long itc_index; /* Index of this tce table */
|
||||
unsigned short itc_maxtables; /* Max num of tables for partition */
|
||||
unsigned char itc_virtbus; /* Flag to indicate virtual bus */
|
||||
unsigned char itc_slotno; /* IOA Tce Slot Index */
|
||||
unsigned char itc_rsvd[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Call Hv with the architected data structure to get TCE table info.
|
||||
* info. Put the returned data into the Linux representation of the
|
||||
* TCE table data.
|
||||
* The Hardware Tce table comes in three flavors.
|
||||
* 1. TCE table shared between Buses.
|
||||
* 2. TCE table per Bus.
|
||||
* 3. TCE Table per IOA.
|
||||
*/
|
||||
void iommu_table_getparms_iSeries(unsigned long busno,
|
||||
unsigned char slotno,
|
||||
unsigned char virtbus,
|
||||
struct iommu_table* tbl)
|
||||
{
|
||||
struct iommu_table_cb *parms;
|
||||
|
||||
parms = kzalloc(sizeof(*parms), GFP_KERNEL);
|
||||
if (parms == NULL)
|
||||
panic("PCI_DMA: TCE Table Allocation failed.");
|
||||
|
||||
parms->itc_busno = busno;
|
||||
parms->itc_slotno = slotno;
|
||||
parms->itc_virtbus = virtbus;
|
||||
|
||||
HvCallXm_getTceTableParms(iseries_hv_addr(parms));
|
||||
|
||||
if (parms->itc_size == 0)
|
||||
panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms);
|
||||
|
||||
/* itc_size is in pages worth of table, it_size is in # of entries */
|
||||
tbl->it_size = (parms->itc_size * TCE_PAGE_SIZE) / TCE_ENTRY_SIZE;
|
||||
tbl->it_busno = parms->itc_busno;
|
||||
tbl->it_offset = parms->itc_offset;
|
||||
tbl->it_index = parms->itc_index;
|
||||
tbl->it_blocksize = 1;
|
||||
tbl->it_type = virtbus ? TCE_VB : TCE_PCI;
|
||||
|
||||
kfree(parms);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/*
|
||||
* This function compares the known tables to find an iommu_table
|
||||
* that has already been built for hardware TCEs.
|
||||
*/
|
||||
static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
for (node = NULL; (node = of_find_all_nodes(node)); ) {
|
||||
struct pci_dn *pdn = PCI_DN(node);
|
||||
struct iommu_table *it;
|
||||
|
||||
if (pdn == NULL)
|
||||
continue;
|
||||
it = pdn->iommu_table;
|
||||
if ((it != NULL) &&
|
||||
(it->it_type == TCE_PCI) &&
|
||||
(it->it_offset == tbl->it_offset) &&
|
||||
(it->it_index == tbl->it_index) &&
|
||||
(it->it_size == tbl->it_size)) {
|
||||
of_node_put(node);
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void pci_dma_dev_setup_iseries(struct pci_dev *pdev)
|
||||
{
|
||||
struct iommu_table *tbl;
|
||||
struct device_node *dn = pci_device_to_OF_node(pdev);
|
||||
struct pci_dn *pdn = PCI_DN(dn);
|
||||
const u32 *lsn = of_get_property(dn, "linux,logical-slot-number", NULL);
|
||||
|
||||
BUG_ON(lsn == NULL);
|
||||
|
||||
tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL);
|
||||
|
||||
iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
|
||||
|
||||
/* Look for existing tce table */
|
||||
pdn->iommu_table = iommu_table_find(tbl);
|
||||
if (pdn->iommu_table == NULL)
|
||||
pdn->iommu_table = iommu_init_table(tbl, -1);
|
||||
else
|
||||
kfree(tbl);
|
||||
set_iommu_table_base(&pdev->dev, pdn->iommu_table);
|
||||
}
|
||||
#else
|
||||
#define pci_dma_dev_setup_iseries NULL
|
||||
#endif
|
||||
|
||||
static struct iommu_table veth_iommu_table;
|
||||
static struct iommu_table vio_iommu_table;
|
||||
|
||||
void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
|
||||
{
|
||||
return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
|
||||
DMA_BIT_MASK(32), flag, -1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iseries_hv_alloc);
|
||||
|
||||
void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iseries_hv_free);
|
||||
|
||||
dma_addr_t iseries_hv_map(void *vaddr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
return iommu_map_page(NULL, &vio_iommu_table, virt_to_page(vaddr),
|
||||
(unsigned long)vaddr % PAGE_SIZE, size,
|
||||
DMA_BIT_MASK(32), direction, NULL);
|
||||
}
|
||||
|
||||
void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
iommu_unmap_page(&vio_iommu_table, dma_handle, size, direction, NULL);
|
||||
}
|
||||
|
||||
void __init iommu_vio_init(void)
|
||||
{
|
||||
iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
|
||||
veth_iommu_table.it_size /= 2;
|
||||
vio_iommu_table = veth_iommu_table;
|
||||
vio_iommu_table.it_offset += veth_iommu_table.it_size;
|
||||
|
||||
if (!iommu_init_table(&veth_iommu_table, -1))
|
||||
printk("Virtual Bus VETH TCE table failed.\n");
|
||||
if (!iommu_init_table(&vio_iommu_table, -1))
|
||||
printk("Virtual Bus VIO TCE table failed.\n");
|
||||
}
|
||||
|
||||
struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev)
|
||||
{
|
||||
if (strcmp(dev->type, "network") == 0)
|
||||
return &veth_iommu_table;
|
||||
return &vio_iommu_table;
|
||||
}
|
||||
|
||||
void iommu_init_early_iSeries(void)
|
||||
{
|
||||
ppc_md.tce_build = tce_build_iSeries;
|
||||
ppc_md.tce_free = tce_free_iSeries;
|
||||
|
||||
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_iseries;
|
||||
set_pci_dma_ops(&dma_iommu_ops);
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Mike Corrigan IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _ISERIES_IPL_PARMS_H
|
||||
#define _ISERIES_IPL_PARMS_H
|
||||
|
||||
/*
|
||||
* This struct maps the IPL Parameters DMA'd from the SP.
|
||||
*
|
||||
* Warning:
|
||||
* This data must map in exactly 64 bytes and match the architecture for
|
||||
* the IPL parms
|
||||
*/
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
struct ItIplParmsReal {
|
||||
u8 xFormat; // Defines format of IplParms x00-x00
|
||||
u8 xRsvd01:6; // Reserved x01-x01
|
||||
u8 xAlternateSearch:1; // Alternate search indicator ...
|
||||
u8 xUaSupplied:1; // UA Supplied on programmed IPL...
|
||||
u8 xLsUaFormat; // Format byte for UA x02-x02
|
||||
u8 xRsvd02; // Reserved x03-x03
|
||||
u32 xLsUa; // LS UA x04-x07
|
||||
u32 xUnusedLsLid; // First OS LID to load x08-x0B
|
||||
u16 xLsBusNumber; // LS Bus Number x0C-x0D
|
||||
u8 xLsCardAdr; // LS Card Address x0E-x0E
|
||||
u8 xLsBoardAdr; // LS Board Address x0F-x0F
|
||||
u32 xRsvd03; // Reserved x10-x13
|
||||
u8 xSpcnPresent:1; // SPCN present x14-x14
|
||||
u8 xCpmPresent:1; // CPM present ...
|
||||
u8 xRsvd04:6; // Reserved ...
|
||||
u8 xRsvd05:4; // Reserved x15-x15
|
||||
u8 xKeyLock:4; // Keylock setting ...
|
||||
u8 xRsvd06:6; // Reserved x16-x16
|
||||
u8 xIplMode:2; // Ipl mode (A|B|C|D) ...
|
||||
u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17
|
||||
u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19
|
||||
u16 xPowerOnResetIpl:1; // Indicate POR condition ...
|
||||
u16 xMainStorePreserved:1; // Main Storage is preserved ...
|
||||
u16 xRsvd07:13; // Reserved ...
|
||||
u16 xIplSource:16; // Ipl source x1A-x1B
|
||||
u8 xIplReason:8; // Reason for this IPL x1C-x1C
|
||||
u8 xRsvd08; // Reserved x1D-x1D
|
||||
u16 xRsvd09; // Reserved x1E-x1F
|
||||
u16 xSysBoxType; // System Box Type x20-x21
|
||||
u16 xSysProcType; // System Processor Type x22-x23
|
||||
u32 xRsvd10; // Reserved x24-x27
|
||||
u64 xRsvd11; // Reserved x28-x2F
|
||||
u64 xRsvd12; // Reserved x30-x37
|
||||
u64 xRsvd13; // Reserved x38-x3F
|
||||
};
|
||||
|
||||
#endif /* _ISERIES_IPL_PARMS_H */
|
||||
@@ -1,400 +0,0 @@
|
||||
/*
|
||||
* This module supports the iSeries PCI bus interrupt handling
|
||||
* Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
|
||||
* Copyright (C) 2004-2005 IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Change Activity:
|
||||
* Created, December 13, 2000 by Wayne Holm
|
||||
* End Change Activity
|
||||
*/
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/paca.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
#include <asm/iseries/hv_lp_event.h>
|
||||
#include <asm/iseries/hv_call_xm.h>
|
||||
#include <asm/iseries/it_lp_queue.h>
|
||||
|
||||
#include "irq.h"
|
||||
#include "pci.h"
|
||||
#include "call_pci.h"
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
enum pci_event_type {
|
||||
pe_bus_created = 0, /* PHB has been created */
|
||||
pe_bus_error = 1, /* PHB has failed */
|
||||
pe_bus_failed = 2, /* Msg to Secondary, Primary failed bus */
|
||||
pe_node_failed = 4, /* Multi-adapter bridge has failed */
|
||||
pe_node_recovered = 5, /* Multi-adapter bridge has recovered */
|
||||
pe_bus_recovered = 12, /* PHB has been recovered */
|
||||
pe_unquiese_bus = 18, /* Secondary bus unqiescing */
|
||||
pe_bridge_error = 21, /* Bridge Error */
|
||||
pe_slot_interrupt = 22 /* Slot interrupt */
|
||||
};
|
||||
|
||||
struct pci_event {
|
||||
struct HvLpEvent event;
|
||||
union {
|
||||
u64 __align; /* Align on an 8-byte boundary */
|
||||
struct {
|
||||
u32 fisr;
|
||||
HvBusNumber bus_number;
|
||||
HvSubBusNumber sub_bus_number;
|
||||
HvAgentId dev_id;
|
||||
} slot;
|
||||
struct {
|
||||
HvBusNumber bus_number;
|
||||
HvSubBusNumber sub_bus_number;
|
||||
} bus;
|
||||
struct {
|
||||
HvBusNumber bus_number;
|
||||
HvSubBusNumber sub_bus_number;
|
||||
HvAgentId dev_id;
|
||||
} node;
|
||||
} data;
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(pending_irqs_lock);
|
||||
static int num_pending_irqs;
|
||||
static int pending_irqs[NR_IRQS];
|
||||
|
||||
static void int_received(struct pci_event *event)
|
||||
{
|
||||
int irq;
|
||||
|
||||
switch (event->event.xSubtype) {
|
||||
case pe_slot_interrupt:
|
||||
irq = event->event.xCorrelationToken;
|
||||
if (irq < NR_IRQS) {
|
||||
spin_lock(&pending_irqs_lock);
|
||||
pending_irqs[irq]++;
|
||||
num_pending_irqs++;
|
||||
spin_unlock(&pending_irqs_lock);
|
||||
} else {
|
||||
printk(KERN_WARNING "int_received: bad irq number %d\n",
|
||||
irq);
|
||||
HvCallPci_eoi(event->data.slot.bus_number,
|
||||
event->data.slot.sub_bus_number,
|
||||
event->data.slot.dev_id);
|
||||
}
|
||||
break;
|
||||
/* Ignore error recovery events for now */
|
||||
case pe_bus_created:
|
||||
printk(KERN_INFO "int_received: system bus %d created\n",
|
||||
event->data.bus.bus_number);
|
||||
break;
|
||||
case pe_bus_error:
|
||||
case pe_bus_failed:
|
||||
printk(KERN_INFO "int_received: system bus %d failed\n",
|
||||
event->data.bus.bus_number);
|
||||
break;
|
||||
case pe_bus_recovered:
|
||||
case pe_unquiese_bus:
|
||||
printk(KERN_INFO "int_received: system bus %d recovered\n",
|
||||
event->data.bus.bus_number);
|
||||
break;
|
||||
case pe_node_failed:
|
||||
case pe_bridge_error:
|
||||
printk(KERN_INFO
|
||||
"int_received: multi-adapter bridge %d/%d/%d failed\n",
|
||||
event->data.node.bus_number,
|
||||
event->data.node.sub_bus_number,
|
||||
event->data.node.dev_id);
|
||||
break;
|
||||
case pe_node_recovered:
|
||||
printk(KERN_INFO
|
||||
"int_received: multi-adapter bridge %d/%d/%d recovered\n",
|
||||
event->data.node.bus_number,
|
||||
event->data.node.sub_bus_number,
|
||||
event->data.node.dev_id);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"int_received: unrecognized event subtype 0x%x\n",
|
||||
event->event.xSubtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_event_handler(struct HvLpEvent *event)
|
||||
{
|
||||
if (event && (event->xType == HvLpEvent_Type_PciIo)) {
|
||||
if (hvlpevent_is_int(event))
|
||||
int_received((struct pci_event *)event);
|
||||
else
|
||||
printk(KERN_ERR
|
||||
"pci_event_handler: unexpected ack received\n");
|
||||
} else if (event)
|
||||
printk(KERN_ERR
|
||||
"pci_event_handler: Unrecognized PCI event type 0x%x\n",
|
||||
(int)event->xType);
|
||||
else
|
||||
printk(KERN_ERR "pci_event_handler: NULL event received\n");
|
||||
}
|
||||
|
||||
#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
|
||||
#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
|
||||
#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
|
||||
#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
|
||||
|
||||
/*
|
||||
* This will be called by device drivers (via enable_IRQ)
|
||||
* to enable INTA in the bridge interrupt status register.
|
||||
*/
|
||||
static void iseries_enable_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
|
||||
|
||||
/* The IRQ has already been locked by the caller */
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
function = REAL_IRQ_TO_FUNC(rirq);
|
||||
dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
||||
|
||||
/* Unmask secondary INTA */
|
||||
mask = 0x80000000;
|
||||
HvCallPci_unmaskInterrupts(bus, sub_bus, dev_id, mask);
|
||||
}
|
||||
|
||||
/* This is called by iseries_activate_IRQs */
|
||||
static unsigned int iseries_startup_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
|
||||
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
function = REAL_IRQ_TO_FUNC(rirq);
|
||||
dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
||||
|
||||
/* Link the IRQ number to the bridge */
|
||||
HvCallXm_connectBusUnit(bus, sub_bus, dev_id, d->irq);
|
||||
|
||||
/* Unmask bridge interrupts in the FISR */
|
||||
mask = 0x01010000 << function;
|
||||
HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
|
||||
iseries_enable_IRQ(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called out of iSeries_fixup to activate interrupt
|
||||
* generation for usable slots
|
||||
*/
|
||||
void __init iSeries_activate_IRQs()
|
||||
{
|
||||
int irq;
|
||||
unsigned long flags;
|
||||
|
||||
for_each_irq (irq) {
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
struct irq_chip *chip;
|
||||
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
chip = irq_desc_get_chip(desc);
|
||||
if (chip && chip->irq_startup) {
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
chip->irq_startup(&desc->irq_data);
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this is not called anywhere currently */
|
||||
static void iseries_shutdown_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
|
||||
|
||||
/* irq should be locked by the caller */
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
function = REAL_IRQ_TO_FUNC(rirq);
|
||||
dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
||||
|
||||
/* Invalidate the IRQ number in the bridge */
|
||||
HvCallXm_connectBusUnit(bus, sub_bus, dev_id, 0);
|
||||
|
||||
/* Mask bridge interrupts in the FISR */
|
||||
mask = 0x01010000 << function;
|
||||
HvCallPci_maskFisr(bus, sub_bus, dev_id, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* This will be called by device drivers (via disable_IRQ)
|
||||
* to disable INTA in the bridge interrupt status register.
|
||||
*/
|
||||
static void iseries_disable_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
|
||||
|
||||
/* The IRQ has already been locked by the caller */
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
function = REAL_IRQ_TO_FUNC(rirq);
|
||||
dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
||||
|
||||
/* Mask secondary INTA */
|
||||
mask = 0x80000000;
|
||||
HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
|
||||
}
|
||||
|
||||
static void iseries_end_IRQ(struct irq_data *d)
|
||||
{
|
||||
unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
|
||||
|
||||
HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
|
||||
(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
|
||||
}
|
||||
|
||||
static struct irq_chip iseries_pic = {
|
||||
.name = "iSeries",
|
||||
.irq_startup = iseries_startup_IRQ,
|
||||
.irq_shutdown = iseries_shutdown_IRQ,
|
||||
.irq_unmask = iseries_enable_IRQ,
|
||||
.irq_mask = iseries_disable_IRQ,
|
||||
.irq_eoi = iseries_end_IRQ
|
||||
};
|
||||
|
||||
/*
|
||||
* This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
|
||||
* It calculates the irq value for the slot.
|
||||
* Note that sub_bus is always 0 (at the moment at least).
|
||||
*/
|
||||
int __init iSeries_allocate_IRQ(HvBusNumber bus,
|
||||
HvSubBusNumber sub_bus, u32 bsubbus)
|
||||
{
|
||||
unsigned int realirq;
|
||||
u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
|
||||
u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
|
||||
|
||||
realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
|
||||
+ function;
|
||||
|
||||
return irq_create_mapping(NULL, realirq);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/*
|
||||
* Get the next pending IRQ.
|
||||
*/
|
||||
unsigned int iSeries_get_irq(void)
|
||||
{
|
||||
int irq = NO_IRQ_IGNORE;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (get_lppaca()->int_dword.fields.ipi_cnt) {
|
||||
get_lppaca()->int_dword.fields.ipi_cnt = 0;
|
||||
smp_ipi_demux();
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
if (hvlpevent_is_pending())
|
||||
process_hvlpevents();
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (num_pending_irqs) {
|
||||
spin_lock(&pending_irqs_lock);
|
||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
||||
if (pending_irqs[irq]) {
|
||||
pending_irqs[irq]--;
|
||||
num_pending_irqs--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&pending_irqs_lock);
|
||||
if (irq >= NR_IRQS)
|
||||
irq = NO_IRQ_IGNORE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
irq_set_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iseries_irq_host_match(struct irq_host *h, struct device_node *np)
|
||||
{
|
||||
/* Match all */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct irq_host_ops iseries_irq_host_ops = {
|
||||
.map = iseries_irq_host_map,
|
||||
.match = iseries_irq_host_match,
|
||||
};
|
||||
|
||||
/*
|
||||
* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
|
||||
* It must be called before the bus walk.
|
||||
*/
|
||||
void __init iSeries_init_IRQ(void)
|
||||
{
|
||||
/* Register PCI event handler and open an event path */
|
||||
struct irq_host *host;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The Hypervisor only allows us up to 256 interrupt
|
||||
* sources (the irq number is passed in a u8).
|
||||
*/
|
||||
irq_set_virq_count(256);
|
||||
|
||||
/* Create irq host. No need for a revmap since HV will give us
|
||||
* back our virtual irq number
|
||||
*/
|
||||
host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
|
||||
&iseries_irq_host_ops, 0);
|
||||
BUG_ON(host == NULL);
|
||||
irq_set_default_host(host);
|
||||
|
||||
ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
|
||||
&pci_event_handler);
|
||||
if (ret == 0) {
|
||||
ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
|
||||
if (ret != 0)
|
||||
printk(KERN_ERR "iseries_init_IRQ: open event path "
|
||||
"failed with rc 0x%x\n", ret);
|
||||
} else
|
||||
printk(KERN_ERR "iseries_init_IRQ: register handler "
|
||||
"failed with rc 0x%x\n", ret);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef _ISERIES_IRQ_H
|
||||
#define _ISERIES_IRQ_H
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern void iSeries_init_IRQ(void);
|
||||
extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
|
||||
extern void iSeries_activate_IRQs(void);
|
||||
#else
|
||||
#define iSeries_init_IRQ NULL
|
||||
#endif
|
||||
extern unsigned int iSeries_get_irq(void);
|
||||
|
||||
#endif /* _ISERIES_IRQ_H */
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Dave Boutcher IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H
|
||||
#define _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H
|
||||
|
||||
/*
|
||||
* This struct maps the panel information
|
||||
*
|
||||
* Warning:
|
||||
* This data must match the architecture for the panel information
|
||||
*/
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
struct ItExtVpdPanel {
|
||||
/* Definition of the Extended Vpd On Panel Data Area */
|
||||
char systemSerial[8];
|
||||
char mfgID[4];
|
||||
char reserved1[24];
|
||||
char machineType[4];
|
||||
char systemID[6];
|
||||
char somUniqueCnt[4];
|
||||
char serialNumberCount;
|
||||
char reserved2[7];
|
||||
u16 bbu3;
|
||||
u16 bbu2;
|
||||
u16 bbu1;
|
||||
char xLocationLabel[8];
|
||||
u8 xRsvd1[6];
|
||||
u16 xFrameId;
|
||||
u8 xRsvd2[48];
|
||||
};
|
||||
|
||||
extern struct ItExtVpdPanel xItExtVpdPanel;
|
||||
|
||||
#endif /* _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H */
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Mike Corrigan IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _PLATFORMS_ISERIES_IT_LP_NACA_H
|
||||
#define _PLATFORMS_ISERIES_IT_LP_NACA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* This control block contains the data that is shared between the
|
||||
* hypervisor (PLIC) and the OS.
|
||||
*/
|
||||
|
||||
struct ItLpNaca {
|
||||
// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
|
||||
u32 xDesc; // Eye catcher x00-x03
|
||||
u16 xSize; // Size of this class x04-x05
|
||||
u16 xIntHdlrOffset; // Offset to IntHdlr array x06-x07
|
||||
u8 xMaxIntHdlrEntries; // Number of entries in array x08-x08
|
||||
u8 xPrimaryLpIndex; // LP Index of Primary x09-x09
|
||||
u8 xServiceLpIndex; // LP Ind of Service Focal Pointx0A-x0A
|
||||
u8 xLpIndex; // LP Index x0B-x0B
|
||||
u16 xMaxLpQueues; // Number of allocated queues x0C-x0D
|
||||
u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F
|
||||
u8 xPirEnvironMode; // Piranha or hardware x10-x10
|
||||
u8 xPirConsoleMode; // Piranha console indicator x11-x11
|
||||
u8 xPirDasdMode; // Piranha dasd indicator x12-x12
|
||||
u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17
|
||||
u8 flags; // flags, see below x18-x1F
|
||||
u8 xSpVpdFormat; // VPD areas are in CSP format ...
|
||||
u8 xIntProcRatio; // Ratio of int procs to procs ...
|
||||
u8 xRsvd1_2[5]; // Reserved ...
|
||||
u16 xRsvd1_3; // Reserved x20-x21
|
||||
u16 xPlicVrmIndex; // VRM index of PLIC x22-x23
|
||||
u16 xMinSupportedSlicVrmInd;// Min supported OS VRM index x24-x25
|
||||
u16 xMinCompatableSlicVrmInd;// Min compatible OS VRM index x26-x27
|
||||
u64 xLoadAreaAddr; // ER address of load area x28-x2F
|
||||
u32 xLoadAreaChunks; // Chunks for the load area x30-x33
|
||||
u32 xPaseSysCallCRMask; // Mask used to test CR before x34-x37
|
||||
// doing an ASR switch on PASE
|
||||
// system call.
|
||||
u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f
|
||||
u8 xRsvd1_4[64]; // x40-x7F
|
||||
|
||||
// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
|
||||
u8 xRsvd2_0[128]; // Reserved x00-x7F
|
||||
|
||||
// CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators
|
||||
// NB: Padding required to keep xInterruptHdlr at x300 which is required
|
||||
// for v4r4 PLIC.
|
||||
u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F
|
||||
u8 xRsvd3_0[384]; // Reserved 180-2FF
|
||||
|
||||
// CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt
|
||||
// handlers
|
||||
u64 xInterruptHdlr[32]; // Interrupt handlers 300-x3FF
|
||||
};
|
||||
|
||||
extern struct ItLpNaca itLpNaca;
|
||||
|
||||
#define ITLPNACA_LPAR 0x80 /* Is LPAR installed on the system */
|
||||
#define ITLPNACA_PARTITIONED 0x40 /* Is the system partitioned */
|
||||
#define ITLPNACA_HWSYNCEDTBS 0x20 /* Hardware synced TBs */
|
||||
#define ITLPNACA_HMTINT 0x10 /* Utilize MHT for interrupts */
|
||||
|
||||
#endif /* _PLATFORMS_ISERIES_IT_LP_NACA_H */
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* (C) 2001-2005 PPC 64 Team, IBM Corp
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/iseries/hv_call_sc.h>
|
||||
|
||||
EXPORT_SYMBOL(HvCall0);
|
||||
EXPORT_SYMBOL(HvCall1);
|
||||
EXPORT_SYMBOL(HvCall2);
|
||||
EXPORT_SYMBOL(HvCall3);
|
||||
EXPORT_SYMBOL(HvCall4);
|
||||
EXPORT_SYMBOL(HvCall5);
|
||||
EXPORT_SYMBOL(HvCall6);
|
||||
EXPORT_SYMBOL(HvCall7);
|
||||
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001 Mike Corrigan, IBM Corp
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/lppaca.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/iseries/lpar_map.h>
|
||||
#include <asm/iseries/it_lp_queue.h>
|
||||
#include <asm/iseries/alpaca.h>
|
||||
|
||||
#include "naca.h"
|
||||
#include "vpd_areas.h"
|
||||
#include "spcomm_area.h"
|
||||
#include "ipl_parms.h"
|
||||
#include "processor_vpd.h"
|
||||
#include "release_data.h"
|
||||
#include "it_exp_vpd_panel.h"
|
||||
#include "it_lp_naca.h"
|
||||
|
||||
/* The HvReleaseData is the root of the information shared between
|
||||
* the hypervisor and Linux.
|
||||
*/
|
||||
const struct HvReleaseData hvReleaseData = {
|
||||
.xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
|
||||
.xSize = sizeof(struct HvReleaseData),
|
||||
.xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
|
||||
.xSlicNacaAddr = &naca, /* 64-bit Naca address */
|
||||
.xMsNucDataOffset = LPARMAP_PHYS,
|
||||
.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 */
|
||||
.xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */
|
||||
0xa7, 0x40, 0xf2, 0x4b,
|
||||
0xf4, 0x4b, 0xf6, 0xf4 },
|
||||
};
|
||||
|
||||
/*
|
||||
* The NACA. The first dword of the naca is required by the iSeries
|
||||
* hypervisor to point to itVpdAreas. The hypervisor finds the NACA
|
||||
* through the pointer in hvReleaseData.
|
||||
*/
|
||||
struct naca_struct naca = {
|
||||
.xItVpdAreas = &itVpdAreas,
|
||||
.xRamDisk = 0,
|
||||
.xRamDiskSize = 0,
|
||||
};
|
||||
|
||||
struct ItLpRegSave {
|
||||
u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003
|
||||
u16 xSize; // Size of this class 004-005
|
||||
u8 xInUse; // Area is live 006-007
|
||||
u8 xRsvd1[9]; // Reserved 007-00F
|
||||
|
||||
u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F
|
||||
u32 xCTRL; // Control Register 170-173
|
||||
u32 xDEC; // Decrementer 174-177
|
||||
u32 xFPSCR; // FP Status and Control Reg 178-17B
|
||||
u32 xPVR; // Processor Version Number 17C-17F
|
||||
|
||||
u64 xMMCR0; // Monitor Mode Control Reg 0 180-187
|
||||
u32 xPMC1; // Perf Monitor Counter 1 188-18B
|
||||
u32 xPMC2; // Perf Monitor Counter 2 18C-18F
|
||||
u32 xPMC3; // Perf Monitor Counter 3 190-193
|
||||
u32 xPMC4; // Perf Monitor Counter 4 194-197
|
||||
u32 xPIR; // Processor ID Reg 198-19B
|
||||
|
||||
u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F
|
||||
u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3
|
||||
u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7
|
||||
u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB
|
||||
u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF
|
||||
u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3
|
||||
u32 xTSC; // Thread Switch Control 1B4-1B7
|
||||
u32 xTST; // Thread Switch Timeout 1B8-1BB
|
||||
u32 xRsvd; // Reserved 1BC-1BF
|
||||
|
||||
u64 xACCR; // Address Compare Control Reg 1C0-1C7
|
||||
u64 xIMR; // Instruction Match Register 1C8-1CF
|
||||
u64 xSDR1; // Storage Description Reg 1 1D0-1D7
|
||||
u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF
|
||||
u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7
|
||||
u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF
|
||||
u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7
|
||||
u64 xTB; // Time Base Register 1F8-1FF
|
||||
|
||||
u64 xFPR[32]; // Floating Point Registers 200-2FF
|
||||
|
||||
u64 xMSR; // Machine State Register 300-307
|
||||
u64 xNIA; // Next Instruction Address 308-30F
|
||||
|
||||
u64 xDABR; // Data Address Breakpoint Reg 310-317
|
||||
u64 xIABR; // Inst Address Breakpoint Reg 318-31F
|
||||
|
||||
u64 xHID0; // HW Implementation Dependent0 320-327
|
||||
|
||||
u64 xHID4; // HW Implementation Dependent4 328-32F
|
||||
u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337
|
||||
u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F
|
||||
u64 xSDAR; // Sample Data Address Register 340-347
|
||||
u64 xSIAR; // Sample Inst Address Register 348-34F
|
||||
|
||||
u8 xRsvd3[176]; // Reserved 350-3FF
|
||||
};
|
||||
|
||||
extern void system_reset_iSeries(void);
|
||||
extern void machine_check_iSeries(void);
|
||||
extern void data_access_iSeries(void);
|
||||
extern void instruction_access_iSeries(void);
|
||||
extern void hardware_interrupt_iSeries(void);
|
||||
extern void alignment_iSeries(void);
|
||||
extern void program_check_iSeries(void);
|
||||
extern void fp_unavailable_iSeries(void);
|
||||
extern void decrementer_iSeries(void);
|
||||
extern void trap_0a_iSeries(void);
|
||||
extern void trap_0b_iSeries(void);
|
||||
extern void system_call_iSeries(void);
|
||||
extern void single_step_iSeries(void);
|
||||
extern void trap_0e_iSeries(void);
|
||||
extern void performance_monitor_iSeries(void);
|
||||
extern void data_access_slb_iSeries(void);
|
||||
extern void instruction_access_slb_iSeries(void);
|
||||
|
||||
struct ItLpNaca itLpNaca = {
|
||||
.xDesc = 0xd397d581, /* "LpNa" ebcdic */
|
||||
.xSize = 0x0400, /* size of ItLpNaca */
|
||||
.xIntHdlrOffset = 0x0300, /* offset to int array */
|
||||
.xMaxIntHdlrEntries = 19, /* # ents */
|
||||
.xPrimaryLpIndex = 0, /* Part # of primary */
|
||||
.xServiceLpIndex = 0, /* Part # of serv */
|
||||
.xLpIndex = 0, /* Part # of me */
|
||||
.xMaxLpQueues = 0, /* # of LP queues */
|
||||
.xLpQueueOffset = 0x100, /* offset of start of LP queues */
|
||||
.xPirEnvironMode = 0, /* Piranha stuff */
|
||||
.xPirConsoleMode = 0,
|
||||
.xPirDasdMode = 0,
|
||||
.flags = 0,
|
||||
.xSpVpdFormat = 0,
|
||||
.xIntProcRatio = 0,
|
||||
.xPlicVrmIndex = 0, /* VRM index of PLIC */
|
||||
.xMinSupportedSlicVrmInd = 0, /* min supported SLIC */
|
||||
.xMinCompatableSlicVrmInd = 0, /* min compat SLIC */
|
||||
.xLoadAreaAddr = 0, /* 64-bit addr of load area */
|
||||
.xLoadAreaChunks = 0, /* chunks for load area */
|
||||
.xPaseSysCallCRMask = 0, /* PASE mask */
|
||||
.xSlicSegmentTablePtr = 0, /* seg table */
|
||||
.xOldLpQueue = { 0 }, /* Old LP Queue */
|
||||
.xInterruptHdlr = {
|
||||
(u64)system_reset_iSeries, /* 0x100 System Reset */
|
||||
(u64)machine_check_iSeries, /* 0x200 Machine Check */
|
||||
(u64)data_access_iSeries, /* 0x300 Data Access */
|
||||
(u64)instruction_access_iSeries, /* 0x400 Instruction Access */
|
||||
(u64)hardware_interrupt_iSeries, /* 0x500 External */
|
||||
(u64)alignment_iSeries, /* 0x600 Alignment */
|
||||
(u64)program_check_iSeries, /* 0x700 Program Check */
|
||||
(u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */
|
||||
(u64)decrementer_iSeries, /* 0x900 Decrementer */
|
||||
(u64)trap_0a_iSeries, /* 0xa00 Trap 0A */
|
||||
(u64)trap_0b_iSeries, /* 0xb00 Trap 0B */
|
||||
(u64)system_call_iSeries, /* 0xc00 System Call */
|
||||
(u64)single_step_iSeries, /* 0xd00 Single Step */
|
||||
(u64)trap_0e_iSeries, /* 0xe00 Trap 0E */
|
||||
(u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */
|
||||
0, /* int 0x1000 */
|
||||
0, /* int 0x1010 */
|
||||
0, /* int 0x1020 CPU ctls */
|
||||
(u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */
|
||||
(u64)data_access_slb_iSeries, /* 0x380 D-SLB */
|
||||
(u64)instruction_access_slb_iSeries /* 0x480 I-SLB */
|
||||
}
|
||||
};
|
||||
|
||||
/* May be filled in by the hypervisor so cannot end up in the BSS */
|
||||
static struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
|
||||
|
||||
/* May be filled in by the hypervisor so cannot end up in the BSS */
|
||||
struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data")));
|
||||
|
||||
#define maxPhysicalProcessors 32
|
||||
|
||||
struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
|
||||
{
|
||||
.xInstCacheOperandSize = 32,
|
||||
.xDataCacheOperandSize = 32,
|
||||
.xProcFreq = 50000000,
|
||||
.xTimeBaseFreq = 50000000,
|
||||
.xPVR = 0x3600
|
||||
}
|
||||
};
|
||||
|
||||
/* Space for Main Store Vpd 27,200 bytes */
|
||||
/* May be filled in by the hypervisor so cannot end up in the BSS */
|
||||
u64 xMsVpd[3400] __attribute__((__section__(".data")));
|
||||
|
||||
/* Space for Recovery Log Buffer */
|
||||
/* May be filled in by the hypervisor so cannot end up in the BSS */
|
||||
static u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
|
||||
|
||||
static const struct SpCommArea xSpCommArea = {
|
||||
.xDesc = 0xE2D7C3C2,
|
||||
.xFormat = 1,
|
||||
};
|
||||
|
||||
static const struct ItLpRegSave iseries_reg_save[] = {
|
||||
[0 ... (NR_CPUS-1)] = {
|
||||
.xDesc = 0xd397d9e2, /* "LpRS" */
|
||||
.xSize = sizeof(struct ItLpRegSave),
|
||||
},
|
||||
};
|
||||
|
||||
#define ALPACA_INIT(number) \
|
||||
{ \
|
||||
.lppaca_ptr = &lppaca[number], \
|
||||
.reg_save_ptr = &iseries_reg_save[number], \
|
||||
}
|
||||
|
||||
const struct alpaca alpaca[] = {
|
||||
ALPACA_INIT( 0),
|
||||
#if NR_CPUS > 1
|
||||
ALPACA_INIT( 1), ALPACA_INIT( 2), ALPACA_INIT( 3),
|
||||
#if NR_CPUS > 4
|
||||
ALPACA_INIT( 4), ALPACA_INIT( 5), ALPACA_INIT( 6), ALPACA_INIT( 7),
|
||||
#if NR_CPUS > 8
|
||||
ALPACA_INIT( 8), ALPACA_INIT( 9), ALPACA_INIT(10), ALPACA_INIT(11),
|
||||
ALPACA_INIT(12), ALPACA_INIT(13), ALPACA_INIT(14), ALPACA_INIT(15),
|
||||
ALPACA_INIT(16), ALPACA_INIT(17), ALPACA_INIT(18), ALPACA_INIT(19),
|
||||
ALPACA_INIT(20), ALPACA_INIT(21), ALPACA_INIT(22), ALPACA_INIT(23),
|
||||
ALPACA_INIT(24), ALPACA_INIT(25), ALPACA_INIT(26), ALPACA_INIT(27),
|
||||
ALPACA_INIT(28), ALPACA_INIT(29), ALPACA_INIT(30), ALPACA_INIT(31),
|
||||
#if NR_CPUS > 32
|
||||
ALPACA_INIT(32), ALPACA_INIT(33), ALPACA_INIT(34), ALPACA_INIT(35),
|
||||
ALPACA_INIT(36), ALPACA_INIT(37), ALPACA_INIT(38), ALPACA_INIT(39),
|
||||
ALPACA_INIT(40), ALPACA_INIT(41), ALPACA_INIT(42), ALPACA_INIT(43),
|
||||
ALPACA_INIT(44), ALPACA_INIT(45), ALPACA_INIT(46), ALPACA_INIT(47),
|
||||
ALPACA_INIT(48), ALPACA_INIT(49), ALPACA_INIT(50), ALPACA_INIT(51),
|
||||
ALPACA_INIT(52), ALPACA_INIT(53), ALPACA_INIT(54), ALPACA_INIT(55),
|
||||
ALPACA_INIT(56), ALPACA_INIT(57), ALPACA_INIT(58), ALPACA_INIT(59),
|
||||
ALPACA_INIT(60), ALPACA_INIT(61), ALPACA_INIT(62), ALPACA_INIT(63),
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The LparMap data is now located at offset 0x6000 in head.S
|
||||
* It was put there so that the HvReleaseData could address it
|
||||
* with a 32-bit offset as required by the iSeries hypervisor
|
||||
*
|
||||
* The Naca has a pointer to the ItVpdAreas. The hypervisor finds
|
||||
* the Naca via the HvReleaseData area. The HvReleaseData has the
|
||||
* offset into the Naca of the pointer to the ItVpdAreas.
|
||||
*/
|
||||
const struct ItVpdAreas itVpdAreas = {
|
||||
.xSlicDesc = 0xc9a3e5c1, /* "ItVA" */
|
||||
.xSlicSize = sizeof(struct ItVpdAreas),
|
||||
.xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */
|
||||
.xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */
|
||||
.xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */
|
||||
.xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */
|
||||
.xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks),
|
||||
.xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs),
|
||||
.xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens),
|
||||
.xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens),
|
||||
.xSlicMaxSlotLabels = 0, /* max slot labels */
|
||||
.xSlicMaxLpQueues = 1, /* max LP queues */
|
||||
.xPlicDmaLens = { 0 }, /* DMA lengths */
|
||||
.xPlicDmaToks = { 0 }, /* DMA tokens */
|
||||
.xSlicVpdLens = { /* VPD lengths */
|
||||
0,0,0, /* 0 - 2 */
|
||||
sizeof(xItExtVpdPanel), /* 3 Extended VPD */
|
||||
sizeof(struct alpaca), /* 4 length of (fake) Paca */
|
||||
0, /* 5 */
|
||||
sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
|
||||
26992, /* 7 length of MS VPD */
|
||||
0, /* 8 */
|
||||
sizeof(struct ItLpNaca),/* 9 length of LP Naca */
|
||||
0, /* 10 */
|
||||
256, /* 11 length of Recovery Log Buf */
|
||||
sizeof(struct SpCommArea), /* 12 length of SP Comm Area */
|
||||
0,0,0, /* 13 - 15 */
|
||||
sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
|
||||
0,0,0,0,0,0, /* 17 - 22 */
|
||||
sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */
|
||||
0,0 /* 24 - 25 */
|
||||
},
|
||||
.xSlicVpdAdrs = { /* VPD addresses */
|
||||
0,0,0, /* 0 - 2 */
|
||||
&xItExtVpdPanel, /* 3 Extended VPD */
|
||||
&alpaca[0], /* 4 first (fake) Paca */
|
||||
0, /* 5 */
|
||||
&xItIplParmsReal, /* 6 IPL parms */
|
||||
&xMsVpd, /* 7 MS Vpd */
|
||||
0, /* 8 */
|
||||
&itLpNaca, /* 9 LpNaca */
|
||||
0, /* 10 */
|
||||
&xRecoveryLogBuffer, /* 11 Recovery Log Buffer */
|
||||
&xSpCommArea, /* 12 SP Comm Area */
|
||||
0,0,0, /* 13 - 15 */
|
||||
&xIoHriProcessorVpd, /* 16 Proc Vpd */
|
||||
0,0,0,0,0,0, /* 17 - 22 */
|
||||
&hvlpevent_queue, /* 23 Lp Queue */
|
||||
0,0
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user