exec_machdep.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214
  1. /*-
  2. * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (C) 1995, 1996 Wolfgang Solfrank.
  5. * Copyright (C) 1995, 1996 TooLs GmbH.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. All advertising materials mentioning features or use of this software
  17. * must display the following acknowledgement:
  18. * This product includes software developed by TooLs GmbH.
  19. * 4. The name of TooLs GmbH may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  28. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  30. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  31. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. /*-
  34. * Copyright (C) 2001 Benno Rice
  35. * All rights reserved.
  36. *
  37. * Redistribution and use in source and binary forms, with or without
  38. * modification, are permitted provided that the following conditions
  39. * are met:
  40. * 1. Redistributions of source code must retain the above copyright
  41. * notice, this list of conditions and the following disclaimer.
  42. * 2. Redistributions in binary form must reproduce the above copyright
  43. * notice, this list of conditions and the following disclaimer in the
  44. * documentation and/or other materials provided with the distribution.
  45. *
  46. * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
  47. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  48. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  49. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  50. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  51. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  52. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  53. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  54. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  55. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  56. * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
  57. */
  58. #include <sys/cdefs.h>
  59. __FBSDID("$FreeBSD$");
  60. #include "opt_fpu_emu.h"
  61. #include <sys/param.h>
  62. #include <sys/proc.h>
  63. #include <sys/systm.h>
  64. #include <sys/bio.h>
  65. #include <sys/buf.h>
  66. #include <sys/bus.h>
  67. #include <sys/cons.h>
  68. #include <sys/cpu.h>
  69. #include <sys/exec.h>
  70. #include <sys/imgact.h>
  71. #include <sys/kernel.h>
  72. #include <sys/ktr.h>
  73. #include <sys/lock.h>
  74. #include <sys/malloc.h>
  75. #include <sys/mutex.h>
  76. #include <sys/signalvar.h>
  77. #include <sys/syscallsubr.h>
  78. #include <sys/syscall.h>
  79. #include <sys/sysent.h>
  80. #include <sys/sysproto.h>
  81. #include <sys/ucontext.h>
  82. #include <sys/uio.h>
  83. #include <machine/altivec.h>
  84. #include <machine/cpu.h>
  85. #include <machine/elf.h>
  86. #include <machine/fpu.h>
  87. #include <machine/pcb.h>
  88. #include <machine/reg.h>
  89. #include <machine/sigframe.h>
  90. #include <machine/trap.h>
  91. #include <machine/vmparam.h>
  92. #include <vm/pmap.h>
  93. #ifdef FPU_EMU
  94. #include <powerpc/fpu/fpu_extern.h>
  95. #endif
  96. #ifdef COMPAT_FREEBSD32
  97. #include <compat/freebsd32/freebsd32_signal.h>
  98. #include <compat/freebsd32/freebsd32_util.h>
  99. #include <compat/freebsd32/freebsd32_proto.h>
  100. typedef struct __ucontext32 {
  101. sigset_t uc_sigmask;
  102. mcontext32_t uc_mcontext;
  103. uint32_t uc_link;
  104. struct sigaltstack32 uc_stack;
  105. uint32_t uc_flags;
  106. uint32_t __spare__[4];
  107. } ucontext32_t;
  108. struct sigframe32 {
  109. ucontext32_t sf_uc;
  110. struct siginfo32 sf_si;
  111. };
  112. static int grab_mcontext32(struct thread *td, mcontext32_t *, int flags);
  113. #endif
  114. static int grab_mcontext(struct thread *, mcontext_t *, int);
  115. static void cleanup_power_extras(struct thread *);
  116. #ifdef __powerpc64__
  117. extern struct sysentvec elf64_freebsd_sysvec_v2;
  118. #endif
  119. void
  120. sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
  121. {
  122. struct trapframe *tf;
  123. struct sigacts *psp;
  124. struct sigframe sf;
  125. struct thread *td;
  126. struct proc *p;
  127. #ifdef COMPAT_FREEBSD32
  128. struct siginfo32 siginfo32;
  129. struct sigframe32 sf32;
  130. #endif
  131. size_t sfpsize;
  132. caddr_t sfp, usfp;
  133. register_t sp;
  134. int oonstack, rndfsize;
  135. int sig;
  136. int code;
  137. td = curthread;
  138. p = td->td_proc;
  139. PROC_LOCK_ASSERT(p, MA_OWNED);
  140. psp = p->p_sigacts;
  141. mtx_assert(&psp->ps_mtx, MA_OWNED);
  142. tf = td->td_frame;
  143. /*
  144. * Fill siginfo structure.
  145. */
  146. ksi->ksi_info.si_signo = ksi->ksi_signo;
  147. ksi->ksi_info.si_addr =
  148. (void *)((tf->exc == EXC_DSI || tf->exc == EXC_DSE) ?
  149. tf->dar : tf->srr0);
  150. #ifdef COMPAT_FREEBSD32
  151. if (SV_PROC_FLAG(p, SV_ILP32)) {
  152. siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32);
  153. sig = siginfo32.si_signo;
  154. code = siginfo32.si_code;
  155. sfp = (caddr_t)&sf32;
  156. sfpsize = sizeof(sf32);
  157. rndfsize = roundup(sizeof(sf32), 16);
  158. sp = (uint32_t)tf->fixreg[1];
  159. oonstack = sigonstack(sp);
  160. /*
  161. * Save user context
  162. */
  163. memset(&sf32, 0, sizeof(sf32));
  164. grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0);
  165. sf32.sf_uc.uc_sigmask = *mask;
  166. sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
  167. sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size;
  168. sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  169. ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  170. sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  171. } else {
  172. #endif
  173. sig = ksi->ksi_signo;
  174. code = ksi->ksi_code;
  175. sfp = (caddr_t)&sf;
  176. sfpsize = sizeof(sf);
  177. #ifdef __powerpc64__
  178. /*
  179. * 64-bit PPC defines a 288 byte scratch region
  180. * below the stack.
  181. */
  182. rndfsize = 288 + roundup(sizeof(sf), 48);
  183. #else
  184. rndfsize = roundup(sizeof(sf), 16);
  185. #endif
  186. sp = tf->fixreg[1];
  187. oonstack = sigonstack(sp);
  188. /*
  189. * Save user context
  190. */
  191. memset(&sf, 0, sizeof(sf));
  192. grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
  193. sf.sf_uc.uc_sigmask = *mask;
  194. sf.sf_uc.uc_stack = td->td_sigstk;
  195. sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  196. ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  197. sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  198. #ifdef COMPAT_FREEBSD32
  199. }
  200. #endif
  201. CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
  202. catcher, sig);
  203. /*
  204. * Allocate and validate space for the signal handler context.
  205. */
  206. if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
  207. SIGISMEMBER(psp->ps_sigonstack, sig)) {
  208. usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp +
  209. td->td_sigstk.ss_size - rndfsize) & ~0xFul);
  210. } else {
  211. usfp = (void *)((sp - rndfsize) & ~0xFul);
  212. }
  213. /*
  214. * Set Floating Point facility to "Ignore Exceptions Mode" so signal
  215. * handler can run.
  216. */
  217. if (td->td_pcb->pcb_flags & PCB_FPU)
  218. tf->srr1 = tf->srr1 & ~(PSL_FE0 | PSL_FE1);
  219. /*
  220. * Set up the registers to return to sigcode.
  221. *
  222. * r1/sp - sigframe ptr
  223. * lr - sig function, dispatched to by blrl in trampoline
  224. * r3 - sig number
  225. * r4 - SIGINFO ? &siginfo : exception code
  226. * r5 - user context
  227. * srr0 - trampoline function addr
  228. */
  229. tf->lr = (register_t)catcher;
  230. tf->fixreg[1] = (register_t)usfp;
  231. tf->fixreg[FIRSTARG] = sig;
  232. #ifdef COMPAT_FREEBSD32
  233. tf->fixreg[FIRSTARG+2] = (register_t)usfp +
  234. ((SV_PROC_FLAG(p, SV_ILP32)) ?
  235. offsetof(struct sigframe32, sf_uc) :
  236. offsetof(struct sigframe, sf_uc));
  237. #else
  238. tf->fixreg[FIRSTARG+2] = (register_t)usfp +
  239. offsetof(struct sigframe, sf_uc);
  240. #endif
  241. if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  242. /*
  243. * Signal handler installed with SA_SIGINFO.
  244. */
  245. #ifdef COMPAT_FREEBSD32
  246. if (SV_PROC_FLAG(p, SV_ILP32)) {
  247. sf32.sf_si = siginfo32;
  248. tf->fixreg[FIRSTARG+1] = (register_t)usfp +
  249. offsetof(struct sigframe32, sf_si);
  250. sf32.sf_si = siginfo32;
  251. } else {
  252. #endif
  253. tf->fixreg[FIRSTARG+1] = (register_t)usfp +
  254. offsetof(struct sigframe, sf_si);
  255. sf.sf_si = ksi->ksi_info;
  256. #ifdef COMPAT_FREEBSD32
  257. }
  258. #endif
  259. } else {
  260. /* Old FreeBSD-style arguments. */
  261. tf->fixreg[FIRSTARG+1] = code;
  262. tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
  263. tf->dar : tf->srr0;
  264. }
  265. mtx_unlock(&psp->ps_mtx);
  266. PROC_UNLOCK(p);
  267. tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base;
  268. /*
  269. * copy the frame out to userland.
  270. */
  271. if (copyout(sfp, usfp, sfpsize) != 0) {
  272. /*
  273. * Process has trashed its stack. Kill it.
  274. */
  275. CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
  276. PROC_LOCK(p);
  277. sigexit(td, SIGILL);
  278. }
  279. CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
  280. tf->srr0, tf->fixreg[1]);
  281. PROC_LOCK(p);
  282. mtx_lock(&psp->ps_mtx);
  283. }
  284. int
  285. sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
  286. {
  287. ucontext_t uc;
  288. int error;
  289. CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
  290. if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
  291. CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
  292. return (EFAULT);
  293. }
  294. error = set_mcontext(td, &uc.uc_mcontext);
  295. if (error != 0)
  296. return (error);
  297. /*
  298. * Save FPU state if needed. User may have changed it on
  299. * signal handler
  300. */
  301. if (uc.uc_mcontext.mc_srr1 & PSL_FP)
  302. save_fpu(td);
  303. kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
  304. CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
  305. td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
  306. return (EJUSTRETURN);
  307. }
  308. #ifdef COMPAT_FREEBSD4
  309. int
  310. freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
  311. {
  312. return sys_sigreturn(td, (struct sigreturn_args *)uap);
  313. }
  314. #endif
  315. /*
  316. * Construct a PCB from a trapframe. This is called from kdb_trap() where
  317. * we want to start a backtrace from the function that caused us to enter
  318. * the debugger. We have the context in the trapframe, but base the trace
  319. * on the PCB. The PCB doesn't have to be perfect, as long as it contains
  320. * enough for a backtrace.
  321. */
  322. void
  323. makectx(struct trapframe *tf, struct pcb *pcb)
  324. {
  325. pcb->pcb_lr = tf->srr0;
  326. pcb->pcb_sp = tf->fixreg[1];
  327. }
  328. /*
  329. * get_mcontext/sendsig helper routine that doesn't touch the
  330. * proc lock
  331. */
  332. static int
  333. grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
  334. {
  335. struct pcb *pcb;
  336. int i;
  337. pcb = td->td_pcb;
  338. memset(mcp, 0, sizeof(mcontext_t));
  339. mcp->mc_vers = _MC_VERSION;
  340. mcp->mc_flags = 0;
  341. memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
  342. if (flags & GET_MC_CLEAR_RET) {
  343. mcp->mc_gpr[3] = 0;
  344. mcp->mc_gpr[4] = 0;
  345. }
  346. /*
  347. * This assumes that floating-point context is *not* lazy,
  348. * so if the thread has used FP there would have been a
  349. * FP-unavailable exception that would have set things up
  350. * correctly.
  351. */
  352. if (pcb->pcb_flags & PCB_FPREGS) {
  353. if (pcb->pcb_flags & PCB_FPU) {
  354. KASSERT(td == curthread,
  355. ("get_mcontext: fp save not curthread"));
  356. critical_enter();
  357. save_fpu(td);
  358. critical_exit();
  359. }
  360. mcp->mc_flags |= _MC_FP_VALID;
  361. memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
  362. for (i = 0; i < 32; i++)
  363. memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
  364. sizeof(double));
  365. }
  366. if (pcb->pcb_flags & PCB_VSX) {
  367. for (i = 0; i < 32; i++)
  368. memcpy(&mcp->mc_vsxfpreg[i],
  369. &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double));
  370. }
  371. /*
  372. * Repeat for Altivec context
  373. */
  374. if (pcb->pcb_flags & PCB_VEC) {
  375. KASSERT(td == curthread,
  376. ("get_mcontext: fp save not curthread"));
  377. critical_enter();
  378. save_vec(td);
  379. critical_exit();
  380. mcp->mc_flags |= _MC_AV_VALID;
  381. mcp->mc_vscr = pcb->pcb_vec.vscr;
  382. mcp->mc_vrsave = pcb->pcb_vec.vrsave;
  383. memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
  384. }
  385. mcp->mc_len = sizeof(*mcp);
  386. return (0);
  387. }
  388. int
  389. get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
  390. {
  391. int error;
  392. error = grab_mcontext(td, mcp, flags);
  393. if (error == 0) {
  394. PROC_LOCK(curthread->td_proc);
  395. mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
  396. PROC_UNLOCK(curthread->td_proc);
  397. }
  398. return (error);
  399. }
  400. int
  401. set_mcontext(struct thread *td, mcontext_t *mcp)
  402. {
  403. struct pcb *pcb;
  404. struct trapframe *tf;
  405. register_t tls;
  406. int i;
  407. pcb = td->td_pcb;
  408. tf = td->td_frame;
  409. if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
  410. return (EINVAL);
  411. /*
  412. * Don't let the user change privileged MSR bits.
  413. *
  414. * psl_userstatic is used here to mask off any bits that can
  415. * legitimately vary between user contexts (Floating point
  416. * exception control and any facilities that we are using the
  417. * "enable on first use" pattern with.)
  418. *
  419. * All other bits are required to match psl_userset(32).
  420. *
  421. * Remember to update the platform cpu_init code when implementing
  422. * support for a new conditional facility!
  423. */
  424. if ((mcp->mc_srr1 & psl_userstatic) != (tf->srr1 & psl_userstatic)) {
  425. return (EINVAL);
  426. }
  427. /* Copy trapframe, preserving TLS pointer across context change */
  428. if (SV_PROC_FLAG(td->td_proc, SV_LP64))
  429. tls = tf->fixreg[13];
  430. else
  431. tls = tf->fixreg[2];
  432. memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
  433. if (SV_PROC_FLAG(td->td_proc, SV_LP64))
  434. tf->fixreg[13] = tls;
  435. else
  436. tf->fixreg[2] = tls;
  437. /*
  438. * Force the FPU back off to ensure the new context will not bypass
  439. * the enable_fpu() setup code accidentally.
  440. *
  441. * This prevents an issue where a process that uses floating point
  442. * inside a signal handler could end up in a state where the MSR
  443. * did not match pcb_flags.
  444. *
  445. * Additionally, ensure VSX is disabled as well, as it is illegal
  446. * to leave it turned on when FP or VEC are off.
  447. */
  448. tf->srr1 &= ~(PSL_FP | PSL_VSX);
  449. pcb->pcb_flags &= ~(PCB_FPU | PCB_VSX);
  450. if (mcp->mc_flags & _MC_FP_VALID) {
  451. /* enable_fpu() will happen lazily on a fault */
  452. pcb->pcb_flags |= PCB_FPREGS;
  453. memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
  454. bzero(pcb->pcb_fpu.fpr, sizeof(pcb->pcb_fpu.fpr));
  455. for (i = 0; i < 32; i++) {
  456. memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i],
  457. sizeof(double));
  458. memcpy(&pcb->pcb_fpu.fpr[i].vsr[2],
  459. &mcp->mc_vsxfpreg[i], sizeof(double));
  460. }
  461. }
  462. if (mcp->mc_flags & _MC_AV_VALID) {
  463. if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
  464. critical_enter();
  465. enable_vec(td);
  466. critical_exit();
  467. }
  468. pcb->pcb_vec.vscr = mcp->mc_vscr;
  469. pcb->pcb_vec.vrsave = mcp->mc_vrsave;
  470. memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
  471. } else {
  472. tf->srr1 &= ~PSL_VEC;
  473. pcb->pcb_flags &= ~PCB_VEC;
  474. }
  475. return (0);
  476. }
  477. /*
  478. * Clean up extra POWER state. Some per-process registers and states are not
  479. * managed by the MSR, so must be cleaned up explicitly on thread exit.
  480. *
  481. * Currently this includes:
  482. * DSCR -- Data stream control register (PowerISA 2.06+)
  483. * FSCR -- Facility Status and Control Register (PowerISA 2.07+)
  484. */
  485. static void
  486. cleanup_power_extras(struct thread *td)
  487. {
  488. uint32_t pcb_flags;
  489. if (td != curthread)
  490. return;
  491. pcb_flags = td->td_pcb->pcb_flags;
  492. /* Clean up registers not managed by MSR. */
  493. if (pcb_flags & PCB_CFSCR)
  494. mtspr(SPR_FSCR, 0);
  495. if (pcb_flags & PCB_CDSCR)
  496. mtspr(SPR_DSCRP, 0);
  497. cleanup_fpscr();
  498. }
  499. /*
  500. * Set set up registers on exec.
  501. */
  502. void
  503. exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
  504. {
  505. struct trapframe *tf;
  506. register_t argc;
  507. tf = trapframe(td);
  508. bzero(tf, sizeof *tf);
  509. #ifdef __powerpc64__
  510. tf->fixreg[1] = -roundup(-stack + 48, 16);
  511. #else
  512. tf->fixreg[1] = -roundup(-stack + 8, 16);
  513. #endif
  514. /*
  515. * Set up arguments for _start():
  516. * _start(argc, argv, envp, obj, cleanup, ps_strings);
  517. *
  518. * Notes:
  519. * - obj and cleanup are the auxilliary and termination
  520. * vectors. They are fixed up by ld.elf_so.
  521. * - ps_strings is a NetBSD extention, and will be
  522. * ignored by executables which are strictly
  523. * compliant with the SVR4 ABI.
  524. */
  525. /* Collect argc from the user stack */
  526. argc = fuword((void *)stack);
  527. tf->fixreg[3] = argc;
  528. tf->fixreg[4] = stack + sizeof(register_t);
  529. tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
  530. tf->fixreg[6] = 0; /* auxillary vector */
  531. tf->fixreg[7] = 0; /* termination vector */
  532. tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */
  533. tf->srr0 = imgp->entry_addr;
  534. #ifdef __powerpc64__
  535. tf->fixreg[12] = imgp->entry_addr;
  536. #endif
  537. tf->srr1 = psl_userset | PSL_FE_DFLT;
  538. cleanup_power_extras(td);
  539. td->td_pcb->pcb_flags = 0;
  540. }
  541. #ifdef COMPAT_FREEBSD32
  542. void
  543. ppc32_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
  544. {
  545. struct trapframe *tf;
  546. uint32_t argc;
  547. tf = trapframe(td);
  548. bzero(tf, sizeof *tf);
  549. tf->fixreg[1] = -roundup(-stack + 8, 16);
  550. argc = fuword32((void *)stack);
  551. tf->fixreg[3] = argc;
  552. tf->fixreg[4] = stack + sizeof(uint32_t);
  553. tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t);
  554. tf->fixreg[6] = 0; /* auxillary vector */
  555. tf->fixreg[7] = 0; /* termination vector */
  556. tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */
  557. tf->srr0 = imgp->entry_addr;
  558. tf->srr1 = psl_userset32 | PSL_FE_DFLT;
  559. cleanup_power_extras(td);
  560. td->td_pcb->pcb_flags = 0;
  561. }
  562. #endif
  563. int
  564. fill_regs(struct thread *td, struct reg *regs)
  565. {
  566. struct trapframe *tf;
  567. tf = td->td_frame;
  568. memcpy(regs, tf, sizeof(struct reg));
  569. return (0);
  570. }
  571. int
  572. fill_dbregs(struct thread *td, struct dbreg *dbregs)
  573. {
  574. /* No debug registers on PowerPC */
  575. return (ENOSYS);
  576. }
  577. int
  578. fill_fpregs(struct thread *td, struct fpreg *fpregs)
  579. {
  580. struct pcb *pcb;
  581. int i;
  582. pcb = td->td_pcb;
  583. if ((pcb->pcb_flags & PCB_FPREGS) == 0)
  584. memset(fpregs, 0, sizeof(struct fpreg));
  585. else {
  586. memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
  587. for (i = 0; i < 32; i++)
  588. memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
  589. sizeof(double));
  590. }
  591. return (0);
  592. }
  593. int
  594. set_regs(struct thread *td, struct reg *regs)
  595. {
  596. struct trapframe *tf;
  597. tf = td->td_frame;
  598. memcpy(tf, regs, sizeof(struct reg));
  599. return (0);
  600. }
  601. int
  602. set_dbregs(struct thread *td, struct dbreg *dbregs)
  603. {
  604. /* No debug registers on PowerPC */
  605. return (ENOSYS);
  606. }
  607. int
  608. set_fpregs(struct thread *td, struct fpreg *fpregs)
  609. {
  610. struct pcb *pcb;
  611. int i;
  612. pcb = td->td_pcb;
  613. pcb->pcb_flags |= PCB_FPREGS;
  614. memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double));
  615. for (i = 0; i < 32; i++) {
  616. memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i],
  617. sizeof(double));
  618. }
  619. return (0);
  620. }
  621. #ifdef COMPAT_FREEBSD32
  622. int
  623. set_regs32(struct thread *td, struct reg32 *regs)
  624. {
  625. struct trapframe *tf;
  626. int i;
  627. tf = td->td_frame;
  628. for (i = 0; i < 32; i++)
  629. tf->fixreg[i] = regs->fixreg[i];
  630. tf->lr = regs->lr;
  631. tf->cr = regs->cr;
  632. tf->xer = regs->xer;
  633. tf->ctr = regs->ctr;
  634. tf->srr0 = regs->pc;
  635. return (0);
  636. }
  637. int
  638. fill_regs32(struct thread *td, struct reg32 *regs)
  639. {
  640. struct trapframe *tf;
  641. int i;
  642. tf = td->td_frame;
  643. for (i = 0; i < 32; i++)
  644. regs->fixreg[i] = tf->fixreg[i];
  645. regs->lr = tf->lr;
  646. regs->cr = tf->cr;
  647. regs->xer = tf->xer;
  648. regs->ctr = tf->ctr;
  649. regs->pc = tf->srr0;
  650. return (0);
  651. }
  652. static int
  653. grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
  654. {
  655. mcontext_t mcp64;
  656. int i, error;
  657. error = grab_mcontext(td, &mcp64, flags);
  658. if (error != 0)
  659. return (error);
  660. mcp->mc_vers = mcp64.mc_vers;
  661. mcp->mc_flags = mcp64.mc_flags;
  662. mcp->mc_onstack = mcp64.mc_onstack;
  663. mcp->mc_len = mcp64.mc_len;
  664. memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec));
  665. memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av));
  666. for (i = 0; i < 42; i++)
  667. mcp->mc_frame[i] = mcp64.mc_frame[i];
  668. memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg));
  669. memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
  670. return (0);
  671. }
  672. static int
  673. get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
  674. {
  675. int error;
  676. error = grab_mcontext32(td, mcp, flags);
  677. if (error == 0) {
  678. PROC_LOCK(curthread->td_proc);
  679. mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
  680. PROC_UNLOCK(curthread->td_proc);
  681. }
  682. return (error);
  683. }
  684. static int
  685. set_mcontext32(struct thread *td, mcontext32_t *mcp)
  686. {
  687. mcontext_t mcp64;
  688. int i, error;
  689. mcp64.mc_vers = mcp->mc_vers;
  690. mcp64.mc_flags = mcp->mc_flags;
  691. mcp64.mc_onstack = mcp->mc_onstack;
  692. mcp64.mc_len = mcp->mc_len;
  693. memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec));
  694. memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av));
  695. for (i = 0; i < 42; i++)
  696. mcp64.mc_frame[i] = mcp->mc_frame[i];
  697. mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL);
  698. memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg));
  699. memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg));
  700. error = set_mcontext(td, &mcp64);
  701. return (error);
  702. }
  703. #endif
  704. #ifdef COMPAT_FREEBSD32
  705. int
  706. freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
  707. {
  708. ucontext32_t uc;
  709. int error;
  710. CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
  711. if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
  712. CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
  713. return (EFAULT);
  714. }
  715. error = set_mcontext32(td, &uc.uc_mcontext);
  716. if (error != 0)
  717. return (error);
  718. /*
  719. * Save FPU state if needed. User may have changed it on
  720. * signal handler
  721. */
  722. if (uc.uc_mcontext.mc_srr1 & PSL_FP)
  723. save_fpu(td);
  724. kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
  725. CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
  726. td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
  727. return (EJUSTRETURN);
  728. }
  729. /*
  730. * The first two fields of a ucontext_t are the signal mask and the machine
  731. * context. The next field is uc_link; we want to avoid destroying the link
  732. * when copying out contexts.
  733. */
  734. #define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link)
  735. int
  736. freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
  737. {
  738. ucontext32_t uc;
  739. int ret;
  740. if (uap->ucp == NULL)
  741. ret = EINVAL;
  742. else {
  743. bzero(&uc, sizeof(uc));
  744. get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  745. PROC_LOCK(td->td_proc);
  746. uc.uc_sigmask = td->td_sigmask;
  747. PROC_UNLOCK(td->td_proc);
  748. ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
  749. }
  750. return (ret);
  751. }
  752. int
  753. freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
  754. {
  755. ucontext32_t uc;
  756. int ret;
  757. if (uap->ucp == NULL)
  758. ret = EINVAL;
  759. else {
  760. ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
  761. if (ret == 0) {
  762. ret = set_mcontext32(td, &uc.uc_mcontext);
  763. if (ret == 0) {
  764. kern_sigprocmask(td, SIG_SETMASK,
  765. &uc.uc_sigmask, NULL, 0);
  766. }
  767. }
  768. }
  769. return (ret == 0 ? EJUSTRETURN : ret);
  770. }
  771. int
  772. freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
  773. {
  774. ucontext32_t uc;
  775. int ret;
  776. if (uap->oucp == NULL || uap->ucp == NULL)
  777. ret = EINVAL;
  778. else {
  779. bzero(&uc, sizeof(uc));
  780. get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  781. PROC_LOCK(td->td_proc);
  782. uc.uc_sigmask = td->td_sigmask;
  783. PROC_UNLOCK(td->td_proc);
  784. ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
  785. if (ret == 0) {
  786. ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
  787. if (ret == 0) {
  788. ret = set_mcontext32(td, &uc.uc_mcontext);
  789. if (ret == 0) {
  790. kern_sigprocmask(td, SIG_SETMASK,
  791. &uc.uc_sigmask, NULL, 0);
  792. }
  793. }
  794. }
  795. }
  796. return (ret == 0 ? EJUSTRETURN : ret);
  797. }
  798. #endif
  799. void
  800. cpu_set_syscall_retval(struct thread *td, int error)
  801. {
  802. struct proc *p;
  803. struct trapframe *tf;
  804. int fixup;
  805. if (error == EJUSTRETURN)
  806. return;
  807. p = td->td_proc;
  808. tf = td->td_frame;
  809. if (tf->fixreg[0] == SYS___syscall &&
  810. (SV_PROC_FLAG(p, SV_ILP32))) {
  811. int code = tf->fixreg[FIRSTARG + 1];
  812. fixup = (
  813. #if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek)
  814. code != SYS_freebsd6_lseek &&
  815. #endif
  816. code != SYS_lseek) ? 1 : 0;
  817. } else
  818. fixup = 0;
  819. switch (error) {
  820. case 0:
  821. if (fixup) {
  822. /*
  823. * 64-bit return, 32-bit syscall. Fixup byte order
  824. */
  825. tf->fixreg[FIRSTARG] = 0;
  826. tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
  827. } else {
  828. tf->fixreg[FIRSTARG] = td->td_retval[0];
  829. tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
  830. }
  831. tf->cr &= ~0x10000000; /* Unset summary overflow */
  832. break;
  833. case ERESTART:
  834. /*
  835. * Set user's pc back to redo the system call.
  836. */
  837. tf->srr0 -= 4;
  838. break;
  839. default:
  840. tf->fixreg[FIRSTARG] = error;
  841. tf->cr |= 0x10000000; /* Set summary overflow */
  842. break;
  843. }
  844. }
  845. /*
  846. * Threading functions
  847. */
  848. void
  849. cpu_thread_exit(struct thread *td)
  850. {
  851. cleanup_power_extras(td);
  852. }
  853. void
  854. cpu_thread_clean(struct thread *td)
  855. {
  856. }
  857. void
  858. cpu_thread_alloc(struct thread *td)
  859. {
  860. struct pcb *pcb;
  861. pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
  862. sizeof(struct pcb)) & ~0x2fUL);
  863. td->td_pcb = pcb;
  864. td->td_frame = (struct trapframe *)pcb - 1;
  865. }
  866. void
  867. cpu_thread_free(struct thread *td)
  868. {
  869. }
  870. int
  871. cpu_set_user_tls(struct thread *td, void *tls_base)
  872. {
  873. if (SV_PROC_FLAG(td->td_proc, SV_LP64))
  874. td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010;
  875. else
  876. td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
  877. return (0);
  878. }
  879. void
  880. cpu_copy_thread(struct thread *td, struct thread *td0)
  881. {
  882. struct pcb *pcb2;
  883. struct trapframe *tf;
  884. struct callframe *cf;
  885. pcb2 = td->td_pcb;
  886. /* Copy the upcall pcb */
  887. bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
  888. /* Create a stack for the new thread */
  889. tf = td->td_frame;
  890. bcopy(td0->td_frame, tf, sizeof(struct trapframe));
  891. tf->fixreg[FIRSTARG] = 0;
  892. tf->fixreg[FIRSTARG + 1] = 0;
  893. tf->cr &= ~0x10000000;
  894. /* Set registers for trampoline to user mode. */
  895. cf = (struct callframe *)tf - 1;
  896. memset(cf, 0, sizeof(struct callframe));
  897. cf->cf_func = (register_t)fork_return;
  898. cf->cf_arg0 = (register_t)td;
  899. cf->cf_arg1 = (register_t)tf;
  900. pcb2->pcb_sp = (register_t)cf;
  901. #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
  902. pcb2->pcb_lr = ((register_t *)fork_trampoline)[0];
  903. pcb2->pcb_toc = ((register_t *)fork_trampoline)[1];
  904. #else
  905. pcb2->pcb_lr = (register_t)fork_trampoline;
  906. pcb2->pcb_context[0] = pcb2->pcb_lr;
  907. #endif
  908. pcb2->pcb_cpu.aim.usr_vsid = 0;
  909. #ifdef __SPE__
  910. pcb2->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE |
  911. SPEFSCR_FUNFE | SPEFSCR_FOVFE;
  912. #endif
  913. /* Setup to release spin count in fork_exit(). */
  914. td->td_md.md_spinlock_count = 1;
  915. td->td_md.md_saved_msr = psl_kernset;
  916. }
  917. void
  918. cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
  919. stack_t *stack)
  920. {
  921. struct trapframe *tf;
  922. uintptr_t sp;
  923. tf = td->td_frame;
  924. /* align stack and alloc space for frame ptr and saved LR */
  925. #ifdef __powerpc64__
  926. sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) &
  927. ~0x1f;
  928. #else
  929. sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) &
  930. ~0x1f;
  931. #endif
  932. bzero(tf, sizeof(struct trapframe));
  933. tf->fixreg[1] = (register_t)sp;
  934. tf->fixreg[3] = (register_t)arg;
  935. if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
  936. tf->srr0 = (register_t)entry;
  937. #ifdef __powerpc64__
  938. tf->srr1 = psl_userset32 | PSL_FE_DFLT;
  939. #else
  940. tf->srr1 = psl_userset | PSL_FE_DFLT;
  941. #endif
  942. } else {
  943. #ifdef __powerpc64__
  944. if (td->td_proc->p_sysent == &elf64_freebsd_sysvec_v2) {
  945. tf->srr0 = (register_t)entry;
  946. /* ELFv2 ABI requires that the global entry point be in r12. */
  947. tf->fixreg[12] = (register_t)entry;
  948. }
  949. else {
  950. register_t entry_desc[3];
  951. (void)copyin((void *)entry, entry_desc, sizeof(entry_desc));
  952. tf->srr0 = entry_desc[0];
  953. tf->fixreg[2] = entry_desc[1];
  954. tf->fixreg[11] = entry_desc[2];
  955. }
  956. tf->srr1 = psl_userset | PSL_FE_DFLT;
  957. #endif
  958. }
  959. td->td_pcb->pcb_flags = 0;
  960. #ifdef __SPE__
  961. td->td_pcb->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE |
  962. SPEFSCR_FUNFE | SPEFSCR_FOVFE;
  963. #endif
  964. td->td_retval[0] = (register_t)entry;
  965. td->td_retval[1] = 0;
  966. }
  967. static int
  968. emulate_mfspr(int spr, int reg, struct trapframe *frame){
  969. struct thread *td;
  970. td = curthread;
  971. if (spr == SPR_DSCR || spr == SPR_DSCRP) {
  972. if (!(cpu_features2 & PPC_FEATURE2_DSCR))
  973. return (SIGILL);
  974. // If DSCR was never set, get the default DSCR
  975. if ((td->td_pcb->pcb_flags & PCB_CDSCR) == 0)
  976. td->td_pcb->pcb_dscr = mfspr(SPR_DSCRP);
  977. frame->fixreg[reg] = td->td_pcb->pcb_dscr;
  978. frame->srr0 += 4;
  979. return (0);
  980. } else
  981. return (SIGILL);
  982. }
  983. static int
  984. emulate_mtspr(int spr, int reg, struct trapframe *frame){
  985. struct thread *td;
  986. td = curthread;
  987. if (spr == SPR_DSCR || spr == SPR_DSCRP) {
  988. if (!(cpu_features2 & PPC_FEATURE2_DSCR))
  989. return (SIGILL);
  990. td->td_pcb->pcb_flags |= PCB_CDSCR;
  991. td->td_pcb->pcb_dscr = frame->fixreg[reg];
  992. mtspr(SPR_DSCRP, frame->fixreg[reg]);
  993. frame->srr0 += 4;
  994. return (0);
  995. } else
  996. return (SIGILL);
  997. }
  998. #define XFX 0xFC0007FF
  999. int
  1000. ppc_instr_emulate(struct trapframe *frame, struct thread *td)
  1001. {
  1002. struct pcb *pcb;
  1003. uint32_t instr;
  1004. int reg, sig;
  1005. int rs, spr;
  1006. instr = fuword32((void *)frame->srr0);
  1007. sig = SIGILL;
  1008. if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */
  1009. reg = (instr & ~0xfc1fffff) >> 21;
  1010. frame->fixreg[reg] = mfpvr();
  1011. frame->srr0 += 4;
  1012. return (0);
  1013. } else if ((instr & XFX) == 0x7c0002a6) { /* mfspr */
  1014. rs = (instr & 0x3e00000) >> 21;
  1015. spr = (instr & 0x1ff800) >> 16;
  1016. return emulate_mfspr(spr, rs, frame);
  1017. } else if ((instr & XFX) == 0x7c0003a6) { /* mtspr */
  1018. rs = (instr & 0x3e00000) >> 21;
  1019. spr = (instr & 0x1ff800) >> 16;
  1020. return emulate_mtspr(spr, rs, frame);
  1021. } else if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */
  1022. powerpc_sync(); /* Do a heavy-weight sync */
  1023. frame->srr0 += 4;
  1024. return (0);
  1025. }
  1026. pcb = td->td_pcb;
  1027. #ifdef FPU_EMU
  1028. if (!(pcb->pcb_flags & PCB_FPREGS)) {
  1029. bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
  1030. pcb->pcb_flags |= PCB_FPREGS;
  1031. } else if (pcb->pcb_flags & PCB_FPU)
  1032. save_fpu(td);
  1033. sig = fpu_emulate(frame, &pcb->pcb_fpu);
  1034. if ((sig == 0 || sig == SIGFPE) && pcb->pcb_flags & PCB_FPU)
  1035. enable_fpu(td);
  1036. #endif
  1037. if (sig == SIGILL) {
  1038. if (pcb->pcb_lastill != frame->srr0) {
  1039. /* Allow a second chance, in case of cache sync issues. */
  1040. sig = 0;
  1041. pmap_sync_icache(PCPU_GET(curpmap), frame->srr0, 4);
  1042. pcb->pcb_lastill = frame->srr0;
  1043. }
  1044. }
  1045. return (sig);
  1046. }