From owner-svn-src-user@FreeBSD.ORG Wed Jul 7 12:04:57 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 873271065670; Wed, 7 Jul 2010 12:04:57 +0000 (UTC) (envelope-from jmallett@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 766468FC1F; Wed, 7 Jul 2010 12:04:57 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o67C4vuT084116; Wed, 7 Jul 2010 12:04:57 GMT (envelope-from jmallett@svn.freebsd.org) Received: (from jmallett@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o67C4v6Q084114; Wed, 7 Jul 2010 12:04:57 GMT (envelope-from jmallett@svn.freebsd.org) Message-Id: <201007071204.o67C4v6Q084114@svn.freebsd.org> From: Juli Mallett Date: Wed, 7 Jul 2010 12:04:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r209762 - user/jmallett/octeon/sys/mips/mips X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Jul 2010 12:04:57 -0000 Author: jmallett Date: Wed Jul 7 12:04:56 2010 New Revision: 209762 URL: http://svn.freebsd.org/changeset/base/209762 Log: Simplify code some and correct a few bugs and omissions related to unaligned accesses. There still seems to be something not quite right here, but this should fix problems related to useracc failing when the access could have been fixed up (due to always assuming word access width in useracc even for halfword unaligned accesses), as well as providing unaligned ld/sd fixup. Modified: user/jmallett/octeon/sys/mips/mips/trap.c Modified: user/jmallett/octeon/sys/mips/mips/trap.c ============================================================================== --- user/jmallett/octeon/sys/mips/mips/trap.c Wed Jul 7 12:00:11 2010 (r209761) +++ user/jmallett/octeon/sys/mips/mips/trap.c Wed Jul 7 12:04:56 2010 (r209762) @@ -259,7 +259,7 @@ static int allow_unaligned_acc = 1; SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW, &allow_unaligned_acc, 0, "Allow unaligned accesses"); -static int emulate_unaligned_access(struct trapframe *frame); +static int emulate_unaligned_access(struct trapframe *frame, int mode); extern void fswintrberr(void); /* XXX */ @@ -563,21 +563,9 @@ dofault: else mode = VM_PROT_WRITE; - /* - * ADDR_ERR faults have higher priority than TLB - * Miss faults. Therefore, it is necessary to - * verify that the faulting address is a valid - * virtual address within the process' address space - * before trying to emulate the unaligned access. - */ - if (useracc((caddr_t) - (((vm_offset_t)trapframe->badvaddr) & - ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) { - access_type = emulate_unaligned_access( - trapframe); - if (access_type != 0) - goto out; - } + access_type = emulate_unaligned_access(trapframe, mode); + if (access_type != 0) + goto out; } msg = "ADDRESS_ERR"; @@ -949,22 +937,9 @@ dofault: else mode = VM_PROT_WRITE; - /* - * ADDR_ERR faults have higher priority than TLB - * Miss faults. Therefore, it is necessary to - * verify that the faulting address is a valid - * virtual address within the process' address space - * before trying to emulate the unaligned access. - */ - if (useracc((caddr_t) - (((vm_offset_t)trapframe->badvaddr) & - ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) { - access_type = emulate_unaligned_access( - trapframe); - if (access_type != 0) { - return (trapframe->pc); - } - } + access_type = emulate_unaligned_access(trapframe, mode); + if (access_type != 0) + return (trapframe->pc); } /* FALLTHROUGH */ @@ -1429,76 +1404,120 @@ log_bad_page_fault(char *msg, struct tra * Unaligned load/store emulation */ static int -mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc) +mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc) { register_t *reg = (register_t *) frame; u_int32_t inst = *((u_int32_t *)(intptr_t)pc); - u_int32_t value_msb, value; - int access_type = 0; + register_t value_msb, value; + unsigned size; + + /* + * ADDR_ERR faults have higher priority than TLB + * Miss faults. Therefore, it is necessary to + * verify that the faulting address is a valid + * virtual address within the process' address space + * before trying to emulate the unaligned access. + */ + switch (MIPS_INST_OPCODE(inst)) { + case OP_LHU: case OP_LH: + case OP_SH: + size = 2; + break; + case OP_LWU: case OP_LW: + case OP_SW: + size = 4; + break; + case OP_LD: + case OP_SD: + size = 8; + break; + default: + printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst)); + return (0); + } + if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode)) + return (0); + + /* + * XXX + * Handle LL/SC LLD/SCD. + */ switch (MIPS_INST_OPCODE(inst)) { case OP_LHU: + KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); lbu_macro(value_msb, addr); addr += 1; lbu_macro(value, addr); value |= value_msb << 8; reg[MIPS_INST_RT(inst)] = value; - access_type = MIPS_LHU_ACCESS; - break; + return (MIPS_LHU_ACCESS); case OP_LH: + KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); lb_macro(value_msb, addr); addr += 1; lbu_macro(value, addr); value |= value_msb << 8; reg[MIPS_INST_RT(inst)] = value; - access_type = MIPS_LH_ACCESS; - break; + return (MIPS_LH_ACCESS); case OP_LWU: + KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); lwl_macro(value, addr); addr += 3; lwr_macro(value, addr); value &= 0xffffffff; reg[MIPS_INST_RT(inst)] = value; - access_type = MIPS_LWU_ACCESS; - break; + return (MIPS_LWU_ACCESS); case OP_LW: + KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); lwl_macro(value, addr); addr += 3; lwr_macro(value, addr); reg[MIPS_INST_RT(inst)] = value; - access_type = MIPS_LW_ACCESS; - break; + return (MIPS_LW_ACCESS); + + case OP_LD: + KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); + ldl_macro(value, addr); + addr += 7; + ldr_macro(value, addr); + reg[MIPS_INST_RT(inst)] = value; + return (MIPS_LD_ACCESS); case OP_SH: + KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction.")); value = reg[MIPS_INST_RT(inst)]; value_msb = value >> 8; sb_macro(value_msb, addr); addr += 1; sb_macro(value, addr); - access_type = MIPS_SH_ACCESS; - break; + return (MIPS_SH_ACCESS); case OP_SW: + KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction.")); value = reg[MIPS_INST_RT(inst)]; swl_macro(value, addr); addr += 3; swr_macro(value, addr); - access_type = MIPS_SW_ACCESS; - break; + return (MIPS_SW_ACCESS); - default: - break; + case OP_SD: + KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction.")); + value = reg[MIPS_INST_RT(inst)]; + sdl_macro(value, addr); + addr += 7; + sdr_macro(value, addr); + return (MIPS_SD_ACCESS); } - - return access_type; + panic("%s: should not be reached.", __func__); } static int -emulate_unaligned_access(struct trapframe *frame) +emulate_unaligned_access(struct trapframe *frame, int mode) { register_t pc; int access_type = 0; @@ -1519,7 +1538,7 @@ emulate_unaligned_access(struct trapfram * Otherwise restore pc and fall through. */ access_type = mips_unaligned_load_store(frame, - frame->badvaddr, pc); + mode, frame->badvaddr, pc); if (access_type) { if (DELAYBRANCH(frame->cause))