1 /* $NetBSD: fault.c,v 1.19 2002/05/25 07:58:35 ichiro Exp $ */ 2 3 /* 4 * Copyright (c) 1994-1997 Mark Brinicombe. 5 * Copyright (c) 1994 Brini. 6 * All rights reserved. 7 * 8 * This code is derived from software written for Brini by Mark Brinicombe 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Brini. 21 * 4. The name of the company nor the name of the author may be used to 22 * endorse or promote products derived from this software without specific 23 * prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * RiscBSD kernel project 38 * 39 * fault.c 40 * 41 * Fault handlers 42 * 43 * Created : 28/11/94 44 */ 45 46 #include "opt_ddb.h" 47 #include "opt_pmap_debug.h" 48 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/proc.h> 53 #include <sys/user.h> 54 #include <sys/kernel.h> 55 56 #include <uvm/uvm_extern.h> 57 58 #include <arm/cpuconf.h> 59 60 #include <machine/frame.h> 61 #include <arm/arm32/katelib.h> 62 #include <machine/cpu.h> 63 #include <machine/intr.h> 64 #ifdef DDB 65 #include <machine/db_machdep.h> 66 #endif 67 68 #include <arch/arm/arm/disassem.h> 69 #include <arm/arm32/machdep.h> 70 71 int cowfault __P((vaddr_t)); 72 extern char fusubailout[]; 73 74 static void report_abort __P((const char *, u_int, u_int, u_int)); 75 76 /* Abort code */ 77 78 /* Define text descriptions of the different aborts */ 79 80 static const char *aborts[16] = { 81 "Write buffer fault", 82 "Alignment fault", 83 "Write buffer fault", 84 "Alignment fault", 85 "Bus error (LF section)", 86 "Translation fault (section)", 87 "Bus error (page)", 88 "Translation fault (page)", 89 "Bus error (section)", 90 "Domain error (section)", 91 "Bus error (page)", 92 "Domain error (page)", 93 "Bus error trans (L1)", 94 "Permission error (section)", 95 "Bus error trans (L2)", 96 "Permission error (page)" 97 }; 98 99 static void 100 report_abort(prefix, fault_status, fault_address, fault_pc) 101 const char *prefix; 102 u_int fault_status; 103 u_int fault_address; 104 u_int fault_pc; 105 { 106 #ifndef DEBUG 107 if (prefix == NULL) { 108 #endif 109 if (prefix) 110 printf("%s ", prefix); 111 printf("Data abort: '%s' status=%03x address=%08x PC=%08x\n", 112 aborts[fault_status & FAULT_TYPE_MASK], 113 fault_status & 0xfff, fault_address, fault_pc); 114 #ifndef DEBUG 115 } 116 #endif 117 } 118 119 static __volatile int data_abort_expected; 120 static __volatile int data_abort_received; 121 122 int 123 badaddr_read(void *addr, size_t size, void *rptr) 124 { 125 u_long rcpt; 126 int rv; 127 128 /* Tell the Data Abort handler that we're expecting one. */ 129 data_abort_received = 0; 130 data_abort_expected = 1; 131 132 cpu_drain_writebuf(); 133 134 /* Read from the test address. */ 135 switch (size) { 136 case sizeof(uint8_t): 137 __asm __volatile("ldrb %0, [%1]" 138 : "=r" (rcpt) 139 : "r" (addr)); 140 break; 141 142 case sizeof(uint16_t): 143 __asm __volatile("ldrh %0, [%1]" 144 : "=r" (rcpt) 145 : "r" (addr)); 146 break; 147 148 case sizeof(uint32_t): 149 __asm __volatile("ldr %0, [%1]" 150 : "=r" (rcpt) 151 : "r" (addr)); 152 break; 153 154 default: 155 data_abort_expected = 0; 156 panic("badaddr: invalid size (%lu)\n", (u_long) size); 157 } 158 159 /* Disallow further Data Aborts. */ 160 data_abort_expected = 0; 161 162 rv = data_abort_received; 163 data_abort_received = 0; 164 165 /* Copy the data back if no fault occurred. */ 166 if (rptr != NULL && rv == 0) { 167 switch (size) { 168 case sizeof(uint8_t): 169 *(uint8_t *) rptr = rcpt; 170 break; 171 172 case sizeof(uint16_t): 173 *(uint16_t *) rptr = rcpt; 174 break; 175 176 case sizeof(uint32_t): 177 *(uint32_t *) rptr = rcpt; 178 break; 179 } 180 } 181 182 /* Return true if the address was invalid. */ 183 return (rv); 184 } 185 186 /* 187 * void data_abort_handler(trapframe_t *frame) 188 * 189 * Abort handler called when read/write occurs at an address of 190 * a non existent or restricted (access permissions) memory page. 191 * We first need to identify the type of page fault. 192 */ 193 194 #define TRAP_CODE ((fault_status & 0x0f) | (fault_address & 0xfffffff0)) 195 196 void 197 data_abort_handler(frame) 198 trapframe_t *frame; 199 { 200 struct proc *p; 201 struct pcb *pcb; 202 u_int fault_address; 203 u_int fault_status; 204 u_int fault_pc; 205 u_int fault_instruction; 206 int fault_code; 207 int user; 208 int error; 209 void *onfault; 210 211 /* 212 * If we were expecting a Data Abort, signal that we got 213 * one, adjust the PC to skip the faulting insn, and 214 * return. 215 */ 216 if (data_abort_expected) { 217 data_abort_received = 1; 218 frame->tf_pc += INSN_SIZE; 219 return; 220 } 221 222 /* 223 * Must get fault address and status from the CPU before 224 * re-enabling interrupts. (Interrupt handlers may take 225 * R/M emulation faults.) 226 */ 227 fault_address = cpu_faultaddress(); 228 fault_status = cpu_faultstatus(); 229 fault_pc = frame->tf_pc; 230 231 /* 232 * Enable IRQ's (disabled by CPU on abort) if trapframe 233 * shows they were enabled. 234 */ 235 if (!(frame->tf_spsr & I32_bit)) 236 enable_interrupts(I32_bit); 237 238 #ifdef DEBUG 239 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) 240 panic("data_abort_handler: not in SVC32 mode"); 241 #endif 242 243 /* Update vmmeter statistics */ 244 uvmexp.traps++; 245 246 /* Extract the fault code from the fault status */ 247 fault_code = fault_status & FAULT_TYPE_MASK; 248 249 /* Get the current proc structure or proc0 if there is none */ 250 if ((p = curproc) == NULL) 251 p = &proc0; 252 253 /* 254 * can't use curpcb, as it might be NULL; and we have p in 255 * a register anyway 256 */ 257 pcb = &p->p_addr->u_pcb; 258 259 /* fusubailout is used by [fs]uswintr to avoid page faulting */ 260 if (pcb->pcb_onfault 261 && ((fault_code != FAULT_TRANS_S && fault_code != FAULT_TRANS_P && 262 fault_code != FAULT_PERM_S && fault_code != FAULT_PERM_P) 263 || pcb->pcb_onfault == fusubailout)) { 264 265 copyfault: 266 #ifdef DEBUG 267 printf("Using pcb_onfault=%p addr=%08x st=%08x p=%p\n", 268 pcb->pcb_onfault, fault_address, fault_status, p); 269 #endif 270 frame->tf_pc = (u_int)pcb->pcb_onfault; 271 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) 272 panic("Yikes pcb_onfault=%p during USR mode fault\n", 273 pcb->pcb_onfault); 274 return; 275 } 276 277 /* More debug stuff */ 278 279 fault_instruction = ReadWord(fault_pc); 280 281 #ifdef PMAP_DEBUG 282 if (pmap_debug_level >= 0) { 283 report_abort(NULL, fault_status, fault_address, fault_pc); 284 printf("Instruction @V%08x = %08x\n", 285 fault_pc, fault_instruction); 286 } 287 #endif 288 289 /* Call the cpu specific abort fixup routine */ 290 error = cpu_dataabt_fixup(frame); 291 if (error == ABORT_FIXUP_RETURN) 292 return; 293 if (error == ABORT_FIXUP_FAILED) { 294 printf("pc = 0x%08x, opcode 0x%08x, insn = ", fault_pc, *((u_int *)fault_pc)); 295 disassemble(fault_pc); 296 printf("data abort handler: fixup failed for this instruction\n"); 297 } 298 299 #ifdef PMAP_DEBUG 300 if (pmap_debug_level >= 0) 301 printf("fault in process %p\n", p); 302 #endif 303 304 #ifdef DEBUG 305 /* Is this needed ? */ 306 if (pcb != curpcb) { 307 printf("data_abort: Alert ! pcb(%p) != curpcb(%p)\n", 308 pcb, curpcb); 309 printf("data_abort: Alert ! proc(%p), curproc(%p)\n", 310 p, curproc); 311 } 312 #endif /* DEBUG */ 313 314 /* Were we in user mode when the abort occurred ? */ 315 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) { 316 /* 317 * Note that the fault was from USR mode. 318 */ 319 user = 1; 320 p->p_addr->u_pcb.pcb_tf = frame; 321 } else 322 user = 0; 323 324 /* check if this was a failed fixup */ 325 if (error == ABORT_FIXUP_FAILED) { 326 if (user) { 327 trapsignal(p, SIGSEGV, TRAP_CODE); 328 userret(p); 329 return; 330 }; 331 panic("Data abort fixup failed in kernel - we're dead\n"); 332 }; 333 334 /* Now act on the fault type */ 335 switch (fault_code) { 336 case FAULT_WRTBUF_0: /* Write Buffer Fault */ 337 case FAULT_WRTBUF_1: /* Write Buffer Fault */ 338 /* If this happens forget it no point in continuing */ 339 340 /* FALLTHROUGH */ 341 342 case FAULT_ALIGN_0: /* Alignment Fault */ 343 case FAULT_ALIGN_1: /* Alignment Fault */ 344 /* 345 * Really this should just kill the process. 346 * Alignment faults are turned off in the kernel 347 * in order to get better performance from shorts with 348 * GCC so an alignment fault means somebody has played 349 * with the control register in the CPU. Might as well 350 * panic as the kernel was not compiled for aligned accesses. 351 */ 352 353 /* FALLTHROUGH */ 354 355 case FAULT_BUSERR_0: /* Bus Error LF Section */ 356 case FAULT_BUSERR_1: /* Bus Error Page */ 357 case FAULT_BUSERR_2: /* Bus Error Section */ 358 case FAULT_BUSERR_3: /* Bus Error Page */ 359 /* What will accutally cause a bus error ? */ 360 /* Real bus errors are not a process problem but hardware */ 361 362 /* FALLTHROUGH */ 363 364 case FAULT_DOMAIN_S: /* Section Domain Error Fault */ 365 case FAULT_DOMAIN_P: /* Page Domain Error Fault*/ 366 /* 367 * Right well we dont use domains, everything is 368 * always a client and thus subject to access permissions. 369 * If we get a domain error then we have corrupts PTE's 370 * so we might as well die ! 371 * I suppose eventually this should just kill the process 372 * who owns the PTE's but if this happens it implies a 373 * kernel problem. 374 */ 375 376 /* FALLTHROUGH */ 377 378 case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */ 379 case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */ 380 /* 381 * These faults imply that the PTE is corrupt. 382 * Likely to be a kernel fault so we had better stop. 383 */ 384 385 /* FALLTHROUGH */ 386 387 default : 388 /* Are there any combinations I have missed ? */ 389 report_abort(NULL, fault_status, fault_address, fault_pc); 390 391 we_re_toast: 392 /* 393 * Were are dead, try and provide some debug 394 * information before dying. 395 */ 396 #ifdef DDB 397 printf("Unhandled trap (frame = %p)\n", frame); 398 report_abort(NULL, fault_status, fault_address, fault_pc); 399 kdb_trap(-1, frame); 400 return; 401 #else 402 panic("Unhandled trap (frame = %p)", frame); 403 #endif /* DDB */ 404 405 case FAULT_TRANS_P: /* Page Translation Fault */ 406 case FAULT_PERM_P: /* Page Permission Fault */ 407 case FAULT_TRANS_S: /* Section Translation Fault */ 408 case FAULT_PERM_S: /* Section Permission Fault */ 409 /* 410 * Page/section translation/permission fault -- need to fault in 411 * the page and possibly the page table page. 412 */ 413 { 414 register vaddr_t va; 415 register struct vmspace *vm = p->p_vmspace; 416 register struct vm_map *map; 417 int rv; 418 vm_prot_t ftype; 419 extern struct vm_map *kernel_map; 420 421 va = trunc_page((vaddr_t)fault_address); 422 423 #ifdef PMAP_DEBUG 424 if (pmap_debug_level >= 0) 425 printf("page fault: addr=V%08lx ", va); 426 #endif 427 428 /* 429 * It is only a kernel address space fault iff: 430 * 1. user == 0 and 431 * 2. pcb_onfault not set or 432 * 3. pcb_onfault set but supervisor space fault 433 * The last can occur during an exec() copyin where the 434 * argument space is lazy-allocated. 435 */ 436 if (!user && 437 (va >= VM_MIN_KERNEL_ADDRESS || va < VM_MIN_ADDRESS)) { 438 /* Was the fault due to the FPE/IPKDB ? */ 439 if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) { 440 report_abort("UND32", fault_status, 441 fault_address, fault_pc); 442 trapsignal(p, SIGSEGV, TRAP_CODE); 443 444 /* 445 * Force exit via userret() 446 * This is necessary as the FPE is an extension 447 * to userland that actually runs in a 448 * priveledged mode but uses USR mode 449 * permissions for its accesses. 450 */ 451 userret(p); 452 return; 453 } 454 map = kernel_map; 455 } else 456 map = &vm->vm_map; 457 458 #ifdef PMAP_DEBUG 459 if (pmap_debug_level >= 0) 460 printf("vmmap=%p ", map); 461 #endif 462 463 if (map == NULL) 464 panic("No map for fault address va = 0x%08lx", va); 465 466 /* 467 * We need to know whether the page should be mapped 468 * as R or R/W. The MMU does not give us the info as 469 * to whether the fault was caused by a read or a write. 470 * This means we need to disassemble the instruction 471 * responsible and determine if it was a read or write 472 * instruction. 473 */ 474 /* STR instruction ? */ 475 if ((fault_instruction & 0x0c100000) == 0x04000000) 476 ftype = VM_PROT_WRITE; 477 /* STM or CDT instruction ? */ 478 else if ((fault_instruction & 0x0a100000) == 0x08000000) 479 ftype = VM_PROT_WRITE; 480 /* STRH, STRSH or STRSB instruction ? */ 481 else if ((fault_instruction & 0x0e100090) == 0x00000090) 482 ftype = VM_PROT_WRITE; 483 /* SWP instruction ? */ 484 else if ((fault_instruction & 0x0fb00ff0) == 0x01000090) 485 ftype = VM_PROT_READ | VM_PROT_WRITE; 486 else 487 ftype = VM_PROT_READ; 488 489 #ifdef PMAP_DEBUG 490 if (pmap_debug_level >= 0) 491 printf("fault protection = %d\n", ftype); 492 #endif 493 494 if ((ftype & VM_PROT_WRITE) ? 495 pmap_modified_emulation(map->pmap, va) : 496 pmap_handled_emulation(map->pmap, va)) 497 goto out; 498 499 if (current_intr_depth > 0) { 500 #ifdef DDB 501 printf("Non-emulated page fault with intr_depth > 0\n"); 502 report_abort(NULL, fault_status, fault_address, fault_pc); 503 kdb_trap(-1, frame); 504 return; 505 #else 506 panic("Fault with intr_depth > 0"); 507 #endif /* DDB */ 508 } 509 510 onfault = pcb->pcb_onfault; 511 pcb->pcb_onfault = NULL; 512 rv = uvm_fault(map, va, 0, ftype); 513 pcb->pcb_onfault = onfault; 514 if (rv == 0) 515 goto out; 516 517 if (user == 0) { 518 if (pcb->pcb_onfault) 519 goto copyfault; 520 printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n", 521 map, va, ftype, rv); 522 goto we_re_toast; 523 } 524 525 report_abort("", fault_status, fault_address, fault_pc); 526 if (rv == ENOMEM) { 527 printf("UVM: pid %d (%s), uid %d killed: " 528 "out of swap\n", p->p_pid, p->p_comm, 529 p->p_cred && p->p_ucred ? 530 p->p_ucred->cr_uid : -1); 531 trapsignal(p, SIGKILL, TRAP_CODE); 532 } else 533 trapsignal(p, SIGSEGV, TRAP_CODE); 534 break; 535 } 536 } 537 538 out: 539 /* Call userret() if it was a USR mode fault */ 540 if (user) 541 userret(p); 542 } 543 544 545 /* 546 * void prefetch_abort_handler(trapframe_t *frame) 547 * 548 * Abort handler called when instruction execution occurs at 549 * a non existent or restricted (access permissions) memory page. 550 * If the address is invalid and we were in SVC mode then panic as 551 * the kernel should never prefetch abort. 552 * If the address is invalid and the page is mapped then the user process 553 * does no have read permission so send it a signal. 554 * Otherwise fault the page in and try again. 555 */ 556 557 extern int kernel_debug; 558 559 void 560 prefetch_abort_handler(frame) 561 trapframe_t *frame; 562 { 563 struct proc *p; 564 struct vm_map *map; 565 vaddr_t fault_pc, va; 566 int error; 567 568 /* 569 * Enable IRQ's (disabled by the abort) This always comes 570 * from user mode so we know interrupts were not disabled. 571 * But we check anyway. 572 */ 573 if (!(frame->tf_spsr & I32_bit)) 574 enable_interrupts(I32_bit); 575 576 #ifdef DEBUG 577 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) 578 panic("prefetch_abort_handler: not in SVC32 mode"); 579 #endif 580 581 /* Update vmmeter statistics */ 582 uvmexp.traps++; 583 584 /* Call the cpu specific abort fixup routine */ 585 error = cpu_prefetchabt_fixup(frame); 586 if (error == ABORT_FIXUP_RETURN) 587 return; 588 if (error == ABORT_FIXUP_FAILED) 589 panic("prefetch abort fixup failed\n"); 590 591 /* Get the current proc structure or proc0 if there is none */ 592 if ((p = curproc) == 0) { 593 p = &proc0; 594 #ifdef DEBUG 595 printf("Prefetch abort with curproc == 0\n"); 596 #endif 597 } 598 599 #ifdef PMAP_DEBUG 600 if (pmap_debug_level >= 0) 601 printf("prefetch fault in process %p %s\n", p, p->p_comm); 602 #endif 603 604 /* Get fault address */ 605 fault_pc = frame->tf_pc; 606 va = trunc_page(fault_pc); 607 608 /* Was the prefectch abort from USR32 mode ? */ 609 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) { 610 p->p_addr->u_pcb.pcb_tf = frame; 611 } else { 612 /* 613 * All the kernel code pages are loaded at boot time 614 * and do not get paged 615 */ 616 panic("Prefetch abort in non-USR mode (frame=%p PC=0x%08lx)\n", 617 frame, fault_pc); 618 } 619 620 map = &p->p_vmspace->vm_map; 621 622 #ifdef PMAP_DEBUG 623 if (pmap_debug_level >= 0) 624 printf("prefetch_abort: PC = %08lx\n", fault_pc); 625 #endif 626 /* Ok validate the address, can only execute in USER space */ 627 if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) { 628 #ifdef DEBUG 629 printf("prefetch: pc (%08lx) not in user process space\n", 630 fault_pc); 631 #endif 632 trapsignal(p, SIGSEGV, fault_pc); 633 userret(p); 634 return; 635 } 636 637 #ifdef CPU_SA110 638 /* 639 * There are bugs in the rev K SA110. This is a check for one 640 * of them. 641 */ 642 if (curcpu()->ci_cputype == CPU_ID_SA110 && curcpu()->ci_cpurev < 3) { 643 /* Always current pmap */ 644 pt_entry_t *pte = vtopte((vaddr_t) fault_pc); 645 struct pmap *pmap = p->p_vmspace->vm_map.pmap; 646 647 if (pmap_pde_v(pmap_pde(pmap, (vaddr_t) fault_pc)) && 648 pmap_pte_v(pte)) { 649 if (kernel_debug & 1) { 650 printf("prefetch_abort: page is already " 651 "mapped - pte=%p *pte=%08x\n", pte, *pte); 652 printf("prefetch_abort: pc=%08lx proc=%p " 653 "process=%s\n", fault_pc, p, p->p_comm); 654 printf("prefetch_abort: far=%08x fs=%x\n", 655 cpu_faultaddress(), cpu_faultstatus()); 656 printf("prefetch_abort: trapframe=%08x\n", 657 (u_int)frame); 658 } 659 #ifdef DDB 660 if (kernel_debug & 2) 661 Debugger(); 662 #endif 663 } 664 } 665 #endif /* CPU_SA110 */ 666 667 if (pmap_handled_emulation(map->pmap, va)) 668 goto out; 669 670 if (current_intr_depth > 0) { 671 #ifdef DDB 672 printf("Non-emulated prefetch abort with intr_depth > 0\n"); 673 kdb_trap(-1, frame); 674 return; 675 #else 676 panic("Prefetch Abort with intr_depth > 0"); 677 #endif 678 } 679 680 error = uvm_fault(map, va, 0, VM_PROT_READ); 681 if (error == 0) 682 goto out; 683 684 if (error == ENOMEM) { 685 printf("UVM: pid %d (%s), uid %d killed: " 686 "out of swap\n", p->p_pid, p->p_comm, 687 p->p_cred && p->p_ucred ? 688 p->p_ucred->cr_uid : -1); 689 trapsignal(p, SIGKILL, fault_pc); 690 } else 691 trapsignal(p, SIGSEGV, fault_pc); 692 out: 693 userret(p); 694 } 695 696 int 697 cowfault(va) 698 vaddr_t va; 699 { 700 struct vmspace *vm; 701 int error; 702 703 if (va >= VM_MAXUSER_ADDRESS) 704 return (EFAULT); 705 706 /* uvm_fault can't be called from within an interrupt */ 707 KASSERT(current_intr_depth == 0); 708 709 vm = curproc->p_vmspace; 710 error = uvm_fault(&vm->vm_map, va, 0, VM_PROT_WRITE); 711 return error; 712 } 713