[ppc64] Check range of PCI memory and I/O accesses on iSeries, from Stephen Rothwell --- arch/ppc64/kernel/iSeries_pci.c | 86 ++++++++++++++++++++++++++++++++++++++-- 1 files changed, 82 insertions(+), 4 deletions(-) diff -puN arch/ppc64/kernel/iSeries_pci.c~ppc64-iseries_pci_2 arch/ppc64/kernel/iSeries_pci.c --- 25/arch/ppc64/kernel/iSeries_pci.c~ppc64-iseries_pci_2 2004-01-13 23:23:09.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_pci.c 2004-01-13 23:23:09.000000000 -0800 @@ -654,10 +654,16 @@ static int CheckReturnCode(char *TextHdr static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, u64 *dsaptr, u64 *BarOffsetPtr) { - unsigned long BaseIoAddr = - (unsigned long)IoAddress - iSeries_Base_Io_Memory; - long TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size; - struct iSeries_Device_Node *DevNode = iSeries_IoMmTable[TableIndex]; + unsigned long BaseIoAddr; + unsigned long TableIndex; + struct iSeries_Device_Node *DevNode; + + if (((unsigned long)IoAddress < iSeries_Base_Io_Memory) || + ((unsigned long)IoAddress >= iSeries_Max_Io_Memory)) + return NULL; + BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory; + TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size; + DevNode = iSeries_IoMmTable[TableIndex]; if (DevNode != NULL) { int barnum = iSeries_IoBarTable[TableIndex]; @@ -685,6 +691,18 @@ u8 iSeries_Read_Byte(void *IoAddress) struct iSeries_Device_Node *DevNode = xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); + return 0xff; + } do { ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); @@ -701,6 +719,18 @@ u16 iSeries_Read_Word(void *IoAddress) struct iSeries_Device_Node *DevNode = xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); + return 0xffff; + } do { ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, @@ -718,6 +748,18 @@ u32 iSeries_Read_Long(void *IoAddress) struct iSeries_Device_Node *DevNode = xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); + return 0xffffffff; + } do { ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, @@ -742,6 +784,18 @@ void iSeries_Write_Byte(u8 data, void *I struct iSeries_Device_Node *DevNode = xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress); + return; + } do { ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); @@ -756,6 +810,18 @@ void iSeries_Write_Word(u16 data, void * struct iSeries_Device_Node *DevNode = xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); + return; + } do { ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); @@ -770,6 +836,18 @@ void iSeries_Write_Long(u32 data, void * struct iSeries_Device_Node *DevNode = xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); + return; + } do { ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); _