From owner-svn-src-head@freebsd.org Wed Mar 6 02:31:14 2019 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 334F21521CBC; Wed, 6 Mar 2019 02:31:14 +0000 (UTC) (envelope-from freebsd@gndrsh.dnsmgr.net) Received: from gndrsh.dnsmgr.net (br1.CN84in.dnsmgr.net [69.59.192.140]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 879446D466; Wed, 6 Mar 2019 02:31:13 +0000 (UTC) (envelope-from freebsd@gndrsh.dnsmgr.net) Received: from gndrsh.dnsmgr.net (localhost [127.0.0.1]) by gndrsh.dnsmgr.net (8.13.3/8.13.3) with ESMTP id x262VA5Q083585; Tue, 5 Mar 2019 18:31:10 -0800 (PST) (envelope-from freebsd@gndrsh.dnsmgr.net) Received: (from freebsd@localhost) by gndrsh.dnsmgr.net (8.13.3/8.13.3/Submit) id x262V9Zn083584; Tue, 5 Mar 2019 18:31:09 -0800 (PST) (envelope-from freebsd) From: "Rodney W. Grimes" Message-Id: <201903060231.x262V9Zn083584@ gndrsh.dnsmgr.net> Subject: Re: svn commit: r344829 - head/lib/libkvm In-Reply-To: <201903052359.x25Nxtm3019756@repo.freebsd.org> To: Mark Johnston Date: Tue, 5 Mar 2019 18:31:09 -0800 (PST) CC: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Reply-To: rgrimes@freebsd.org X-Mailer: ELM [version 2.4ME+ PL121h (25)] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII X-Rspamd-Queue-Id: 879446D466 X-Spamd-Bar: ------ Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-6.97 / 15.00]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.97)[-0.968,0]; REPLY(-4.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Mar 2019 02:31:14 -0000 [ Charset UTF-8 unsupported, converting... ] > Author: markj > Date: Tue Mar 5 23:59:55 2019 > New Revision: 344829 > URL: https://svnweb.freebsd.org/changeset/base/344829 > > Log: > Add riscv minidump support to libkvm. > > Submitted by: Mitchell Horne > Differential Revision: https://reviews.freebsd.org/D19171 > > Added: > head/lib/libkvm/kvm_minidump_riscv.c (contents, props changed) > head/lib/libkvm/kvm_riscv.h (contents, props changed) > Modified: > head/lib/libkvm/Makefile > > Modified: head/lib/libkvm/Makefile > ============================================================================== > --- head/lib/libkvm/Makefile Tue Mar 5 23:58:16 2019 (r344828) > +++ head/lib/libkvm/Makefile Tue Mar 5 23:59:55 2019 (r344829) > @@ -18,6 +18,7 @@ SRCS= kvm.c kvm_cptime.c kvm_getloadavg.c \ > kvm_i386.c kvm_minidump_i386.c \ > kvm_minidump_mips.c \ > kvm_powerpc.c kvm_powerpc64.c \ > + kvm_minidump_riscv.c \ > kvm_sparc64.c > INCS= kvm.h > > > Added: head/lib/libkvm/kvm_minidump_riscv.c > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/lib/libkvm/kvm_minidump_riscv.c Tue Mar 5 23:59:55 2019 (r344829) > @@ -0,0 +1,288 @@ > +/*- > + * Copyright (c) 2006 Peter Wemm > + * Copyright (c) 2019 Mitchell Horne > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * From: FreeBSD: src/lib/libkvm/kvm_minidump_amd64.c r261799 > + */ > + > +#include > +__FBSDID("$FreeBSD$"); > + > +/* > + * RISC-V machine dependent routines for kvm and minidumps. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "../../sys/riscv/include/minidump.h" > + > +#include > + > +#include "kvm_private.h" > +#include "kvm_riscv.h" > + > +#define riscv_round_page(x) roundup2((kvaddr_t)(x), RISCV_PAGE_SIZE) > + > +struct vmstate { > + struct minidumphdr hdr; > +}; > + > +static riscv_pt_entry_t > +_riscv_pte_get(kvm_t *kd, u_long pteindex) > +{ > + riscv_pt_entry_t *pte = _kvm_pmap_get(kd, pteindex, sizeof(*pte)); > + > + return le64toh(*pte); > +} > + > +static int > +_riscv_minidump_probe(kvm_t *kd) > +{ > + > + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_RISCV) && > + _kvm_is_minidump(kd)); > +} > + > +static void > +_riscv_minidump_freevtop(kvm_t *kd) > +{ > + struct vmstate *vm = kd->vmst; > + > + free(vm); > + kd->vmst = NULL; > +} > + > +static int > +_riscv_minidump_initvtop(kvm_t *kd) > +{ > + struct vmstate *vmst; > + off_t off, sparse_off; > + > + vmst = _kvm_malloc(kd, sizeof(*vmst)); > + if (vmst == NULL) { > + _kvm_err(kd, kd->program, "cannot allocate vm"); > + return (-1); > + } > + kd->vmst = vmst; > + if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != > + sizeof(vmst->hdr)) { > + _kvm_err(kd, kd->program, "cannot read dump header"); > + return (-1); > + } > + if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, > + sizeof(vmst->hdr.magic)) != 0) { > + _kvm_err(kd, kd->program, "not a minidump for this platform"); > + return (-1); > + } > + > + vmst->hdr.version = le32toh(vmst->hdr.version); > + if (vmst->hdr.version != MINIDUMP_VERSION) { > + _kvm_err(kd, kd->program, "wrong minidump version. " > + "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version); > + return (-1); > + } > + vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize); > + vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize); > + vmst->hdr.pmapsize = le32toh(vmst->hdr.pmapsize); > + vmst->hdr.kernbase = le64toh(vmst->hdr.kernbase); > + vmst->hdr.dmapphys = le64toh(vmst->hdr.dmapphys); > + vmst->hdr.dmapbase = le64toh(vmst->hdr.dmapbase); > + vmst->hdr.dmapend = le64toh(vmst->hdr.dmapend); > + > + /* Skip header and msgbuf */ > + off = RISCV_PAGE_SIZE + riscv_round_page(vmst->hdr.msgbufsize); > + > + /* build physical address lookup table for sparse pages */ > + sparse_off = off + riscv_round_page(vmst->hdr.bitmapsize) + > + riscv_round_page(vmst->hdr.pmapsize); > + if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, > + RISCV_PAGE_SIZE, sizeof(uint64_t)) == -1) { > + return (-1); > + } > + off += riscv_round_page(vmst->hdr.bitmapsize); > + > + if (_kvm_pmap_init(kd, vmst->hdr.pmapsize, off) == -1) { > + return (-1); > + } > + off += riscv_round_page(vmst->hdr.pmapsize); > + > + return (0); > +} > + > +static int > +_riscv_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) > +{ > + struct vmstate *vm; > + riscv_physaddr_t offset; > + riscv_pt_entry_t l3; > + kvaddr_t l3_index; > + riscv_physaddr_t a; > + off_t ofs; > + > + vm = kd->vmst; > + offset = va & RISCV_PAGE_MASK; > + > + if (va >= vm->hdr.dmapbase && va < vm->hdr.dmapend) { > + a = (va - vm->hdr.dmapbase + vm->hdr.dmapphys) & > + ~RISCV_PAGE_MASK; > + ofs = _kvm_pt_find(kd, a, RISCV_PAGE_SIZE); > + if (ofs == -1) { > + _kvm_err(kd, kd->program, "_riscv_minidump_vatop: " > + "direct map address 0x%jx not in minidump", > + (uintmax_t)va); > + goto invalid; > + } > + *pa = ofs + offset; > + return (RISCV_PAGE_SIZE - offset); > + } else if (va >= vm->hdr.kernbase) { > + l3_index = (va - vm->hdr.kernbase) >> RISCV_L3_SHIFT; > + if (l3_index >= vm->hdr.pmapsize / sizeof(l3)) > + goto invalid; > + l3 = _riscv_pte_get(kd, l3_index); > + if ((l3 & RISCV_PTE_V) == 0 || (l3 & RISCV_PTE_RWX) == 0) { > + _kvm_err(kd, kd->program, > + "_riscv_minidump_vatop: pte not valid"); > + goto invalid; > + } > + a = (l3 >> RISCV_PTE_PPN0_S) << RISCV_L3_SHIFT; > + ofs = _kvm_pt_find(kd, a, RISCV_PAGE_SIZE); > + if (ofs == -1) { > + _kvm_err(kd, kd->program, "_riscv_minidump_vatop: " > + "physical address 0x%jx not in minidump", > + (uintmax_t)a); > + goto invalid; > + } > + *pa = ofs + offset; > + return (RISCV_PAGE_SIZE - offset); > + } else { > + _kvm_err(kd, kd->program, > + "_riscv_minidump_vatop: virtual address 0x%jx not minidumped", > + (uintmax_t)va); > + goto invalid; > + } > + > +invalid: > + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); > + return (0); > +} > + > +static int > +_riscv_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) > +{ > + > + if (ISALIVE(kd)) { > + _kvm_err(kd, 0, > + "_riscv_minidump_kvatop called in live kernel!"); > + return (0); > + } > + return (_riscv_minidump_vatop(kd, va, pa)); > +} > + > +static int > +_riscv_native(kvm_t *kd __unused) > +{ > + > +#ifdef __riscv > + return (1); > +#else > + return (0); > +#endif > +} > + > +static vm_prot_t > +_riscv_entry_to_prot(riscv_pt_entry_t pte) > +{ > + vm_prot_t prot = VM_PROT_READ; > + > + if ((pte & RISCV_PTE_W) != 0) > + prot |= VM_PROT_WRITE; > + if ((pte & RISCV_PTE_X) != 0) > + prot |= VM_PROT_EXECUTE; > + return prot; > +} > + > +static int > +_riscv_minidump_walk_pages(kvm_t *kd, kvm_walk_pages_cb_t *cb, void *arg) > +{ > + struct vmstate *vm = kd->vmst; > + u_long nptes = vm->hdr.pmapsize / sizeof(riscv_pt_entry_t); > + u_long bmindex, dva, pa, pteindex, va; > + struct kvm_bitmap bm; > + vm_prot_t prot; > + int ret = 0; > + > + if (!_kvm_bitmap_init(&bm, vm->hdr.bitmapsize, &bmindex)) > + return (0); > + > + for (pteindex = 0; pteindex < nptes; pteindex++) { > + riscv_pt_entry_t pte = _riscv_pte_get(kd, pteindex); > + > + if (((pte & RISCV_PTE_V) == 0) || > + ((pte & RISCV_PTE_RWX) == 0)) > + continue; > + > + va = vm->hdr.kernbase + (pteindex << RISCV_L3_SHIFT); > + pa = (pte >> RISCV_PTE_PPN0_S) << RISCV_L3_SHIFT; > + dva = vm->hdr.dmapbase + pa; > + if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, > + _riscv_entry_to_prot(pte), RISCV_PAGE_SIZE, 0)) { > + goto out; > + } > + } > + > + while (_kvm_bitmap_next(&bm, &bmindex)) { > + pa = bmindex * RISCV_PAGE_SIZE; > + dva = vm->hdr.dmapbase + pa; > + if (vm->hdr.dmapend < (dva + RISCV_PAGE_SIZE)) > + break; > + va = 0; > + prot = VM_PROT_READ | VM_PROT_WRITE; > + if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, > + prot, RISCV_PAGE_SIZE, 0)) { > + goto out; > + } > + } > + ret = 1; > + > +out: > + _kvm_bitmap_deinit(&bm); > + return (ret); > +} > + > +static struct kvm_arch kvm_riscv_minidump = { > + .ka_probe = _riscv_minidump_probe, > + .ka_initvtop = _riscv_minidump_initvtop, > + .ka_freevtop = _riscv_minidump_freevtop, > + .ka_kvatop = _riscv_minidump_kvatop, > + .ka_native = _riscv_native, > + .ka_walk_pages = _riscv_minidump_walk_pages, > +}; > + > +KVM_ARCH(kvm_riscv_minidump); > > Added: head/lib/libkvm/kvm_riscv.h > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/lib/libkvm/kvm_riscv.h Tue Mar 5 23:59:55 2019 (r344829) > @@ -0,0 +1,90 @@ > +/*- > + * Copyright (c) 2015 John H. Baldwin > + * Copyright (c) 2019 Mitchell Horne > + * All rights reserved. It appears as if Mitchell Horne has removed John Baldwin's All rights reserved by the way he has inserted his copyright into the middle of Johns. > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * Where did this file come from that it has Jhb copyright? Shouldnt a cp, then patch been done rather than a new file? > + * $FreeBSD$ > + */ > + > +#ifndef __KVM_RISCV_H__ > +#define __KVM_RISCV_H__ > + > +#ifdef __riscv > +#include > +#endif > + > +typedef uint64_t riscv_physaddr_t; > +typedef uint64_t riscv_pt_entry_t; > + > +#define RISCV_PAGE_SHIFT 12 > +#define RISCV_PAGE_SIZE (1 << RISCV_PAGE_SHIFT) > +#define RISCV_PAGE_MASK (RISCV_PAGE_SIZE - 1) > + > +/* Source: sys/riscv/include/pte.h */ > +#define RISCV_L3_SHIFT 12 > +#define RISCV_L3_SIZE (1 << L3_SHIFT) > +#define RISCV_L3_OFFSET (L3_SIZE - 1) > + > +#define RISCV_PTE_SW_MANAGED (1 << 9) > +#define RISCV_PTE_SW_WIRED (1 << 8) > +#define RISCV_PTE_D (1 << 7) /* Dirty */ > +#define RISCV_PTE_A (1 << 6) /* Accessed */ > +#define RISCV_PTE_G (1 << 5) /* Global */ > +#define RISCV_PTE_U (1 << 4) /* User */ > +#define RISCV_PTE_X (1 << 3) /* Execute */ > +#define RISCV_PTE_W (1 << 2) /* Write */ > +#define RISCV_PTE_R (1 << 1) /* Read */ > +#define RISCV_PTE_V (1 << 0) /* Valid */ > +#define RISCV_PTE_RWX (RISCV_PTE_R | RISCV_PTE_W | RISCV_PTE_X) > + > +#define RISCV_PTE_PPN0_S 10 > + > +#ifdef __riscv > +_Static_assert(sizeof(pt_entry_t) == sizeof(riscv_pt_entry_t), > + "pt_entry_t size mismatch"); > + > +_Static_assert(PAGE_SHIFT == RISCV_PAGE_SHIFT, "PAGE_SHIFT mismatch"); > +_Static_assert(PAGE_SIZE == RISCV_PAGE_SIZE, "PAGE_SIZE mismatch"); > +_Static_assert(PAGE_MASK == RISCV_PAGE_MASK, "PAGE_MASK mismatch"); > + > +_Static_assert(L3_SHIFT == RISCV_L3_SHIFT, "L3_SHIFT mismatch"); > +_Static_assert(L3_SIZE == RISCV_L3_SIZE, "L3_SIZE mismatch"); > +_Static_assert(L3_OFFSET == RISCV_L3_OFFSET, "L3_OFFSET mismatch"); > +_Static_assert(PTE_PPN0_S == RISCV_PTE_PPN0_S, "PTE_PPN0_S mismatch"); > + > +_Static_assert(PTE_SW_MANAGED == RISCV_PTE_SW_MANAGED, > + "PTE_SW_MANAGED mismatch"); > +_Static_assert(PTE_SW_WIRED == RISCV_PTE_SW_WIRED, "PTE_SW_WIRED mismatch"); > +_Static_assert(PTE_D == RISCV_PTE_D, "PTE_D mismatch"); > +_Static_assert(PTE_A == RISCV_PTE_A, "PTE_A mismatch"); > +_Static_assert(PTE_G == RISCV_PTE_G, "PTE_G mismatch"); > +_Static_assert(PTE_U == RISCV_PTE_U, "PTE_U mismatch"); > +_Static_assert(PTE_X == RISCV_PTE_X, "PTE_X mismatch"); > +_Static_assert(PTE_W == RISCV_PTE_W, "PTE_W mismatch"); > +_Static_assert(PTE_R == RISCV_PTE_R, "PTE_R mismatch"); > +_Static_assert(PTE_V == RISCV_PTE_V, "PTE_V mismatch"); > +_Static_assert(PTE_RWX == RISCV_PTE_RWX, "PTE_RWX mismatch"); > +#endif > + > +#endif /* !__KVM_RISCV_H__ */ > > -- Rod Grimes rgrimes@freebsd.org