From 0349817103d68e9f98eb5fd7f7f29270ce60635c Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 23 Nov 2017 14:07:52 +0000 Subject: [PATCH 01/22] Allow kern.geom.mirror.debug to be negative. A negative value can be used to suppress all prints from the gmirror kernel code, which can be useful when attempting to trigger race conditions using stress tests. MFC after: 1 week --- sys/geom/mirror/g_mirror.c | 4 ++-- sys/geom/mirror/g_mirror.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 7f8f670d746..4a5f542c1de 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -54,8 +54,8 @@ static MALLOC_DEFINE(M_MIRROR, "mirror_data", "GEOM_MIRROR Data"); SYSCTL_DECL(_kern_geom); static SYSCTL_NODE(_kern_geom, OID_AUTO, mirror, CTLFLAG_RW, 0, "GEOM_MIRROR stuff"); -u_int g_mirror_debug = 0; -SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, debug, CTLFLAG_RWTUN, &g_mirror_debug, 0, +int g_mirror_debug = 0; +SYSCTL_INT(_kern_geom_mirror, OID_AUTO, debug, CTLFLAG_RWTUN, &g_mirror_debug, 0, "Debug level"); static u_int g_mirror_timeout = 4; SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, timeout, CTLFLAG_RWTUN, &g_mirror_timeout, diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h index f3a4a007009..3b9664035c9 100644 --- a/sys/geom/mirror/g_mirror.h +++ b/sys/geom/mirror/g_mirror.h @@ -72,7 +72,7 @@ G_MIRROR_DEVICE_FLAG_NOFAILSYNC) #ifdef _KERNEL -extern u_int g_mirror_debug; +extern int g_mirror_debug; #define G_MIRROR_DEBUG(lvl, ...) do { \ if (g_mirror_debug >= (lvl)) { \ From e9f63df76dcfe798bd47df803d5e9dbdcae0bb0a Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 23 Nov 2017 14:29:07 +0000 Subject: [PATCH 02/22] Duplicate helpers after disabling inherited tracepoints during a fork. We may create probes in the nascent child process, so we first need to ensure that any inherited tracepoints are first removed. Otherwise the probe sites will not be in the state expected by fasttrap, and it won't be able to enable the probes. MFC after: 2 weeks --- .../opensolaris/uts/common/dtrace/fasttrap.c | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c index 82353cbb235..9e6bde2eac4 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c @@ -601,8 +601,8 @@ fasttrap_fork(proc_t *p, proc_t *cp) pid_t ppid = p->p_pid; int i; -#ifdef illumos ASSERT(curproc == p); +#ifdef illumos ASSERT(p->p_proc_flag & P_PR_LOCK); #else PROC_LOCK_ASSERT(p, MA_OWNED); @@ -610,26 +610,15 @@ fasttrap_fork(proc_t *p, proc_t *cp) #ifdef illumos ASSERT(p->p_dtrace_count > 0); #else - if (p->p_dtrace_helpers) { - /* - * dtrace_helpers_duplicate() allocates memory. - */ - _PHOLD(cp); - PROC_UNLOCK(p); - PROC_UNLOCK(cp); - dtrace_helpers_duplicate(p, cp); - PROC_LOCK(cp); - PROC_LOCK(p); - _PRELE(cp); - } /* * This check is purposely here instead of in kern_fork.c because, * for legal resons, we cannot include the dtrace_cddl.h header * inside kern_fork.c and insert if-clause there. */ - if (p->p_dtrace_count == 0) + if (p->p_dtrace_count == 0 && p->p_dtrace_helpers == NULL) return; #endif + ASSERT(cp->p_dtrace_count == 0); /* @@ -658,6 +647,8 @@ fasttrap_fork(proc_t *p, proc_t *cp) _PHOLD(cp); PROC_UNLOCK(cp); PROC_UNLOCK(p); + if (p->p_dtrace_count == 0) + goto dup_helpers; #endif /* @@ -711,6 +702,9 @@ fasttrap_fork(proc_t *p, proc_t *cp) mutex_enter(&cp->p_lock); sprunlock(cp); #else +dup_helpers: + if (p->p_dtrace_helpers != NULL) + dtrace_helpers_duplicate(p, cp); PROC_LOCK(p); PROC_LOCK(cp); _PRELE(cp); From bd036e101c7a24a684338fba97a434d9915500fc Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 23 Nov 2017 14:30:41 +0000 Subject: [PATCH 03/22] bfd: fix segfault in the ihex parser on malformed ihex file From binutils commit 0102ea8cec5fc509bba6c91df61b7ce23a799d32, made available under GPLv2 by Nick Clifton. PR: 198824 MFC after: 1 week Security: CVE-2014-8503 --- contrib/binutils/bfd/ihex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/binutils/bfd/ihex.c b/contrib/binutils/bfd/ihex.c index 9f765b33f77..67ac720a6eb 100644 --- a/contrib/binutils/bfd/ihex.c +++ b/contrib/binutils/bfd/ihex.c @@ -320,7 +320,7 @@ ihex_scan (bfd *abfd) { if (! ISHEX (buf[i])) { - ihex_bad_byte (abfd, lineno, hdr[i], error); + ihex_bad_byte (abfd, lineno, buf[i], error); goto error_return; } } From b452493a3dc2a56918209677e82ce4070260289c Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 23 Nov 2017 16:04:52 +0000 Subject: [PATCH 04/22] bfd: avoid crash on corrupt binaries From binutils commits 5a4b0ccc20ba30caef53b01bee2c0aaa5b855339 and 7e1e19887abd24aeb15066b141cdff5541e0ec8e, made available under GPLv2 by Nick Clifton. PR: 198824 MFC after: 1 week Security: CVE-2014-8501 Security: CVE-2014-8502 --- contrib/binutils/bfd/peXXigen.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/contrib/binutils/bfd/peXXigen.c b/contrib/binutils/bfd/peXXigen.c index f96825f687e..954d68ef903 100644 --- a/contrib/binutils/bfd/peXXigen.c +++ b/contrib/binutils/bfd/peXXigen.c @@ -448,6 +448,17 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd, { int idx; + /* PR 17512: Corrupt PE binaries can cause seg-faults. */ + if (a->NumberOfRvaAndSizes > 16) + { + (*_bfd_error_handler) + (_("%B: aout header specifies an invalid number of data-directory entries: %d"), + abfd, a->NumberOfRvaAndSizes); + /* Paranoia: If the number is corrupt, then assume that the + actual entries themselves might be corrupt as well. */ + a->NumberOfRvaAndSizes = 0; + } + for (idx = 0; idx < 16; idx++) { /* If data directory is empty, rva also should be 0. */ @@ -1428,6 +1439,15 @@ pe_print_edata (bfd * abfd, void * vfile) } } + /* PR 17512: Handle corrupt PE binaries. */ + if (datasize < 36) + { + fprintf (file, + _("\nThere is an export table in %s, but it is too small (%d)\n"), + section->name, (int) datasize); + return TRUE; + } + fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"), section->name, (unsigned long) addr); From 521018d3797c6d14a1640a573cb43a96fa4a48c9 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Thu, 23 Nov 2017 17:40:40 +0000 Subject: [PATCH 05/22] Ensure we check the program state set in the trap frame on arm and arm64. This value may be set by userspace so we need to check it before using it. If this is not done correctly on exception return the kernel may continue in kernel mode with all registers set to a userspace controlled value. Fix this by moving the check into set_mcontext, and also add the missing sanitisation from the arm64 set_regs. Discussed with: security-officer@ MFC after: 3 days Sponsored by: DARPA, AFRL --- sys/arm/arm/machdep.c | 24 ++++++++++++++---------- sys/arm64/arm64/machdep.c | 20 ++++++++++++-------- sys/arm64/include/armreg.h | 1 + 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 689f7686d4c..04fd482170e 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -518,6 +518,16 @@ set_mcontext(struct thread *td, mcontext_t *mcp) mcontext_vfp_t mc_vfp, *vfp; struct trapframe *tf = td->td_frame; const __greg_t *gr = mcp->__gregs; + int spsr; + + /* + * Make sure the processor mode has not been tampered with and + * interrupts have not been disabled. + */ + spsr = gr[_REG_CPSR]; + if ((spsr & PSR_MODE) != PSR_USR32_MODE || + (spsr & (PSR_I | PSR_F)) != 0) + return (EINVAL); #ifdef WITNESS if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(mc_vfp)) { @@ -677,22 +687,16 @@ sys_sigreturn(td, uap) } */ *uap; { ucontext_t uc; - int spsr; + int error; if (uap == NULL) return (EFAULT); if (copyin(uap->sigcntxp, &uc, sizeof(uc))) return (EFAULT); - /* - * Make sure the processor mode has not been tampered with and - * interrupts have not been disabled. - */ - spsr = uc.uc_mcontext.__gregs[_REG_CPSR]; - if ((spsr & PSR_MODE) != PSR_USR32_MODE || - (spsr & (PSR_I | PSR_F)) != 0) - return (EINVAL); /* Restore register context. */ - set_mcontext(td, &uc.uc_mcontext); + error = set_mcontext(td, &uc.uc_mcontext); + if (error != 0) + return (error); /* Restore signal mask. */ kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 886792a9681..54eec90d726 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -211,7 +211,8 @@ set_regs(struct thread *td, struct reg *regs) frame->tf_sp = regs->sp; frame->tf_lr = regs->lr; frame->tf_elr = regs->elr; - frame->tf_spsr = regs->spsr; + frame->tf_spsr &= ~PSR_FLAGS; + frame->tf_spsr |= regs->spsr & PSR_FLAGS; memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x)); @@ -354,6 +355,12 @@ int set_mcontext(struct thread *td, mcontext_t *mcp) { struct trapframe *tf = td->td_frame; + uint32_t spsr; + + spsr = mcp->mc_gpregs.gp_spsr; + if ((spsr & PSR_M_MASK) != PSR_M_EL0t || + (spsr & (PSR_F | PSR_I | PSR_A | PSR_D)) != 0) + return (EINVAL); memcpy(tf->tf_x, mcp->mc_gpregs.gp_x, sizeof(tf->tf_x)); @@ -530,19 +537,16 @@ int sys_sigreturn(struct thread *td, struct sigreturn_args *uap) { ucontext_t uc; - uint32_t spsr; + int error; if (uap == NULL) return (EFAULT); if (copyin(uap->sigcntxp, &uc, sizeof(uc))) return (EFAULT); - spsr = uc.uc_mcontext.mc_gpregs.gp_spsr; - if ((spsr & PSR_M_MASK) != PSR_M_EL0t || - (spsr & (PSR_F | PSR_I | PSR_A | PSR_D)) != 0) - return (EINVAL); - - set_mcontext(td, &uc.uc_mcontext); + error = set_mcontext(td, &uc.uc_mcontext); + if (error != 0) + return (error); set_fpcontext(td, &uc.uc_mcontext); /* Restore signal mask. */ diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index a7a15fc8785..cf24fadf162 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -572,6 +572,7 @@ #define PSR_C 0x20000000 #define PSR_Z 0x40000000 #define PSR_N 0x80000000 +#define PSR_FLAGS 0xf0000000 /* TCR_EL1 - Translation Control Register */ #define TCR_ASID_16 (1 << 36) From d5589c6c60143bfa3dad78e4d6b0c50f7b639ff9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 23 Nov 2017 19:06:44 +0000 Subject: [PATCH 06/22] Use C standard spelling uint64_t for u_int64_t. Submitted by: Pawel Biernacki Sponsored by: Mysterious Code Ltd. X-Differential revision: https://reviews.freebsd.org/D13199 --- usr.bin/vmstat/vmstat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index 2c1e61203c2..1591996c780 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -665,7 +665,7 @@ getcpuinfo(u_long *maskp, int *maxidp) static void -prthuman(const char *name, u_int64_t val, int size) +prthuman(const char *name, uint64_t val, int size) { char buf[10]; int flags; @@ -822,10 +822,10 @@ dovmstat(unsigned int interval, int reps) if (hflag) { xo_emit(""); prthuman("available-memory", - total.t_avm * (u_int64_t)sum.v_page_size, 5); + total.t_avm * (uint64_t)sum.v_page_size, 5); xo_emit(" "); prthuman("free-memory", - total.t_free * (u_int64_t)sum.v_page_size, 5); + total.t_free * (uint64_t)sum.v_page_size, 5); xo_emit(" "); } else { xo_emit(" "); From 72f406a92c710441b5160b92860cb1d320ec2710 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 23 Nov 2017 19:10:09 +0000 Subject: [PATCH 07/22] vmstat: use 64-bit counters from struct vmtotal. Consistently print counters using unsigned intmax type. Submitted by: Pawel Biernacki Sponsored by: Mysterious Code Ltd. Differential revision: https://reviews.freebsd.org/D13199 --- usr.bin/vmstat/vmstat.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index 1591996c780..ac18efcbb33 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -817,7 +817,7 @@ dovmstat(unsigned int interval, int reps) total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); xo_close_container("processes"); xo_open_container("memory"); -#define vmstat_pgtok(a) ((a) * (sum.v_page_size >> 10)) +#define vmstat_pgtok(a) ((uintmax_t)(a) * (sum.v_page_size >> 10)) #define rate(x) (((x) * rate_adj + halfuptime) / uptime) /* round */ if (hflag) { xo_emit(""); @@ -829,10 +829,10 @@ dovmstat(unsigned int interval, int reps) xo_emit(" "); } else { xo_emit(" "); - xo_emit("{:available-memory/%7d}", + xo_emit("{:available-memory/%7ju}", vmstat_pgtok(total.t_avm)); xo_emit(" "); - xo_emit("{:free-memory/%7d}", + xo_emit("{:free-memory/%7ju}", vmstat_pgtok(total.t_free)); xo_emit(" "); } @@ -1555,9 +1555,9 @@ display_object(struct kinfo_vmobject *kvo) const char *str; xo_open_instance("object"); - xo_emit("{:resident/%5jd} ", (uintmax_t)kvo->kvo_resident); - xo_emit("{:active/%5jd} ", (uintmax_t)kvo->kvo_active); - xo_emit("{:inactive/%5jd} ", (uintmax_t)kvo->kvo_inactive); + xo_emit("{:resident/%5ju} ", (uintmax_t)kvo->kvo_resident); + xo_emit("{:active/%5ju} ", (uintmax_t)kvo->kvo_active); + xo_emit("{:inactive/%5ju} ", (uintmax_t)kvo->kvo_inactive); xo_emit("{:refcount/%3d} ", kvo->kvo_ref_count); xo_emit("{:shadowcount/%3d} ", kvo->kvo_shadow_count); switch (kvo->kvo_memattr) { From 2205d3dd3ecf0da9652b3392868d3c8e3427f497 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 23 Nov 2017 22:10:12 +0000 Subject: [PATCH 08/22] vmrun.sh: add -A option for AHCI emulation of disk devices AHCI emulation is useful for testing scenarios closer to the real hardware. For example, it allows to exercise the CAM subsystem. There could be other uses as well. MFC after: 2 weeks --- share/examples/bhyve/vmrun.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/share/examples/bhyve/vmrun.sh b/share/examples/bhyve/vmrun.sh index c5f8006b27d..7deb4b361ff 100755 --- a/share/examples/bhyve/vmrun.sh +++ b/share/examples/bhyve/vmrun.sh @@ -46,7 +46,7 @@ errmsg() { usage() { local msg=$1 - echo "Usage: vmrun.sh [-aEhiTv] [-c ] [-C ] [-d ]" + echo "Usage: vmrun.sh [-aAEhiTv] [-c ] [-C ] [-d ]" echo " [-e ] [-f ] [-F ]" echo " [-g ] [-H ]" echo " [-I ] [-l ]" @@ -55,6 +55,7 @@ usage() { echo "" echo " -h: display this help message" echo " -a: force memory mapped local APIC access" + echo " -A: use AHCI disk emulation instead of virtio" echo " -c: number of virtual cpus (default is ${DEFAULT_CPUS})" echo " -C: console device (default is ${DEFAULT_CONSOLE})" echo " -d: virtio diskdev file (default is ${DEFAULT_VIRTIO_DISK})" @@ -99,6 +100,7 @@ console=${DEFAULT_CONSOLE} cpus=${DEFAULT_CPUS} tap_total=0 disk_total=0 +disk_emulation="virtio-blk" gdbport=0 loader_opt="" bhyverun_opt="-H -A -P" @@ -113,11 +115,14 @@ vncport=5900 fbsize="w=1024,h=768" tablet="" -while getopts ac:C:d:e:Ef:F:g:hH:iI:l:m:p:P:t:Tuvw c ; do +while getopts aAc:C:d:e:Ef:F:g:hH:iI:l:m:p:P:t:Tuvw c ; do case $c in a) bhyverun_opt="${bhyverun_opt} -a" ;; + A) + disk_emulation="ahci-hd" + ;; c) cpus=${OPTARG} ;; @@ -316,7 +321,7 @@ while [ 1 ]; do eval "disk=\$disk_dev${i}" eval "opts=\$disk_opts${i}" make_and_check_diskdev "${disk}" - devargs="$devargs -s $nextslot:0,virtio-blk,${disk}${opts} " + devargs="$devargs -s $nextslot:0,$disk_emulation,${disk}${opts} " nextslot=$(($nextslot + 1)) i=$(($i + 1)) done From e60d3b7ff4d42698d3fd3779c0e38faa4fe1f34c Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 24 Nov 2017 02:39:38 +0000 Subject: [PATCH 09/22] Add ccu compat string for Allwinner a83t A ccu driver was added for the a83t in r326114. Add compat string to aw_ccung and register the clocks for the a83t upon attach. Reviewed by: manu Approved by: emaste (mentor, implicit) Differential Revision: https://reviews.freebsd.org/D13205 --- sys/arm/allwinner/clkng/aw_ccung.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sys/arm/allwinner/clkng/aw_ccung.c b/sys/arm/allwinner/clkng/aw_ccung.c index 416a3c08bcf..41ee55b4baf 100644 --- a/sys/arm/allwinner/clkng/aw_ccung.c +++ b/sys/arm/allwinner/clkng/aw_ccung.c @@ -76,6 +76,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#if defined(SOC_ALLWINNER_A83T) +#include +#endif + #include "clkdev_if.h" #include "hwreset_if.h" @@ -102,6 +106,10 @@ static struct resource_spec aw_ccung_spec[] = { #define A13_CCU 6 #endif +#if defined(SOC_ALLWINNER_A83T) +#define A83T_CCU 7 +#endif + static struct ofw_compat_data compat_data[] = { #if defined(SOC_ALLWINNER_A31) { "allwinner,sun5i-a13-ccu", A13_CCU}, @@ -116,6 +124,9 @@ static struct ofw_compat_data compat_data[] = { #if defined(SOC_ALLWINNER_A64) { "allwinner,sun50i-a64-ccu", A64_CCU }, { "allwinner,sun50i-a64-r-ccu", A64_R_CCU }, +#endif +#if defined(SOC_ALLWINNER_A83T) + { "allwinner,sun8i-a83t-ccu", A83T_CCU }, #endif {NULL, 0 } }; @@ -358,6 +369,11 @@ aw_ccung_attach(device_t dev) case A64_R_CCU: ccu_sun8i_r_register_clocks(sc); break; +#endif +#if defined(SOC_ALLWINNER_A83T) + case A83T_CCU: + ccu_a83t_register_clocks(sc); + break; #endif } From db7117443695cb35600c84d533c38ff48cf2b2c9 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 24 Nov 2017 05:00:25 +0000 Subject: [PATCH 10/22] Fix theoretical integer overflow issues. If the product here is greater than 2^31-1, then the result will be huge. This is unlikely, as we don't support that many sections, but out of an abundace of caution cast to size_t so the multiplication won't overflow mysteriously when size_t is larger than 32-bits. The resulting code may be a smidge larger, but this isn't super-space critical code. CID: 1194216, 1194217, 1194222, 1194223, 1265018, 1265019,1265020, 1265021 Sponsored by: Netflix --- stand/common/load_elf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c index 679842b9423..cccd585860a 100644 --- a/stand/common/load_elf.c +++ b/stand/common/load_elf.c @@ -456,7 +456,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) * think the rule is going to have to be that you must strip a * file to remove symbols before gzipping it. */ - chunk = ehdr->e_shnum * ehdr->e_shentsize; + chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize; if (chunk == 0 || ehdr->e_shoff == 0) goto nosyms; shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); @@ -747,7 +747,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest) goto out; } - size = ef.ehdr->e_shnum * ef.ehdr->e_shentsize; + size = (size_t)ef.ehdr->e_shnum * (size_t)ef.ehdr->e_shentsize; shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size); if (shdr == NULL) { err = ENOMEM; From d927d443e1cceafe3c4de05161ed2ece105ab4ef Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 24 Nov 2017 05:01:00 +0000 Subject: [PATCH 11/22] Mark the func pointer as __dead2. It looks up loader_main, which either aborts or exits, but never returns. Tag it as a non-returning function rather than supply a bogus return(0) at the end of main. CID: 1382885 Sponsored by: Netflix --- stand/userboot/test/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stand/userboot/test/test.c b/stand/userboot/test/test.c index bacde565ec3..1cee79ce104 100644 --- a/stand/userboot/test/test.c +++ b/stand/userboot/test/test.c @@ -422,7 +422,7 @@ int main(int argc, char** argv) { void *h; - void (*func)(struct loader_callbacks *, void *, int, int); + void (*func)(struct loader_callbacks *, void *, int, int) __dead2; int opt; char *disk_image = NULL; const char *userboot_obj = "/boot/userboot.so"; From 814629dd64a35b829cc8f537b55b9c5d873f7bbf Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Fri, 24 Nov 2017 07:35:08 +0000 Subject: [PATCH 12/22] Don't let cpu_set_syscall_retval() clobber exec_setregs(). Upon successful completion, the execve() system call invokes exec_setregs() to initialize the registers of the initial thread of the newly executed process. What is weird is that when execve() returns, it still goes through the normal system call return path, clobbering the registers with the system call's return value (td->td_retval). Though this doesn't seem to be problematic for x86 most of the times (as the value of eax/rax doesn't matter upon startup), this can be pretty frustrating for architectures where function argument and return registers overlap (e.g., ARM). On these systems, exec_setregs() also needs to initialize td_retval. Even worse are architectures where cpu_set_syscall_retval() sets registers to values not derived from td_retval. On these architectures, there is no way cpu_set_syscall_retval() can set registers to the way it wants them to be upon the start of execution. To get rid of this madness, let sys_execve() return EJUSTRETURN. This will cause cpu_set_syscall_retval() to leave registers intact. This makes process execution easier to understand. It also eliminates the difference between execution of the initial process and successive ones. The initial call to sys_execve() is not performed through a system call context. Reviewed by: kib, jhibbits Differential Revision: https://reviews.freebsd.org/D13180 --- sys/amd64/amd64/machdep.c | 1 - sys/amd64/ia32/ia32_signal.c | 1 - sys/amd64/linux32/linux32_sysvec.c | 1 - sys/arm/cloudabi32/cloudabi32_sysvec.c | 2 +- sys/arm64/arm64/machdep.c | 7 +------ sys/arm64/cloudabi64/cloudabi64_sysvec.c | 2 +- sys/compat/linux/linux_emul.c | 4 ++-- sys/i386/i386/machdep.c | 8 +------- sys/kern/init_main.c | 2 +- sys/kern/kern_exec.c | 10 ++++++++-- sys/powerpc/powerpc/exec_machdep.c | 13 ------------- sys/riscv/riscv/machdep.c | 7 +------ sys/sparc64/sparc64/machdep.c | 3 --- 13 files changed, 16 insertions(+), 45 deletions(-) diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 3175616d0ce..0c16da1327d 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -604,7 +604,6 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) regs->tf_fs = _ufssel; regs->tf_gs = _ugssel; regs->tf_flags = TF_HASSEGS; - td->td_retval[1] = 0; /* * Reset the hardware debug registers if they were in use. diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c index 79131f3f561..b1fc8debc1f 100644 --- a/sys/amd64/ia32/ia32_signal.c +++ b/sys/amd64/ia32/ia32_signal.c @@ -967,5 +967,4 @@ ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) /* Return via doreti so that we can change to a different %cs */ set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); - td->td_retval[1] = 0; } diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 8b0a35ea0bf..1a0dc1c954b 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -832,7 +832,6 @@ exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack) /* Do full restore on return so that we can change to a different %cs */ set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); - td->td_retval[1] = 0; } /* diff --git a/sys/arm/cloudabi32/cloudabi32_sysvec.c b/sys/arm/cloudabi32/cloudabi32_sysvec.c index a0bebcc9964..eeeb93c188c 100644 --- a/sys/arm/cloudabi32/cloudabi32_sysvec.c +++ b/sys/arm/cloudabi32/cloudabi32_sysvec.c @@ -61,7 +61,7 @@ cloudabi32_proc_setregs(struct thread *td, struct image_params *imgp, * tpidrurw to the TCB. */ regs = td->td_frame; - regs->tf_r0 = td->td_retval[0] = + regs->tf_r0 = stack + roundup(sizeof(cloudabi32_tcb_t), sizeof(register_t)); (void)cpu_set_user_tls(td, (void *)stack); } diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 54eec90d726..452f224797a 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -311,12 +311,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) memset(tf, 0, sizeof(struct trapframe)); - /* - * We need to set x0 for init as it doesn't call - * cpu_set_syscall_retval to copy the value. We also - * need to set td_retval for the cases where we do. - */ - tf->tf_x[0] = td->td_retval[0] = stack; + tf->tf_x[0] = stack; tf->tf_sp = STACKALIGN(stack); tf->tf_lr = imgp->entry_addr; tf->tf_elr = imgp->entry_addr; diff --git a/sys/arm64/cloudabi64/cloudabi64_sysvec.c b/sys/arm64/cloudabi64/cloudabi64_sysvec.c index f6e75f56366..a98ff0e2c30 100644 --- a/sys/arm64/cloudabi64/cloudabi64_sysvec.c +++ b/sys/arm64/cloudabi64/cloudabi64_sysvec.c @@ -61,7 +61,7 @@ cloudabi64_proc_setregs(struct thread *td, struct image_params *imgp, * tpidr_el0 to the TCB. */ regs = td->td_frame; - regs->tf_x[0] = td->td_retval[0] = + regs->tf_x[0] = stack + roundup(sizeof(cloudabi64_tcb_t), sizeof(register_t)); (void)cpu_set_user_tls(td, (void *)stack); } diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c index b244eea3b67..8be4fa2df0c 100644 --- a/sys/compat/linux/linux_emul.c +++ b/sys/compat/linux/linux_emul.c @@ -186,7 +186,7 @@ linux_common_execve(struct thread *td, struct image_args *eargs) error = kern_execve(td, eargs, NULL); post_execve(td, error, oldvmspace); - if (error != 0) + if (error != EJUSTRETURN) return (error); /* @@ -213,7 +213,7 @@ linux_common_execve(struct thread *td, struct image_args *eargs) free(em, M_TEMP); free(pem, M_LINUX); } - return (0); + return (EJUSTRETURN); } void diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 68a45220858..dac5fd6967e 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -1126,6 +1126,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) set_fsbase(td, 0); set_gsbase(td, 0); + /* Make sure edx is 0x0 on entry. Linux binaries depend on it. */ bzero((char *)regs, sizeof(struct trapframe)); regs->tf_eip = imgp->entry_addr; regs->tf_esp = stack; @@ -1168,13 +1169,6 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) * clean FP state if it uses the FPU again. */ fpstate_drop(td); - - /* - * XXX - Linux emulator - * Make sure sure edx is 0x0 on entry. Linux binaries depend - * on it. - */ - td->td_retval[1] = 0; } void diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 645d120d980..dbd7a4ac07c 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -797,7 +797,7 @@ start_init(void *dummy) * Otherwise, return via fork_trampoline() all the way * to user mode as init! */ - if ((error = sys_execve(td, &args)) == 0) { + if ((error = sys_execve(td, &args)) == EJUSTRETURN) { mtx_unlock(&Giant); return; } diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index f844a61967c..284e08a801a 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -318,7 +318,7 @@ post_execve(struct thread *td, int error, struct vmspace *oldvmspace) * If success, we upgrade to SINGLE_EXIT state to * force other threads to suicide. */ - if (error == 0) + if (error == EJUSTRETURN) thread_single(p, SINGLE_EXIT); else thread_single_end(p, SINGLE_BOUNDARY); @@ -962,7 +962,13 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p) ktrprocctor(p); #endif - return (error); + /* + * We don't want cpu_set_syscall_retval() to overwrite any of + * the register values put in place by exec_setregs(). + * Implementations of cpu_set_syscall_retval() will leave + * registers unmodified when returning EJUSTRETURN. + */ + return (error == 0 ? EJUSTRETURN : error); } int diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index 596ae8079f1..724ae849a06 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -520,22 +520,11 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) * - ps_strings is a NetBSD extention, and will be * ignored by executables which are strictly * compliant with the SVR4 ABI. - * - * XXX We have to set both regs and retval here due to different - * XXX calling convention in trap.c and init_main.c. */ /* Collect argc from the user stack */ argc = fuword((void *)stack); - /* - * XXX PG: these get overwritten in the syscall return code. - * execve() should return EJUSTRETURN, like it does on NetBSD. - * Emulate by setting the syscall return value cells. The - * registers still have to be set for init's fork trampoline. - */ - td->td_retval[0] = argc; - td->td_retval[1] = stack + sizeof(register_t); tf->fixreg[3] = argc; tf->fixreg[4] = stack + sizeof(register_t); tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); @@ -572,8 +561,6 @@ ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) argc = fuword32((void *)stack); - td->td_retval[0] = argc; - td->td_retval[1] = stack + sizeof(uint32_t); tf->fixreg[3] = argc; tf->fixreg[4] = stack + sizeof(uint32_t); tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index d8a968791a0..de1a71e4d2e 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -279,12 +279,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) memset(tf, 0, sizeof(struct trapframe)); - /* - * We need to set a0 for init as it doesn't call - * cpu_set_syscall_retval to copy the value. We also - * need to set td_retval for the cases where we do. - */ - tf->tf_a[0] = td->td_retval[0] = stack; + tf->tf_a[0] = stack; tf->tf_sp = STACKALIGN(stack); tf->tf_ra = imgp->entry_addr; tf->tf_sepc = imgp->entry_addr; diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 9d917afafbb..d450d436379 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -1009,9 +1009,6 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) * header, it turns out that just always using TSO performs best. */ tf->tf_tstate = TSTATE_IE | TSTATE_PEF | TSTATE_MM_TSO; - - td->td_retval[0] = tf->tf_out[0]; - td->td_retval[1] = tf->tf_out[1]; } int From fd74a38251af5be1cba4f135c2beba2cef30476d Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 10:45:33 +0000 Subject: [PATCH 13/22] zdb: use a heap allocation instead of a huge array on stack SPA_MAXBLOCKSIZE is 16 MB and having such a large object on the stack is not nice in general and it could cause some confusing failures in the single-user mode where the default stack size of 8 MB is used. I expect that the upstream would make the same change. MFC after: 1 week --- cddl/contrib/opensolaris/cmd/zdb/zdb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c index 6ca504783a1..f588caaf205 100644 --- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c +++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c @@ -3724,7 +3724,7 @@ zdb_embedded_block(char *thing) { blkptr_t bp = { 0 }; unsigned long long *words = (void *)&bp; - char buf[SPA_MAXBLOCKSIZE]; + char *buf; int err; err = sscanf(thing, "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx:" @@ -3738,12 +3738,15 @@ zdb_embedded_block(char *thing) exit(1); } ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE); + buf = malloc(SPA_MAXBLOCKSIZE); err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp)); if (err != 0) { (void) printf("decode failed: %u\n", err); + free(buf); exit(1); } zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0); + free(buf); } static boolean_t From 8523ad24baffb1a9df8b6006d384ab340fa9cfbf Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:10:36 +0000 Subject: [PATCH 14/22] vmm/amd: improve iteration over IVHD (type 10h) entries in IVRS table Many 8-byte entries have zero at byte 4, so the second 4-byte part is skipped as a 4-byte padding entry. But not all 8-byte entries have that property and they get misinterpreted. A real example: 48 00 00 00 ff 01 00 01 This an 8-byte ACPI_IVRS_TYPE_SPECIAL entry for IOAPIC with ID 255 (bogus). It is reported as: ivhd0: Unknown dev entry:0xff Fortunately, it was completely harmless. Also, bail out early if we encounter an entry of a variable length type. We do not have proper handling for those yet. Reviewed by: anish --- sys/amd64/vmm/amd/ivrs_drv.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/sys/amd64/vmm/amd/ivrs_drv.c b/sys/amd64/vmm/amd/ivrs_drv.c index dc47717006a..5bc57fe9111 100755 --- a/sys/amd64/vmm/amd/ivrs_drv.c +++ b/sys/amd64/vmm/amd/ivrs_drv.c @@ -186,7 +186,8 @@ ivhd_dev_add_entry(struct amdvi_softc *softc, uint32_t start_id, static int ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc) { - ACPI_IVRS_DE_HEADER *de, *end; + ACPI_IVRS_DE_HEADER *de; + uint8_t *p, *end; int range_start_id = 0, range_end_id = 0; uint32_t *extended; uint8_t all_data = 0, range_data = 0; @@ -195,12 +196,15 @@ ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc) softc->start_dev_rid = ~0; softc->end_dev_rid = 0; - de = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd + - sizeof(ACPI_IVRS_HARDWARE)); - end = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd + - ivhd->Header.Length); + /* + * XXX The following actually depends on Header.Type and + * is only true for 0x10. + */ + p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE); + end = (uint8_t *)ivhd + ivhd->Header.Length; - while (de < (ACPI_IVRS_DE_HEADER *) end) { + while (p < end) { + de = (ACPI_IVRS_DE_HEADER *)p; softc->start_dev_rid = MIN(softc->start_dev_rid, de->Id); softc->end_dev_rid = MAX(softc->end_dev_rid, de->Id); switch (de->Type) { @@ -263,7 +267,15 @@ ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc) "WARN Too many device entries.\n"); return (EINVAL); } - de++; + if (de->Type < 0x40) + p += sizeof(ACPI_IVRS_DEVICE4); + else if (de->Type < 0x80) + p += sizeof(ACPI_IVRS_DEVICE8A); + else { + printf("Variable size IVHD type 0x%x not supported\n", + de->Type); + break; + } } KASSERT((softc->end_dev_rid >= softc->start_dev_rid), From 5a041f21838139b537cfe219a793331f577fcd1f Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:20:10 +0000 Subject: [PATCH 15/22] amd-vi: fix and extend definition of Command and Event Status Register (0x2020) The defined bits are the lower bits, not the higher ones. Also, the specification has been extended to define bits 0:18 and they all could potentially be interesting to us, so extend the width of the field accordingly. Reviewed by: anish --- sys/amd64/vmm/amd/amdvi_priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/amd64/vmm/amd/amdvi_priv.h b/sys/amd64/vmm/amd/amdvi_priv.h index c292d3ef988..1d589fd4d08 100755 --- a/sys/amd64/vmm/amd/amdvi_priv.h +++ b/sys/amd64/vmm/amd/amdvi_priv.h @@ -230,8 +230,8 @@ struct amdvi_ctrl { uint64_t :45; uint32_t evt_tail:19; uint64_t :45; - uint64_t :56; - uint8_t status:8; + uint8_t status:19; + uint64_t :45; uint64_t pad2; uint8_t :4; uint16_t ppr_head:15; From 53d580f984b0255b07aa65f0cba20aa21935d614 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:25:06 +0000 Subject: [PATCH 16/22] amd-vi: fix up r326152, the new width requires a wider type This is my brain-o from extending the width at the last moment. --- sys/amd64/vmm/amd/amdvi_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/amd64/vmm/amd/amdvi_priv.h b/sys/amd64/vmm/amd/amdvi_priv.h index 1d589fd4d08..8d4553fe1a3 100755 --- a/sys/amd64/vmm/amd/amdvi_priv.h +++ b/sys/amd64/vmm/amd/amdvi_priv.h @@ -230,7 +230,7 @@ struct amdvi_ctrl { uint64_t :45; uint32_t evt_tail:19; uint64_t :45; - uint8_t status:19; + uint32_t status:19; uint64_t :45; uint64_t pad2; uint8_t :4; From b7d2b5d5b15981b5901c36c66d000735e85788c8 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Fri, 24 Nov 2017 11:25:53 +0000 Subject: [PATCH 17/22] Add SPDX line. --- sys/netinet/sctp_ss_functions.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/netinet/sctp_ss_functions.c b/sys/netinet/sctp_ss_functions.c index 22d3deb58fd..3099c4893c4 100644 --- a/sys/netinet/sctp_ss_functions.c +++ b/sys/netinet/sctp_ss_functions.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2010-2012, by Michael Tuexen. All rights reserved. * Copyright (c) 2010-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2010-2012, by Robin Seggelmann. All rights reserved. From dee38cdc2ab150a750230b91e5feeba8057ffdb6 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:34:46 +0000 Subject: [PATCH 18/22] amd-vi: print some additional details for INVALID_DEVICE_REQUEST event Namely, the type of the hardware event and whether the transaction was a translation request. Reviewed by: anish --- sys/amd64/vmm/amd/amdvi_hw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/amd64/vmm/amd/amdvi_hw.c b/sys/amd64/vmm/amd/amdvi_hw.c index 22d4a12e321..af4f56479d0 100644 --- a/sys/amd64/vmm/amd/amdvi_hw.c +++ b/sys/amd64/vmm/amd/amdvi_hw.c @@ -705,8 +705,9 @@ amdvi_decode_evt(struct amdvi_event *evt) break; case AMDVI_EVENT_INVALID_DTE_REQ: - printf("\t[INV_DTE devid:0x%x addr:0x%lx", - evt->devid, evt->addr); + printf("\t[INV_DTE devid:0x%x addr:0x%lx type:0x%x tr:%d]\n", + evt->devid, evt->addr, evt->flag >> 9, + (evt->flag >> 8) & 1); break; case AMDVI_EVENT_INVALID_PPR_REQ: From eb6c9c128c9e61ca1db9d56d7cc6559fca79de42 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:35:43 +0000 Subject: [PATCH 19/22] amd-vi: small improvements to event printing Ensure that an opening bracket always has a matching closing one. Ensure that there is always a new-line at the end of a report line. Also, add a space before the printed event flag. Reviewed by: anish --- sys/amd64/vmm/amd/amdvi_hw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/amd64/vmm/amd/amdvi_hw.c b/sys/amd64/vmm/amd/amdvi_hw.c index af4f56479d0..af6ebb51bbc 100644 --- a/sys/amd64/vmm/amd/amdvi_hw.c +++ b/sys/amd64/vmm/amd/amdvi_hw.c @@ -582,7 +582,7 @@ amdvi_decode_evt_flag(uint16_t flag) { flag &= AMDVI_EVENT_FLAG_MASK; - printf("0x%b]\n", flag, + printf(" 0x%b]\n", flag, "\020" "\001GN" "\002NX" @@ -692,7 +692,7 @@ amdvi_decode_evt(struct amdvi_event *evt) case AMDVI_EVENT_ILLEGAL_CMD: /* FALL THROUGH */ case AMDVI_EVENT_CMD_HW_ERROR: - printf("\t[%s EVT]", (evt->opcode == AMDVI_EVENT_ILLEGAL_CMD) ? + printf("\t[%s EVT]\n", (evt->opcode == AMDVI_EVENT_ILLEGAL_CMD) ? "ILLEGAL CMD" : "CMD HW ERR"); cmd = (struct amdvi_cmd *)PHYS_TO_DMAP(evt->addr); printf("\tCMD opcode= 0x%x 0x%x 0x%x 0x%lx\n", @@ -700,7 +700,7 @@ amdvi_decode_evt(struct amdvi_event *evt) break; case AMDVI_EVENT_IOTLB_TIMEOUT: - printf("\t[IOTLB_INV_TIMEOUT devid:0x%x addr:0x%lx", + printf("\t[IOTLB_INV_TIMEOUT devid:0x%x addr:0x%lx]\n", evt->devid, evt->addr); break; @@ -716,7 +716,7 @@ amdvi_decode_evt(struct amdvi_event *evt) break; default: - printf("Unsupported AMD-Vi event:%d", evt->opcode); + printf("Unsupported AMD-Vi event:%d\n", evt->opcode); } } From 685c54fc6abcff47d67faa9ebeadd8fb836936ff Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:36:35 +0000 Subject: [PATCH 20/22] amd-vi: use correct type for pci_rid, start_dev_rid, end_dev_rid sysctls Previously, the values could look confusing because of unrelated bits from adjacent memory. Reviewed by: anish --- sys/amd64/vmm/amd/amdvi_hw.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sys/amd64/vmm/amd/amdvi_hw.c b/sys/amd64/vmm/amd/amdvi_hw.c index af6ebb51bbc..3478262a734 100644 --- a/sys/amd64/vmm/amd/amdvi_hw.c +++ b/sys/amd64/vmm/amd/amdvi_hw.c @@ -989,15 +989,12 @@ amdvi_add_sysctl(struct amdvi_softc *softc) &softc->event_intr_cnt, "Event interrupt count"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "command_count", CTLFLAG_RD, &softc->total_cmd, "Command submitted count"); - SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "pci_rid", CTLFLAG_RD, - (int *)&softc->pci_rid, 0, - "IOMMU RID"); - SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "start_dev_rid", CTLFLAG_RD, - (int *)&softc->start_dev_rid, 0, - "Start of device under this IOMMU"); - SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "end_dev_rid", CTLFLAG_RD, - (int *)&softc->end_dev_rid, 0, - "End of device under this IOMMU"); + SYSCTL_ADD_U16(ctx, child, OID_AUTO, "pci_rid", CTLFLAG_RD, + &softc->pci_rid, 0, "IOMMU RID"); + SYSCTL_ADD_U16(ctx, child, OID_AUTO, "start_dev_rid", CTLFLAG_RD, + &softc->start_dev_rid, 0, "Start of device under this IOMMU"); + SYSCTL_ADD_U16(ctx, child, OID_AUTO, "end_dev_rid", CTLFLAG_RD, + &softc->end_dev_rid, 0, "End of device under this IOMMU"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "command_head", CTLTYPE_UINT | CTLFLAG_RD, softc, 0, amdvi_handle_sysctl, "IU", "Command head"); From a3bbbd5e403410c998d9b05c5e6eea5e213cc0da Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 24 Nov 2017 11:37:41 +0000 Subject: [PATCH 21/22] amd-vi: a small whitespace cleanup Reviewed by: anish --- sys/amd64/vmm/amd/ivrs_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/amd64/vmm/amd/ivrs_drv.c b/sys/amd64/vmm/amd/ivrs_drv.c index 5bc57fe9111..bc30d83c6ca 100755 --- a/sys/amd64/vmm/amd/ivrs_drv.c +++ b/sys/amd64/vmm/amd/ivrs_drv.c @@ -88,7 +88,7 @@ ivrs_hdr_iterate_tbl(ivhd_iter_t iter, void *arg) if (!iter(ivrs_hdr, arg)) return; break; - + case ACPI_IVRS_TYPE_MEMORY1: case ACPI_IVRS_TYPE_MEMORY2: case ACPI_IVRS_TYPE_MEMORY3: @@ -96,7 +96,7 @@ ivrs_hdr_iterate_tbl(ivhd_iter_t iter, void *arg) return; break; - + default: printf("AMD-Vi:Not IVHD/IVMD type(%d)", ivrs_hdr->Type); From 322f006ecce27c190a375cd4b2bcdde4d1257277 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 24 Nov 2017 12:10:42 +0000 Subject: [PATCH 22/22] Implement atomic_fetchadd_64() for i386. This function is needed by the atomic64 header file in the LinuxKPI for i386. Reviewed by: kib MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/i386/include/atomic.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sys/i386/include/atomic.h b/sys/i386/include/atomic.h index c167cf5c0fa..7cd5b0d2a7e 100644 --- a/sys/i386/include/atomic.h +++ b/sys/i386/include/atomic.h @@ -129,6 +129,7 @@ int atomic_cmpset_64(volatile uint64_t *, uint64_t, uint64_t); uint64_t atomic_load_acq_64(volatile uint64_t *); void atomic_store_rel_64(volatile uint64_t *, uint64_t); uint64_t atomic_swap_64(volatile uint64_t *, uint64_t); +uint64_t atomic_fetchadd_64(volatile uint64_t *, uint64_t); #else /* !KLD_MODULE && __GNUCLIKE_ASM */ @@ -565,6 +566,17 @@ atomic_swap_64(volatile uint64_t *p, uint64_t v) return (atomic_swap_64_i586(p, v)); } +static __inline uint64_t +atomic_fetchadd_64(volatile uint64_t *p, uint64_t v) +{ + + for (;;) { + uint64_t t = *p; + if (atomic_cmpset_64(p, t, t + v)) + return (t); + } +} + #endif /* _KERNEL */ #endif /* KLD_MODULE || !__GNUCLIKE_ASM */