aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/mm/fault.c
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2013-08-06 16:04:13 -0400
committerChris Metcalf <cmetcalf@tilera.com>2013-08-13 16:04:10 -0400
commit2f9ac29eec71a696cb0dcc5fb82c0f8d4dac28c9 (patch)
treeee33ba7e452e8614130a811211eb2383a3133194 /arch/tile/mm/fault.c
parentf10da5472c6907a3fbd6886224b36d21925ce47b (diff)
tile: fast-path unaligned memory access for tilegx
This change enables unaligned userspace memory access via a kernel fast path on tilegx. The kernel tracks user PC/instruction pairs per-thread using a direct-mapped cache in userspace. The cache maps those PC/instruction pairs to JIT'ed instruction sequences that load or store using byte-wide load store intructions and then synthesize 2-, 4- or 8-byte load or store results. Once an instruction has been seen to generate an unaligned access once, subsequent hits on that instruction typically require overhead of only around 50 cycles if cache and TLB is hot. We support the prctl() PR_GET_UNALIGN / PR_SET_UNALIGN sys call to enable or disable unaligned fixups on a per-process basis. To do this we pull some of the tilepro unaligned support out of the single_step.c file; tilepro uses instruction disassembly for both single-step and unaligned access support. Since tilegx actually has hardware singlestep support, though, it's cleaner to keep the tilegx unaligned access code in a separate file. While we're at it, properly rename the tilepro-specific types, etc., to have tilepro suffixes instead of generic tile suffixes. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/mm/fault.c')
-rw-r--r--arch/tile/mm/fault.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index 6152819e555b..7863298dad4d 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -722,8 +722,49 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
722{ 722{
723 int is_page_fault; 723 int is_page_fault;
724 724
725#ifdef __tilegx__
726 /*
727 * We don't need early do_page_fault_ics() support, since unlike
728 * Pro we don't need to worry about unlocking the atomic locks.
729 * There is only one current case in GX where we touch any memory
730 * under ICS other than our own kernel stack, and we handle that
731 * here. (If we crash due to trying to touch our own stack,
732 * we're in too much trouble for C code to help out anyway.)
733 */
734 if (write & ~1) {
735 unsigned long pc = write & ~1;
736 if (pc >= (unsigned long) __start_unalign_asm_code &&
737 pc < (unsigned long) __end_unalign_asm_code) {
738 struct thread_info *ti = current_thread_info();
739 /*
740 * Our EX_CONTEXT is still what it was from the
741 * initial unalign exception, but now we've faulted
742 * on the JIT page. We would like to complete the
743 * page fault however is appropriate, and then retry
744 * the instruction that caused the unalign exception.
745 * Our state has been "corrupted" by setting the low
746 * bit in "sp", and stashing r0..r3 in the
747 * thread_info area, so we revert all of that, then
748 * continue as if this were a normal page fault.
749 */
750 regs->sp &= ~1UL;
751 regs->regs[0] = ti->unalign_jit_tmp[0];
752 regs->regs[1] = ti->unalign_jit_tmp[1];
753 regs->regs[2] = ti->unalign_jit_tmp[2];
754 regs->regs[3] = ti->unalign_jit_tmp[3];
755 write &= 1;
756 } else {
757 pr_alert("%s/%d: ICS set at page fault at %#lx: %#lx\n",
758 current->comm, current->pid, pc, address);
759 show_regs(regs);
760 do_group_exit(SIGKILL);
761 return;
762 }
763 }
764#else
725 /* This case should have been handled by do_page_fault_ics(). */ 765 /* This case should have been handled by do_page_fault_ics(). */
726 BUG_ON(write & ~1); 766 BUG_ON(write & ~1);
767#endif
727 768
728#if CHIP_HAS_TILE_DMA() 769#if CHIP_HAS_TILE_DMA()
729 /* 770 /*