Diff
Modified: trunk/arch/blackfin/include/asm/uaccess.h (6602 => 6603)
--- trunk/arch/blackfin/include/asm/uaccess.h 2009-06-07 19:11:50 UTC (rev 6602)
+++ trunk/arch/blackfin/include/asm/uaccess.h 2009-06-07 21:21:31 UTC (rev 6603)
@@ -265,4 +265,12 @@
#define clear_user(to, n) __clear_user(to, n)
+/**
+ * bfin_mem_access_type() - what kind of memory access is required
+ * @addr: the address to check
+ * @size: number of bytes needed
+ * @return: <0 is error, 0 is core read, 1 is dma read
+ */
+int bfin_mem_access_type(unsigned long addr, unsigned long size);
+
#endif /* _BLACKFIN_UACCESS_H */
Modified: trunk/arch/blackfin/kernel/kgdb.c (6602 => 6603)
--- trunk/arch/blackfin/kernel/kgdb.c 2009-06-07 19:11:50 UTC (rev 6602)
+++ trunk/arch/blackfin/kernel/kgdb.c 2009-06-07 21:21:31 UTC (rev 6603)
@@ -463,42 +463,9 @@
static int validate_memory_access_address(unsigned long addr, int size)
{
- int cpu = raw_smp_processor_id();
-
if (size < 0)
return -EFAULT;
- if (addr >= 0x1000 && (addr + size) <= physical_mem_end)
- return 0;
- if (addr >= SYSMMR_BASE)
- return 0;
- if (IN_MEM(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE))
- return 0;
- if (cpu == 0) {
- if (IN_MEM(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH))
- return 0;
- if (IN_MEM(addr, size, L1_CODE_START, L1_CODE_LENGTH))
- return 0;
- if (IN_MEM(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH))
- return 0;
- if (IN_MEM(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
- return 0;
-#ifdef CONFIG_SMP
- } else if (cpu == 1) {
- if (IN_MEM(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
- return 0;
- if (IN_MEM(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
- return 0;
- if (IN_MEM(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
- return 0;
- if (IN_MEM(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
- return 0;
-#endif
- }
-
- if (IN_MEM(addr, size, L2_START, L2_LENGTH))
- return 0;
-
- return -EFAULT;
+ return bfin_mem_access_type(addr, size) < 0 ? -EFAULT : 0;
}
/*
Modified: trunk/arch/blackfin/kernel/process.c (6602 => 6603)
--- trunk/arch/blackfin/kernel/process.c 2009-06-07 19:11:50 UTC (rev 6602)
+++ trunk/arch/blackfin/kernel/process.c 2009-06-07 21:21:31 UTC (rev 6603)
@@ -321,6 +321,57 @@
}
}
+#define IN_MEM(addr, size, const_addr, const_size) \
+({ \
+ unsigned long __addr = (unsigned long)(addr); \
+ (const_size && \
+ __addr >= const_addr && \
+ __addr + (size) <= const_addr + const_size); \
+})
+#define IN_ASYNC(bnum, bctlnum) \
+({ \
+ (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \
+ bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : 0; \
+})
+int bfin_mem_access_type(unsigned long addr, unsigned long size)
+{
+ /* Check that things do not wrap around */
+ if (addr > ULONG_MAX - size)
+ return -EFAULT;
+
+ if (addr >= FIXED_CODE_START && (addr + size) <= physical_mem_end)
+ return 0;
+
+ if (IN_MEM(addr, size, get_l1_code_start(), L1_CODE_LENGTH))
+ return 1;
+
+ if (IN_MEM(addr, size, get_l1_scratch_start(), L1_SCRATCH_LENGTH))
+ return 0;
+ if (IN_MEM(addr, size, get_l1_data_a_start(), L1_DATA_A_LENGTH))
+ return 0;
+ if (IN_MEM(addr, size, get_l1_data_b_start(), L1_DATA_B_LENGTH))
+ return 0;
+ if (IN_MEM(addr, size, L2_START, L2_LENGTH))
+ return 0;
+
+ if (addr >= SYSMMR_BASE)
+ return 0;
+
+ /* We can't read EBIU banks that aren't enabled or we end up hanging
+ * on the access to the async space.
+ */
+ if (IN_MEM(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE))
+ return IN_ASYNC(0, 0);
+ if (IN_MEM(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE))
+ return IN_ASYNC(1, 0);
+ if (IN_MEM(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE))
+ return IN_ASYNC(2, 1);
+ if (IN_MEM(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE))
+ return IN_ASYNC(3, 1);
+
+ return -EFAULT;
+}
+
#if defined(CONFIG_ACCESS_CHECK)
#ifdef CONFIG_ACCESS_OK_L1
__attribute__((l1_text))
Modified: trunk/arch/blackfin/kernel/traps.c (6602 => 6603)
--- trunk/arch/blackfin/kernel/traps.c 2009-06-07 19:11:50 UTC (rev 6602)
+++ trunk/arch/blackfin/kernel/traps.c 2009-06-07 21:21:31 UTC (rev 6603)
@@ -617,57 +617,26 @@
*/
static bool get_instruction(unsigned short *val, unsigned short *address)
{
+ unsigned long addr = (unsigned long)address;
- unsigned long addr;
-
- addr = (unsigned long)address;
-
/* Check for odd addresses */
if (addr & 0x1)
return false;
- /* Check that things do not wrap around */
- if (addr > (addr + 2))
+ /* MMR region will never have instructions */
+ if (addr >= SYSMMR_BASE)
return false;
- /*
- * Since we are in exception context, we need to do a little address checking
- * We need to make sure we are only accessing valid memory, and
- * we don't read something in the async space that can hang forever
- */
- if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
-#if L2_LENGTH != 0
- (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
-#endif
- (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
-#if L1_DATA_A_LENGTH != 0
- (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
-#endif
-#if L1_DATA_B_LENGTH != 0
- (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
-#endif
- (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
- (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
- addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
- (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
- addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
- (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
- addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
- (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
- addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
- *val = *address;
- return true;
+ switch (bfin_mem_access_type(addr, 2)) {
+ case 0: /* core access */
+ *val = *address;
+ return true;
+ case 1: /* L1 inst (dma access) */
+ isram_memcpy(val, address, 2);
+ return true;
+ default: /* invalid access */
+ return false;
}
-
-#if L1_CODE_LENGTH != 0
- if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
- isram_memcpy(val, address, 2);
- return true;
- }
-#endif
-
-
- return false;
}
/*