aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/process.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-06-07 16:31:52 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-22 21:15:34 -0400
commite56e03b0cfeb997a4be9ad874c193824364942e0 (patch)
tree5a49f9a42d1577c13ee59d016bd0630c60de58d1 /arch/blackfin/kernel/process.c
parentac1b7c378ef26fba6694d5f118fe7fc16fee2fe2 (diff)
Blackfin: unify memory region checks between kgdb and traps
The kgdb (in multiple places) and traps code developed pretty much identical checks for how to access different regions of the Blackfin memory map, but each wasn't 100%, so unify them to avoid duplication, bitrot, and bugs with edge cases. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/process.c')
-rw-r--r--arch/blackfin/kernel/process.c151
1 files changed, 121 insertions, 30 deletions
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 3e1d86e456f6..79cad0ac5892 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -344,6 +344,87 @@ void finish_atomic_sections (struct pt_regs *regs)
344 } 344 }
345} 345}
346 346
347static inline
348int in_mem(unsigned long addr, unsigned long size,
349 unsigned long start, unsigned long end)
350{
351 return addr >= start && addr + size <= end;
352}
353static inline
354int in_mem_const_off(unsigned long addr, unsigned long size, unsigned long off,
355 unsigned long const_addr, unsigned long const_size)
356{
357 return const_size &&
358 in_mem(addr, size, const_addr + off, const_addr + const_size);
359}
360static inline
361int in_mem_const(unsigned long addr, unsigned long size,
362 unsigned long const_addr, unsigned long const_size)
363{
364 return in_mem_const_off(addr, 0, size, const_addr, const_size);
365}
366#define IN_ASYNC(bnum, bctlnum) \
367({ \
368 (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \
369 bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : \
370 BFIN_MEM_ACCESS_CORE; \
371})
372
373int bfin_mem_access_type(unsigned long addr, unsigned long size)
374{
375 int cpu = raw_smp_processor_id();
376
377 /* Check that things do not wrap around */
378 if (addr > ULONG_MAX - size)
379 return -EFAULT;
380
381 if (in_mem(addr, size, FIXED_CODE_START, physical_mem_end))
382 return BFIN_MEM_ACCESS_CORE;
383
384 if (in_mem_const(addr, size, L1_CODE_START, L1_CODE_LENGTH))
385 return cpu == 0 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA;
386 if (in_mem_const(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH))
387 return cpu == 0 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT;
388 if (in_mem_const(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH))
389 return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
390 if (in_mem_const(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
391 return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
392#ifdef COREB_L1_CODE_START
393 if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
394 return cpu == 1 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA;
395 if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
396 return cpu == 1 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT;
397 if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
398 return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
399 if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
400 return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
401#endif
402 if (in_mem_const(addr, size, L2_START, L2_LENGTH))
403 return BFIN_MEM_ACCESS_CORE;
404
405 if (addr >= SYSMMR_BASE)
406 return BFIN_MEM_ACCESS_CORE_ONLY;
407
408 /* We can't read EBIU banks that aren't enabled or we end up hanging
409 * on the access to the async space.
410 */
411 if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE))
412 return IN_ASYNC(0, 0);
413 if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE))
414 return IN_ASYNC(1, 0);
415 if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE))
416 return IN_ASYNC(2, 1);
417 if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE))
418 return IN_ASYNC(3, 1);
419
420 if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
421 return BFIN_MEM_ACCESS_CORE;
422 if (in_mem_const(addr, size, L1_ROM_START, L1_ROM_LENGTH))
423 return BFIN_MEM_ACCESS_DMA;
424
425 return -EFAULT;
426}
427
347#if defined(CONFIG_ACCESS_CHECK) 428#if defined(CONFIG_ACCESS_CHECK)
348#ifdef CONFIG_ACCESS_OK_L1 429#ifdef CONFIG_ACCESS_OK_L1
349__attribute__((l1_text)) 430__attribute__((l1_text))
@@ -353,51 +434,61 @@ int _access_ok(unsigned long addr, unsigned long size)
353{ 434{
354 if (size == 0) 435 if (size == 0)
355 return 1; 436 return 1;
356 if (addr > (addr + size)) 437 /* Check that things do not wrap around */
438 if (addr > ULONG_MAX - size)
357 return 0; 439 return 0;
358 if (segment_eq(get_fs(), KERNEL_DS)) 440 if (segment_eq(get_fs(), KERNEL_DS))
359 return 1; 441 return 1;
360#ifdef CONFIG_MTD_UCLINUX 442#ifdef CONFIG_MTD_UCLINUX
361 if (addr >= memory_start && (addr + size) <= memory_end) 443 if (1)
362 return 1; 444#else
363 if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end) 445 if (0)
446#endif
447 {
448 if (in_mem(addr, size, memory_start, memory_end))
449 return 1;
450 if (in_mem(addr, size, memory_mtd_end, physical_mem_end))
451 return 1;
452# ifndef CONFIG_ROMFS_ON_MTD
453 if (0)
454# endif
455 /* For XIP, allow user space to use pointers within the ROMFS. */
456 if (in_mem(addr, size, memory_mtd_start, memory_mtd_end))
457 return 1;
458 } else {
459 if (in_mem(addr, size, memory_start, physical_mem_end))
460 return 1;
461 }
462
463 if (in_mem(addr, size, (unsigned long)__init_begin, (unsigned long)__init_end))
364 return 1; 464 return 1;
365 465
366#ifdef CONFIG_ROMFS_ON_MTD 466 if (in_mem_const(addr, size, L1_CODE_START, L1_CODE_LENGTH))
367 /* For XIP, allow user space to use pointers within the ROMFS. */
368 if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end)
369 return 1; 467 return 1;
370#endif 468 if (in_mem_const_off(addr, size, _etext_l1 - _stext_l1, L1_CODE_START, L1_CODE_LENGTH))
371#else
372 if (addr >= memory_start && (addr + size) <= physical_mem_end)
373 return 1; 469 return 1;
374#endif 470 if (in_mem_const_off(addr, size, _ebss_l1 - _sdata_l1, L1_DATA_A_START, L1_DATA_A_LENGTH))
375 if (addr >= (unsigned long)__init_begin &&
376 addr + size <= (unsigned long)__init_end)
377 return 1; 471 return 1;
378 if (addr >= get_l1_scratch_start() 472 if (in_mem_const_off(addr, size, _ebss_b_l1 - _sdata_b_l1, L1_DATA_B_START, L1_DATA_B_LENGTH))
379 && addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH)
380 return 1; 473 return 1;
381#if L1_CODE_LENGTH != 0 474#ifdef COREB_L1_CODE_START
382 if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1) 475 if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
383 && addr + size <= get_l1_code_start() + L1_CODE_LENGTH)
384 return 1; 476 return 1;
385#endif 477 if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
386#if L1_DATA_A_LENGTH != 0
387 if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1)
388 && addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH)
389 return 1; 478 return 1;
390#endif 479 if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
391#if L1_DATA_B_LENGTH != 0
392 if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1)
393 && addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH)
394 return 1; 480 return 1;
395#endif 481 if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
396#if L2_LENGTH != 0
397 if (addr >= L2_START + (_ebss_l2 - _stext_l2)
398 && addr + size <= L2_START + L2_LENGTH)
399 return 1; 482 return 1;
400#endif 483#endif
484 if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
485 return 1;
486
487 if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
488 return 1;
489 if (in_mem_const(addr, size, L1_ROM_START, L1_ROM_LENGTH))
490 return 1;
491
401 return 0; 492 return 0;
402} 493}
403EXPORT_SYMBOL(_access_ok); 494EXPORT_SYMBOL(_access_ok);