unaligned.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Handle unaligned accesses by emulation.
  3.  *
  4.  * This file is subject to the terms and conditions of the GNU General Public
  5.  * License.  See the file "COPYING" in the main directory of this archive
  6.  * for more details.
  7.  *
  8.  * Copyright (C) 1996, 1998, 1999 by Ralf Baechle
  9.  * Copyright (C) 1999 Silicon Graphics, Inc.
  10.  *
  11.  * This file contains exception handler for address error exception with the
  12.  * special capability to execute faulting instructions in software.  The
  13.  * handler does not try to handle the case when the program counter points
  14.  * to an address not aligned to a word boundary.
  15.  *
  16.  * Putting data to unaligned addresses is a bad practice even on Intel where
  17.  * only the performance is affected.  Much worse is that such code is non-
  18.  * portable.  Due to several programs that die on MIPS due to alignment
  19.  * problems I decided to implement this handler anyway though I originally
  20.  * didn't intend to do this at all for user code.
  21.  *
  22.  * For now I enable fixing of address errors by default to make life easier.
  23.  * I however intend to disable this somewhen in the future when the alignment
  24.  * problems with user programs have been fixed.  For programmers this is the
  25.  * right way to go.
  26.  *
  27.  * Fixing address errors is a per process option.  The option is inherited
  28.  * across fork(2) and execve(2) calls.  If you really want to use the
  29.  * option in your user programs - I discourage the use of the software
  30.  * emulation strongly - use the following code in your userland stuff:
  31.  *
  32.  * #include <sys/sysmips.h>
  33.  *
  34.  * ...
  35.  * sysmips(MIPS_FIXADE, x);
  36.  * ...
  37.  *
  38.  * The argument x is 0 for disabling software emulation, enabled otherwise.
  39.  *
  40.  * Below a little program to play around with this feature.
  41.  *
  42.  * #include <stdio.h>
  43.  * #include <asm/sysmips.h>
  44.  * 
  45.  * struct foo {
  46.  *         unsigned char bar[8];
  47.  * };
  48.  *
  49.  * main(int argc, char *argv[])
  50.  * {
  51.  *         struct foo x = {0, 1, 2, 3, 4, 5, 6, 7};
  52.  *         unsigned int *p = (unsigned int *) (x.bar + 3);
  53.  *         int i;
  54.  *
  55.  *         if (argc > 1)
  56.  *                 sysmips(MIPS_FIXADE, atoi(argv[1]));
  57.  *
  58.  *         printf("*p = %08lxn", *p);
  59.  *
  60.  *         *p = 0xdeadface;
  61.  *
  62.  *         for(i = 0; i <= 7; i++)
  63.  *         printf("%02x ", x.bar[i]);
  64.  *         printf("n");
  65.  * }
  66.  *
  67.  * Coprocessor loads are not supported; I think this case is unimportant
  68.  * in the practice.
  69.  *
  70.  * TODO: Handle ndc (attempted store to doubleword in uncached memory)
  71.  *       exception for the R6000.
  72.  *       A store crossing a page boundary might be executed only partially.
  73.  *       Undo the partial store in this case.
  74.  */
  75. #include <linux/config.h>
  76. #include <linux/mm.h>
  77. #include <linux/signal.h>
  78. #include <linux/smp.h>
  79. #include <linux/smp_lock.h>
  80. #include <asm/asm.h>
  81. #include <asm/branch.h>
  82. #include <asm/byteorder.h>
  83. #include <asm/inst.h>
  84. #include <asm/uaccess.h>
  85. #include <asm/system.h>
  86. #define STR(x)  __STR(x)
  87. #define __STR(x)  #x
  88. /*
  89.  * User code may only access USEG; kernel code may access the
  90.  * entire address space.
  91.  */
  92. #define check_axs(pc,a,s)
  93. if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0)
  94. goto sigbus;
  95. static inline void
  96. emulate_load_store_insn(struct pt_regs *regs,
  97.                         unsigned long addr,
  98.                         unsigned long pc)
  99. {
  100. union mips_instruction insn;
  101. unsigned long value, fixup;
  102. regs->regs[0] = 0;
  103. /*
  104.  * This load never faults.
  105.  */
  106. __get_user(insn.word, (unsigned int *)pc);
  107. switch (insn.i_format.opcode) {
  108. /*
  109.  * These are instructions that a compiler doesn't generate.  We
  110.  * can assume therefore that the code is MIPS-aware and
  111.  * really buggy.  Emulating these instructions would break the
  112.  * semantics anyway.
  113.  */
  114. case ll_op:
  115. case lld_op:
  116. case sc_op:
  117. case scd_op:
  118. /*
  119.  * For these instructions the only way to create an address
  120.  * error is an attempted access to kernel/supervisor address
  121.  * space.
  122.  */
  123. case ldl_op:
  124. case ldr_op:
  125. case lwl_op:
  126. case lwr_op:
  127. case sdl_op:
  128. case sdr_op:
  129. case swl_op:
  130. case swr_op:
  131. case lb_op:
  132. case lbu_op:
  133. case sb_op:
  134. goto sigbus;
  135. /*
  136.  * The remaining opcodes are the ones that are really of interest.
  137.  */
  138. case lh_op:
  139. check_axs(pc, addr, 2);
  140. __asm__(
  141. ".settnoatn"
  142. #ifdef __BIG_ENDIAN
  143. "1:tlbt%0,0(%1)n"
  144. "2:tlbut$1,1(%1)nt"
  145. #endif
  146. #ifdef __LITTLE_ENDIAN
  147. "1:tlbt%0,1(%1)n"
  148. "2:tlbut$1,0(%1)nt"
  149. #endif
  150. "sllt%0,0x8nt"
  151. "ort%0,$1nt"
  152. ".settatnt"
  153. ".sectiont__ex_table,"a"nt"
  154. STR(PTR)"t1b,%2nt"
  155. STR(PTR)"t2b,%2nt"
  156. ".previous"
  157. :"=&r" (value)
  158. :"r" (addr), "i" (&&fault)
  159. :"$1");
  160. regs->regs[insn.i_format.rt] = value;
  161. return;
  162. case lw_op:
  163. check_axs(pc, addr, 4);
  164. __asm__(
  165. #ifdef __BIG_ENDIAN
  166. "1:tlwlt%0,(%1)n"
  167. "2:tlwrt%0,3(%1)nt"
  168. #endif
  169. #ifdef __LITTLE_ENDIAN
  170. "1:tlwlt%0,3(%1)n"
  171. "2:tlwrt%0,(%1)nt"
  172. #endif
  173. ".sectiont__ex_table,"a"nt"
  174. STR(PTR)"t1b,%2nt"
  175. STR(PTR)"t2b,%2nt"
  176. ".previous"
  177. :"=&r" (value)
  178. :"r" (addr), "i" (&&fault));
  179. regs->regs[insn.i_format.rt] = value;
  180. return;
  181. case lhu_op:
  182. check_axs(pc, addr, 2);
  183. __asm__(
  184. ".settnoatn"
  185. #ifdef __BIG_ENDIAN
  186. "1:tlbut%0,0(%1)n"
  187. "2:tlbut$1,1(%1)nt"
  188. #endif
  189. #ifdef __LITTLE_ENDIAN
  190. "1:tlbut%0,1(%1)n"
  191. "2:tlbut$1,0(%1)nt"
  192. #endif
  193. "sllt%0,0x8nt"
  194. "ort%0,$1nt"
  195. ".settatnt"
  196. ".sectiont__ex_table,"a"nt"
  197. STR(PTR)"t1b,%2nt"
  198. STR(PTR)"t2b,%2nt"
  199. ".previous"
  200. :"=&r" (value)
  201. :"r" (addr), "i" (&&fault)
  202. :"$1");
  203. regs->regs[insn.i_format.rt] = value;
  204. return;
  205. case lwu_op:
  206. check_axs(pc, addr, 4);
  207. __asm__(
  208. #ifdef __BIG_ENDIAN
  209. "1:tlwlt%0,(%1)n"
  210. "2:tlwrt%0,3(%1)nt"
  211. #endif
  212. #ifdef __LITTLE_ENDIAN
  213. "1:tlwlt%0,3(%1)n"
  214. "2:tlwrt%0,(%1)nt"
  215. #endif
  216. ".sectiont__ex_table,"a"nt"
  217. STR(PTR)"t1b,%2nt"
  218. STR(PTR)"t2b,%2nt"
  219. ".previous"
  220. :"=&r" (value)
  221. :"r" (addr), "i" (&&fault));
  222. value &= 0xffffffff;
  223. regs->regs[insn.i_format.rt] = value;
  224. return;
  225. case ld_op:
  226. check_axs(pc, addr, 8);
  227. __asm__(
  228. ".settmips3n"
  229. #ifdef __BIG_ENDIAN
  230. "1:tldlt%0,(%1)n"
  231. "2:tldrt%0,7(%1)nt"
  232. #endif
  233. #ifdef __LITTLE_ENDIAN
  234. "1:tldlt%0,7(%1)n"
  235. "2:tldrt%0,(%1)nt"
  236. #endif
  237. ".settmips0nt"
  238. ".sectiont__ex_table,"a"nt"
  239. STR(PTR)"t1b,%2nt"
  240. STR(PTR)"t2b,%2nt"
  241. ".previous"
  242. :"=&r" (value)
  243. :"r" (addr), "i" (&&fault));
  244. regs->regs[insn.i_format.rt] = value;
  245. return;
  246. case sh_op:
  247. check_axs(pc, addr, 2);
  248. value = regs->regs[insn.i_format.rt];
  249. __asm__(
  250. #ifdef __BIG_ENDIAN
  251. ".settnoatn"
  252. "1:tsbt%0,1(%1)nt"
  253. "srlt$1,%0,0x8n"
  254. "2:tsbt$1,0(%1)nt"
  255. ".settatnt"
  256. #endif
  257. #ifdef __LITTLE_ENDIAN
  258. ".settnoatn"
  259. "1:tsbt%0,0(%1)nt"
  260. "srlt$1,%0,0x8n"
  261. "2:tsbt$1,1(%1)nt"
  262. ".settatnt"
  263. #endif
  264. ".sectiont__ex_table,"a"nt"
  265. STR(PTR)"t1b,%2nt"
  266. STR(PTR)"t2b,%2nt"
  267. ".previous"
  268. : /* no outputs */
  269. :"r" (value), "r" (addr), "i" (&&fault)
  270. :"$1");
  271. return;
  272. case sw_op:
  273. check_axs(pc, addr, 4);
  274. value = regs->regs[insn.i_format.rt];
  275. __asm__(
  276. #ifdef __BIG_ENDIAN
  277. "1:tswlt%0,(%1)n"
  278. "2:tswrt%0,3(%1)nt"
  279. #endif
  280. #ifdef __LITTLE_ENDIAN
  281. "1:tswlt%0,3(%1)n"
  282. "2:tswrt%0,(%1)nt"
  283. #endif
  284. ".sectiont__ex_table,"a"nt"
  285. STR(PTR)"t1b,%2nt"
  286. STR(PTR)"t2b,%2nt"
  287. ".previous"
  288. : /* no outputs */
  289. :"r" (value), "r" (addr), "i" (&&fault));
  290. return;
  291. case sd_op:
  292. check_axs(pc, addr, 8);
  293. value = regs->regs[insn.i_format.rt];
  294. __asm__(
  295. ".settmips3n"
  296. #ifdef __BIG_ENDIAN
  297. "1:tsdlt%0,(%1)n"
  298. "2:tsdrt%0,7(%1)nt"
  299. #endif
  300. #ifdef __LITTLE_ENDIAN
  301. "1:tsdlt%0,7(%1)n"
  302. "2:tsdrt%0,(%1)nt"
  303. #endif
  304. ".settmips0nt"
  305. ".sectiont__ex_table,"a"nt"
  306. STR(PTR)"t1b,%2nt"
  307. STR(PTR)"t2b,%2nt"
  308. ".previous"
  309. : /* no outputs */
  310. :"r" (value), "r" (addr), "i" (&&fault));
  311. return;
  312. case lwc1_op:
  313. case ldc1_op:
  314. case swc1_op:
  315. case sdc1_op:
  316. /*
  317.  * I herewith declare: this does not happen.  So send SIGBUS.
  318.  */
  319. goto sigbus;
  320. case lwc2_op:
  321. case ldc2_op:
  322. case swc2_op:
  323. case sdc2_op:
  324. /*
  325.  * These are the coprocessor 2 load/stores.  The current
  326.  * implementations don't use cp2 and cp2 should always be
  327.  * disabled in c0_status.  So send SIGILL.
  328.                  * (No longer true: The Sony Praystation uses cp2 for
  329.                  * 3D matrix operations.  Dunno if that thingy has a MMU ...)
  330.  */
  331. default:
  332. /*
  333.  * Pheeee...  We encountered an yet unknown instruction or
  334.  * cache coherence problem.  Die sucker, die ...
  335.  */
  336. goto sigill;
  337. }
  338. return;
  339. fault:
  340. /* Did we have an exception handler installed? */
  341. fixup = search_exception_table(regs->cp0_epc);
  342. if (fixup) {
  343. long new_epc;
  344. new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
  345. printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)n",
  346.        current->comm, regs->cp0_epc, new_epc);
  347. regs->cp0_epc = new_epc;
  348. return;
  349. }
  350. die_if_kernel ("Unhandled kernel unaligned access", regs);
  351. send_sig(SIGSEGV, current, 1);
  352. return;
  353. sigbus:
  354. die_if_kernel ("Unhandled kernel unaligned access", regs);
  355. send_sig(SIGBUS, current, 1);
  356. return;
  357. sigill:
  358. die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs);
  359. send_sig(SIGILL, current, 1);
  360. return;
  361. }
  362. #ifdef CONFIG_PROC_FS
  363. unsigned long unaligned_instructions;
  364. #endif
  365. asmlinkage void do_ade(struct pt_regs *regs)
  366. {
  367. unsigned long pc;
  368. /*
  369.  * Did we catch a fault trying to load an instruction?
  370.  * This also catches attempts to activate MIPS16 code on
  371.  * CPUs which don't support it.
  372.  */
  373. if (regs->cp0_badvaddr == regs->cp0_epc)
  374. goto sigbus;
  375. pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
  376. if (compute_return_epc(regs))
  377. return;
  378. if ((current->thread.mflags & MF_FIXADE) == 0)
  379. goto sigbus;
  380. emulate_load_store_insn(regs, regs->cp0_badvaddr, pc);
  381. #ifdef CONFIG_PROC_FS
  382. unaligned_instructions++;
  383. #endif
  384. return;
  385. sigbus:
  386. die_if_kernel ("Kernel unaligned instruction access", regs);
  387. force_sig(SIGBUS, current);
  388. }