From owner-svn-src-all@freebsd.org Wed Oct 30 10:42:53 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 6C7101A1A94; Wed, 30 Oct 2019 10:42:53 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4734mF2GXVz3Dqt; Wed, 30 Oct 2019 10:42:53 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 3115791CF; Wed, 30 Oct 2019 10:42:53 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x9UAgqYo025128; Wed, 30 Oct 2019 10:42:52 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x9UAgq8w025127; Wed, 30 Oct 2019 10:42:52 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201910301042.x9UAgq8w025127@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Wed, 30 Oct 2019 10:42:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354174 - head/sys/arm64/arm64 X-SVN-Group: head X-SVN-Commit-Author: andrew X-SVN-Commit-Paths: head/sys/arm64/arm64 X-SVN-Commit-Revision: 354174 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Oct 2019 10:42:53 -0000 Author: andrew Date: Wed Oct 30 10:42:52 2019 New Revision: 354174 URL: https://svnweb.freebsd.org/changeset/base/354174 Log: Use an array of handlers in the data and instruction aborts Previously we would call data_abort on all data and instruction aborts however this is incorrect for most abort types. Move to use an array of function pointers to allow for more handlers to be easily added. Reviewed by: jhibbits Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D22170 Modified: head/sys/arm64/arm64/trap.c Modified: head/sys/arm64/arm64/trap.c ============================================================================== --- head/sys/arm64/arm64/trap.c Wed Oct 30 10:41:10 2019 (r354173) +++ head/sys/arm64/arm64/trap.c Wed Oct 30 10:42:52 2019 (r354174) @@ -84,6 +84,24 @@ static void print_registers(struct trapframe *frame); int (*dtrace_invop_jump_addr)(struct trapframe *); +typedef void (abort_handler)(struct thread *, struct trapframe *, uint64_t, + uint64_t, int); + +static abort_handler data_abort; + +static abort_handler *abort_handlers[] = { + [ISS_DATA_DFSC_TF_L0] = data_abort, + [ISS_DATA_DFSC_TF_L1] = data_abort, + [ISS_DATA_DFSC_TF_L2] = data_abort, + [ISS_DATA_DFSC_TF_L3] = data_abort, + [ISS_DATA_DFSC_AFF_L1] = data_abort, + [ISS_DATA_DFSC_AFF_L2] = data_abort, + [ISS_DATA_DFSC_AFF_L3] = data_abort, + [ISS_DATA_DFSC_PF_L1] = data_abort, + [ISS_DATA_DFSC_PF_L2] = data_abort, + [ISS_DATA_DFSC_PF_L3] = data_abort, +}; + static __inline void call_trapsignal(struct thread *td, int sig, int code, void *addr) { @@ -149,7 +167,7 @@ svc_handler(struct thread *td, struct trapframe *frame static void data_abort(struct thread *td, struct trapframe *frame, uint64_t esr, - uint64_t far, int lower, int exec) + uint64_t far, int lower) { struct vm_map *map; struct proc *p; @@ -212,11 +230,16 @@ data_abort(struct thread *td, struct trapframe *frame, panic("data abort in critical section or under mutex"); } - if (exec) + switch (ESR_ELx_EXCEPTION(esr)) { + case EXCP_INSN_ABORT: + case EXCP_INSN_ABORT_L: ftype = VM_PROT_EXECUTE; - else + break; + default: ftype = (esr & ISS_DATA_WnR) == 0 ? VM_PROT_READ : VM_PROT_READ | VM_PROT_WRITE; + break; + } /* Fault in the page. */ error = vm_fault_trap(map, far, ftype, VM_FAULT_NORMAL, &sig, &ucode); @@ -275,6 +298,7 @@ do_el1h_sync(struct thread *td, struct trapframe *fram struct trapframe *oframe; uint32_t exception; uint64_t esr, far; + int dfsc; /* Read the esr register to get the exception details */ esr = frame->tf_esr; @@ -318,8 +342,14 @@ do_el1h_sync(struct thread *td, struct trapframe *fram case EXCP_INSN_ABORT: case EXCP_DATA_ABORT: far = READ_SPECIALREG(far_el1); - data_abort(td, frame, esr, far, 0, - exception == EXCP_INSN_ABORT); + dfsc = esr & ISS_DATA_DFSC_MASK; + if (dfsc < nitems(abort_handlers) && + abort_handlers[dfsc] != NULL) + abort_handlers[dfsc](td, frame, esr, far, 0); + else + panic("Unhandled EL1 %s abort: %x", + exception == EXCP_INSN_ABORT ? "instruction" : + "data", dfsc); break; case EXCP_BRK: #ifdef KDTRACE_HOOKS @@ -365,6 +395,7 @@ do_el0_sync(struct thread *td, struct trapframe *frame pcpu_bp_harden bp_harden; uint32_t exception; uint64_t esr, far; + int dfsc; /* Check we have a sane environment when entering from userland */ KASSERT((uintptr_t)get_pcpu() >= VM_MIN_KERNEL_ADDRESS, @@ -416,8 +447,14 @@ do_el0_sync(struct thread *td, struct trapframe *frame case EXCP_INSN_ABORT_L: case EXCP_DATA_ABORT_L: case EXCP_DATA_ABORT: - data_abort(td, frame, esr, far, 1, - exception == EXCP_INSN_ABORT_L); + dfsc = esr & ISS_DATA_DFSC_MASK; + if (dfsc < nitems(abort_handlers) && + abort_handlers[dfsc] != NULL) + abort_handlers[dfsc](td, frame, esr, far, 1); + else + panic("Unhandled EL0 %s abort: %x", + exception == EXCP_INSN_ABORT_L ? "instruction" : + "data", dfsc); break; case EXCP_UNKNOWN: if (!undef_insn(0, frame))