diff options
Diffstat (limited to 'arch/blackfin/kernel/process.c')
-rw-r--r-- | arch/blackfin/kernel/process.c | 151 |
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 | ||
347 | static inline | ||
348 | int in_mem(unsigned long addr, unsigned long size, | ||
349 | unsigned long start, unsigned long end) | ||
350 | { | ||
351 | return addr >= start && addr + size <= end; | ||
352 | } | ||
353 | static inline | ||
354 | int 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 | } | ||
360 | static inline | ||
361 | int 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 | |||
373 | int 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 | } |
403 | EXPORT_SYMBOL(_access_ok); | 494 | EXPORT_SYMBOL(_access_ok); |