Merge tag 'io_uring-5.19-2022-06-24' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Jun 2022 18:02:26 +0000 (11:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Jun 2022 18:02:26 +0000 (11:02 -0700)
Pull io_uring fixes from Jens Axboe:
 "A few fixes that should go into the 5.19 release. All are fixing
  issues that either happened in this release, or going to stable.

  In detail:

   - A small series of fixlets for the poll handling, all destined for
     stable (Pavel)

   - Fix a merge error from myself that caused a potential -EINVAL for
     the recv/recvmsg flag setting (me)

   - Fix a kbuf recycling issue for partial IO (me)

   - Use the original request for the inflight tracking (me)

   - Fix an issue introduced this merge window with trace points using a
     custom decoder function, which won't work for perf (Dylan)"

* tag 'io_uring-5.19-2022-06-24' of git://git.kernel.dk/linux-block:
  io_uring: use original request task for inflight tracking
  io_uring: move io_uring_get_opcode out of TP_printk
  io_uring: fix double poll leak on repolling
  io_uring: fix wrong arm_poll error handling
  io_uring: fail links when poll fails
  io_uring: fix req->apoll_events
  io_uring: fix merge error in checking send/recv addr2 flags
  io_uring: mark reissue requests with REQ_F_PARTIAL_IO

412 files changed:
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/admin-guide/hw-vuln/index.rst
Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst [new file with mode: 0644]
Documentation/admin-guide/kernel-parameters.txt
Documentation/devicetree/bindings/hwmon/ti,tmp401.yaml
Documentation/devicetree/bindings/interrupt-controller/socionext,uniphier-aidet.yaml
Documentation/filesystems/ext4/attributes.rst
Documentation/filesystems/ext4/bigalloc.rst
Documentation/filesystems/ext4/bitmaps.rst
Documentation/filesystems/ext4/blockgroup.rst
Documentation/filesystems/ext4/blockmap.rst
Documentation/filesystems/ext4/checksums.rst
Documentation/filesystems/ext4/directory.rst
Documentation/filesystems/ext4/eainode.rst
Documentation/filesystems/ext4/group_descr.rst
Documentation/filesystems/ext4/ifork.rst
Documentation/filesystems/ext4/inlinedata.rst
Documentation/filesystems/ext4/inodes.rst
Documentation/filesystems/ext4/journal.rst
Documentation/filesystems/ext4/mmp.rst
Documentation/filesystems/ext4/overview.rst
Documentation/filesystems/ext4/special_inodes.rst
Documentation/filesystems/ext4/super.rst
Documentation/loongarch/introduction.rst
Documentation/loongarch/irq-chip-model.rst
Documentation/networking/ip-sysctl.rst
Documentation/networking/phy.rst
Documentation/translations/zh_CN/loongarch/introduction.rst
Documentation/translations/zh_CN/loongarch/irq-chip-model.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/at91-sama5d3_ksz9477_evb.dts
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/virt.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/entry-ftrace.S
arch/arm64/kernel/ftrace.c
arch/arm64/kernel/setup.c
arch/arm64/kvm/arch_timer.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/fpsimd.c
arch/arm64/kvm/hyp/nvhe/mem_protect.c
arch/arm64/kvm/hyp/nvhe/sys_regs.c
arch/arm64/kvm/vgic/vgic-mmio-v2.c
arch/arm64/kvm/vgic/vgic-mmio-v3.c
arch/arm64/kvm/vgic/vgic-mmio.c
arch/arm64/kvm/vgic/vgic-mmio.h
arch/arm64/kvm/vmid.c
arch/arm64/mm/cache.S
arch/loongarch/kernel/vmlinux.lds.S
arch/mips/boot/dts/ingenic/x1000.dtsi
arch/mips/boot/dts/ingenic/x1830.dtsi
arch/mips/generic/board-ranchu.c
arch/mips/lantiq/falcon/sysctrl.c
arch/mips/lantiq/irq.c
arch/mips/lantiq/xway/sysctrl.c
arch/mips/mti-malta/malta-time.c
arch/mips/pic32/pic32mzda/init.c
arch/mips/pic32/pic32mzda/time.c
arch/mips/ralink/of.c
arch/mips/vr41xx/common/icu.c
arch/riscv/Kconfig
arch/riscv/Kconfig.erratas
arch/riscv/boot/dts/microchip/mpfs.dtsi
arch/riscv/kernel/cpufeature.c
arch/riscv/kvm/vmid.c
arch/x86/coco/tdx/tdx.c
arch/x86/hyperv/hv_init.c
arch/x86/hyperv/ivm.c
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/e820/api.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/setup.h
arch/x86/kernel/Makefile
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/ftrace_64.S
arch/x86/kernel/resource.c
arch/x86/kernel/setup.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/avic.c
arch/x86/kvm/svm/nested.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/net/bpf_jit_comp.c
arch/x86/pci/acpi.c
block/bfq-iosched.c
block/blk-mq-sched.c
block/blk-mq.c
block/kyber-iosched.c
block/mq-deadline.c
certs/.gitignore
certs/Makefile
certs/blacklist.c
certs/blacklist_hashes.c
certs/common.c [deleted file]
certs/common.h [deleted file]
certs/system_keyring.c
crypto/Kconfig
crypto/Makefile
crypto/asymmetric_keys/Kconfig
crypto/asymmetric_keys/Makefile
crypto/asymmetric_keys/selftest.c [new file with mode: 0644]
crypto/asymmetric_keys/x509_loader.c [new file with mode: 0644]
crypto/asymmetric_keys/x509_parser.h
crypto/asymmetric_keys/x509_public_key.c
crypto/memneq.c [deleted file]
drivers/base/cpu.c
drivers/base/init.c
drivers/bus/fsl-mc/fsl-mc-bus.c
drivers/char/lp.c
drivers/char/random.c
drivers/clocksource/hyperv_timer.c
drivers/comedi/drivers/vmk80xx.c
drivers/dma-buf/udmabuf.c
drivers/firewire/core-cdev.c
drivers/firewire/core-device.c
drivers/firmware/efi/sysfb_efi.c
drivers/gpio/gpio-vr41xx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gt/intel_gt.c
drivers/gpu/drm/i915/gt/intel_gt_sysfs.c
drivers/gpu/drm/i915/gt/intel_gt_sysfs.h
drivers/gpu/drm/i915/gt/intel_gt_types.h
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_device.c
drivers/gpu/drm/ttm/ttm_resource.c
drivers/hid/hid-hyperv.c
drivers/hv/channel_mgmt.c
drivers/hv/hv_kvp.c
drivers/hv/vmbus_drv.c
drivers/hwmon/asus-ec-sensors.c
drivers/hwmon/occ/common.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-npcm7xx.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-apple-aic.c
drivers/irqchip/irq-gic-realview.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-loongson-liointc.c
drivers/irqchip/irq-realtek-rtl.c
drivers/irqchip/irq-uniphier-aidet.c
drivers/md/dm-log.c
drivers/md/dm-raid.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid5-ppl.c
drivers/misc/atmel-ssc.c
drivers/misc/cardreader/rts5261.c
drivers/misc/eeprom/at25.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/hw-me.c
drivers/misc/mei/pci-me.c
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/sdhci-pci-o2micro.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/qca8k.c
drivers/net/dsa/qca8k.h
drivers/net/ethernet/amd/xgbe/xgbe-platform.c
drivers/net/ethernet/broadcom/bgmac-bcma.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/huawei/hinic/hinic_devlink.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_ptp.h
drivers/net/ethernet/intel/ice/ice_tc_lib.c
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/ice/ice_virtchnl.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h
drivers/net/ethernet/xilinx/xilinx_axienet.h
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/hamradio/6pack.c
drivers/net/phy/aquantia_main.c
drivers/net/phy/at803x.c
drivers/net/phy/smsc.c
drivers/net/usb/ax88179_178a.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/storvsc_drv.c
drivers/staging/olpc_dcon/Kconfig
drivers/staging/r8188eu/core/rtw_xmit.c
drivers/staging/r8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
drivers/tty/goldfish.c
drivers/tty/n_gsm.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/sysrq.c
drivers/ufs/core/ufshcd.c
drivers/usb/cdns3/cdnsp-ring.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/udc/lpc32xx_udc.c
drivers/usb/host/xhci.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/io_usbvend.h
drivers/usb/serial/option.c
drivers/watchdog/gxp-wdt.c
fs/9p/fid.c
fs/9p/vfs_addr.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/afs/inode.c
fs/attr.c
fs/btrfs/disk-io.c
fs/btrfs/super.c
fs/cifs/sess.c
fs/cifs/smb2pdu.c
fs/cifs/trace.h
fs/ext2/dir.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/page-io.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/jbd2/transaction.c
fs/nfs/callback_proc.c
fs/nfs/dir.c
fs/nfs/nfs4file.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/tracefs/inode.c
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr.h
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_da_btree.h
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_xattr.c
include/drm/drm_atomic.h
include/drm/ttm/ttm_resource.h
include/keys/asymmetric-type.h
include/linux/backing-dev.h
include/linux/blkdev.h
include/linux/console.h
include/linux/cpu.h
include/linux/netfs.h
include/linux/objtool.h
include/linux/printk.h
include/linux/ratelimit_types.h
include/linux/serial_core.h
include/linux/visorbus.h [deleted file]
include/linux/vmalloc.h
include/net/inet_connection_sock.h
include/net/inet_hashtables.h
include/net/inet_sock.h
include/net/sock.h
kernel/auditsc.c
kernel/bpf/btf.c
kernel/cfi.c
kernel/hung_task.c
kernel/irq/chip.c
kernel/locking/lockdep.c
kernel/panic.c
kernel/power/hibernate.c
kernel/printk/printk.c
kernel/rcu/tree_stall.h
kernel/reboot.c
kernel/sched/core.c
kernel/sched/sched.h
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/rethook.c
kernel/trace/trace.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_uprobe.c
kernel/watchdog.c
kernel/watchdog_hld.c
lib/Kconfig
lib/Kconfig.ubsan
lib/Makefile
lib/crypto/Kconfig
lib/memneq.c [new file with mode: 0644]
mm/backing-dev.c
mm/filemap.c
mm/huge_memory.c
mm/migrate.c
mm/readahead.c
mm/slub.c
mm/usercopy.c
mm/vmalloc.c
net/ax25/af_ax25.c
net/core/dev.c
net/core/filter.c
net/core/net-sysfs.c
net/core/skmsg.c
net/dccp/proto.c
net/ethtool/eeprom.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/ping.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv6/ip6_gre.c
net/netfilter/nf_dup_netdev.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/nft_meta.c
net/netfilter/nft_numgen.c
net/openvswitch/flow.c
net/sched/sch_netem.c
net/sunrpc/clnt.c
net/tipc/core.c
net/tls/tls_main.c
net/xdp/xsk.c
samples/fprobe/fprobe_example.c
scripts/faddr2line
security/selinux/hooks.c
sound/core/memalloc.c
sound/hda/hdac_i915.c
sound/hda/intel-dsp-config.c
sound/hda/intel-nhlt.c
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/usb/mixer_us16x08.c
sound/x86/intel_hdmi_audio.c
tools/arch/arm64/include/asm/cputype.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/include/linux/objtool.h
tools/include/uapi/linux/prctl.h
tools/lib/perf/evsel.c
tools/perf/tests/bp_account.c
tools/perf/tests/expr.c
tools/perf/tests/shell/lib/perf_csv_output_lint.py [deleted file]
tools/perf/tests/shell/stat+csv_output.sh
tools/perf/tests/shell/test_arm_callgraph_fp.sh
tools/perf/tests/topology.c
tools/perf/trace/beauty/include/linux/socket.h
tools/perf/util/arm-spe.c
tools/perf/util/expr.l
tools/perf/util/metricgroup.c
tools/perf/util/unwind-libunwind-local.c
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c
tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
tools/testing/selftests/bpf/prog_tests/tailcalls.c
tools/testing/selftests/bpf/progs/kprobe_multi.c
tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c [new file with mode: 0644]
tools/testing/selftests/dma/Makefile
tools/testing/selftests/dma/dma_map_benchmark.c
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/dirty_log_perf_test.c
tools/testing/selftests/kvm/include/perf_test_util.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/include/x86_64/vmx.h
tools/testing/selftests/kvm/lib/perf_test_util.c
tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c [new file with mode: 0644]
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/max_guest_memory_test.c
tools/testing/selftests/kvm/x86_64/mmu_role_test.c
tools/testing/selftests/lib.mk
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/bind_bhash_test.c [deleted file]
tools/testing/selftests/net/fcnal-test.sh
tools/testing/selftests/netfilter/nft_concat_range.sh
tools/testing/selftests/vm/gup_test.c
tools/testing/selftests/vm/ksm_tests.c
virt/kvm/kvm_main.c

index 2ad01ca..bcc974d 100644 (file)
@@ -526,6 +526,7 @@ What:               /sys/devices/system/cpu/vulnerabilities
                /sys/devices/system/cpu/vulnerabilities/srbds
                /sys/devices/system/cpu/vulnerabilities/tsx_async_abort
                /sys/devices/system/cpu/vulnerabilities/itlb_multihit
+               /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:   Information about CPU vulnerabilities
index 8cbc711..4df436e 100644 (file)
@@ -17,3 +17,4 @@ are configurable at compile, boot or run time.
    special-register-buffer-data-sampling.rst
    core-scheduling.rst
    l1d_flush.rst
+   processor_mmio_stale_data.rst
diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
new file mode 100644 (file)
index 0000000..9393c50
--- /dev/null
@@ -0,0 +1,246 @@
+=========================================
+Processor MMIO Stale Data Vulnerabilities
+=========================================
+
+Processor MMIO Stale Data Vulnerabilities are a class of memory-mapped I/O
+(MMIO) vulnerabilities that can expose data. The sequences of operations for
+exposing data range from simple to very complex. Because most of the
+vulnerabilities require the attacker to have access to MMIO, many environments
+are not affected. System environments using virtualization where MMIO access is
+provided to untrusted guests may need mitigation. These vulnerabilities are
+not transient execution attacks. However, these vulnerabilities may propagate
+stale data into core fill buffers where the data can subsequently be inferred
+by an unmitigated transient execution attack. Mitigation for these
+vulnerabilities includes a combination of microcode update and software
+changes, depending on the platform and usage model. Some of these mitigations
+are similar to those used to mitigate Microarchitectural Data Sampling (MDS) or
+those used to mitigate Special Register Buffer Data Sampling (SRBDS).
+
+Data Propagators
+================
+Propagators are operations that result in stale data being copied or moved from
+one microarchitectural buffer or register to another. Processor MMIO Stale Data
+Vulnerabilities are operations that may result in stale data being directly
+read into an architectural, software-visible state or sampled from a buffer or
+register.
+
+Fill Buffer Stale Data Propagator (FBSDP)
+-----------------------------------------
+Stale data may propagate from fill buffers (FB) into the non-coherent portion
+of the uncore on some non-coherent writes. Fill buffer propagation by itself
+does not make stale data architecturally visible. Stale data must be propagated
+to a location where it is subject to reading or sampling.
+
+Sideband Stale Data Propagator (SSDP)
+-------------------------------------
+The sideband stale data propagator (SSDP) is limited to the client (including
+Intel Xeon server E3) uncore implementation. The sideband response buffer is
+shared by all client cores. For non-coherent reads that go to sideband
+destinations, the uncore logic returns 64 bytes of data to the core, including
+both requested data and unrequested stale data, from a transaction buffer and
+the sideband response buffer. As a result, stale data from the sideband
+response and transaction buffers may now reside in a core fill buffer.
+
+Primary Stale Data Propagator (PSDP)
+------------------------------------
+The primary stale data propagator (PSDP) is limited to the client (including
+Intel Xeon server E3) uncore implementation. Similar to the sideband response
+buffer, the primary response buffer is shared by all client cores. For some
+processors, MMIO primary reads will return 64 bytes of data to the core fill
+buffer including both requested data and unrequested stale data. This is
+similar to the sideband stale data propagator.
+
+Vulnerabilities
+===============
+Device Register Partial Write (DRPW) (CVE-2022-21166)
+-----------------------------------------------------
+Some endpoint MMIO registers incorrectly handle writes that are smaller than
+the register size. Instead of aborting the write or only copying the correct
+subset of bytes (for example, 2 bytes for a 2-byte write), more bytes than
+specified by the write transaction may be written to the register. On
+processors affected by FBSDP, this may expose stale data from the fill buffers
+of the core that created the write transaction.
+
+Shared Buffers Data Sampling (SBDS) (CVE-2022-21125)
+----------------------------------------------------
+After propagators may have moved data around the uncore and copied stale data
+into client core fill buffers, processors affected by MFBDS can leak data from
+the fill buffer. It is limited to the client (including Intel Xeon server E3)
+uncore implementation.
+
+Shared Buffers Data Read (SBDR) (CVE-2022-21123)
+------------------------------------------------
+It is similar to Shared Buffer Data Sampling (SBDS) except that the data is
+directly read into the architectural software-visible state. It is limited to
+the client (including Intel Xeon server E3) uncore implementation.
+
+Affected Processors
+===================
+Not all the CPUs are affected by all the variants. For instance, most
+processors for the server market (excluding Intel Xeon E3 processors) are
+impacted by only Device Register Partial Write (DRPW).
+
+Below is the list of affected Intel processors [#f1]_:
+
+   ===================  ============  =========
+   Common name          Family_Model  Steppings
+   ===================  ============  =========
+   HASWELL_X            06_3FH        2,4
+   SKYLAKE_L            06_4EH        3
+   BROADWELL_X          06_4FH        All
+   SKYLAKE_X            06_55H        3,4,6,7,11
+   BROADWELL_D          06_56H        3,4,5
+   SKYLAKE              06_5EH        3
+   ICELAKE_X            06_6AH        4,5,6
+   ICELAKE_D            06_6CH        1
+   ICELAKE_L            06_7EH        5
+   ATOM_TREMONT_D       06_86H        All
+   LAKEFIELD            06_8AH        1
+   KABYLAKE_L           06_8EH        9 to 12
+   ATOM_TREMONT         06_96H        1
+   ATOM_TREMONT_L       06_9CH        0
+   KABYLAKE             06_9EH        9 to 13
+   COMETLAKE            06_A5H        2,3,5
+   COMETLAKE_L          06_A6H        0,1
+   ROCKETLAKE           06_A7H        1
+   ===================  ============  =========
+
+If a CPU is in the affected processor list, but not affected by a variant, it
+is indicated by new bits in MSR IA32_ARCH_CAPABILITIES. As described in a later
+section, mitigation largely remains the same for all the variants, i.e. to
+clear the CPU fill buffers via VERW instruction.
+
+New bits in MSRs
+================
+Newer processors and microcode update on existing affected processors added new
+bits to IA32_ARCH_CAPABILITIES MSR. These bits can be used to enumerate
+specific variants of Processor MMIO Stale Data vulnerabilities and mitigation
+capability.
+
+MSR IA32_ARCH_CAPABILITIES
+--------------------------
+Bit 13 - SBDR_SSDP_NO - When set, processor is not affected by either the
+        Shared Buffers Data Read (SBDR) vulnerability or the sideband stale
+        data propagator (SSDP).
+Bit 14 - FBSDP_NO - When set, processor is not affected by the Fill Buffer
+        Stale Data Propagator (FBSDP).
+Bit 15 - PSDP_NO - When set, processor is not affected by Primary Stale Data
+        Propagator (PSDP).
+Bit 17 - FB_CLEAR - When set, VERW instruction will overwrite CPU fill buffer
+        values as part of MD_CLEAR operations. Processors that do not
+        enumerate MDS_NO (meaning they are affected by MDS) but that do
+        enumerate support for both L1D_FLUSH and MD_CLEAR implicitly enumerate
+        FB_CLEAR as part of their MD_CLEAR support.
+Bit 18 - FB_CLEAR_CTRL - Processor supports read and write to MSR
+        IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]. On such processors, the FB_CLEAR_DIS
+        bit can be set to cause the VERW instruction to not perform the
+        FB_CLEAR action. Not all processors that support FB_CLEAR will support
+        FB_CLEAR_CTRL.
+
+MSR IA32_MCU_OPT_CTRL
+---------------------
+Bit 3 - FB_CLEAR_DIS - When set, VERW instruction does not perform the FB_CLEAR
+action. This may be useful to reduce the performance impact of FB_CLEAR in
+cases where system software deems it warranted (for example, when performance
+is more critical, or the untrusted software has no MMIO access). Note that
+FB_CLEAR_DIS has no impact on enumeration (for example, it does not change
+FB_CLEAR or MD_CLEAR enumeration) and it may not be supported on all processors
+that enumerate FB_CLEAR.
+
+Mitigation
+==========
+Like MDS, all variants of Processor MMIO Stale Data vulnerabilities  have the
+same mitigation strategy to force the CPU to clear the affected buffers before
+an attacker can extract the secrets.
+
+This is achieved by using the otherwise unused and obsolete VERW instruction in
+combination with a microcode update. The microcode clears the affected CPU
+buffers when the VERW instruction is executed.
+
+Kernel reuses the MDS function to invoke the buffer clearing:
+
+       mds_clear_cpu_buffers()
+
+On MDS affected CPUs, the kernel already invokes CPU buffer clear on
+kernel/userspace, hypervisor/guest and C-state (idle) transitions. No
+additional mitigation is needed on such CPUs.
+
+For CPUs not affected by MDS or TAA, mitigation is needed only for the attacker
+with MMIO capability. Therefore, VERW is not required for kernel/userspace. For
+virtualization case, VERW is only needed at VMENTER for a guest with MMIO
+capability.
+
+Mitigation points
+-----------------
+Return to user space
+^^^^^^^^^^^^^^^^^^^^
+Same mitigation as MDS when affected by MDS/TAA, otherwise no mitigation
+needed.
+
+C-State transition
+^^^^^^^^^^^^^^^^^^
+Control register writes by CPU during C-state transition can propagate data
+from fill buffer to uncore buffers. Execute VERW before C-state transition to
+clear CPU fill buffers.
+
+Guest entry point
+^^^^^^^^^^^^^^^^^
+Same mitigation as MDS when processor is also affected by MDS/TAA, otherwise
+execute VERW at VMENTER only for MMIO capable guests. On CPUs not affected by
+MDS/TAA, guest without MMIO access cannot extract secrets using Processor MMIO
+Stale Data vulnerabilities, so there is no need to execute VERW for such guests.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The kernel command line allows to control the Processor MMIO Stale Data
+mitigations at boot time with the option "mmio_stale_data=". The valid
+arguments for this option are:
+
+  ==========  =================================================================
+  full        If the CPU is vulnerable, enable mitigation; CPU buffer clearing
+              on exit to userspace and when entering a VM. Idle transitions are
+              protected as well. It does not automatically disable SMT.
+  full,nosmt  Same as full, with SMT disabled on vulnerable CPUs. This is the
+              complete mitigation.
+  off         Disables mitigation completely.
+  ==========  =================================================================
+
+If the CPU is affected and mmio_stale_data=off is not supplied on the kernel
+command line, then the kernel selects the appropriate mitigation.
+
+Mitigation status information
+-----------------------------
+The Linux kernel provides a sysfs interface to enumerate the current
+vulnerability status of the system: whether the system is vulnerable, and
+which mitigations are active. The relevant sysfs file is:
+
+       /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
+
+The possible values in this file are:
+
+  .. list-table::
+
+     * - 'Not affected'
+       - The processor is not vulnerable
+     * - 'Vulnerable'
+       - The processor is vulnerable, but no mitigation enabled
+     * - 'Vulnerable: Clear CPU buffers attempted, no microcode'
+       - The processor is vulnerable, but microcode is not updated. The
+         mitigation is enabled on a best effort basis.
+     * - 'Mitigation: Clear CPU buffers'
+       - The processor is vulnerable and the CPU buffer clearing mitigation is
+         enabled.
+
+If the processor is vulnerable then the following information is appended to
+the above information:
+
+  ========================  ===========================================
+  'SMT vulnerable'          SMT is enabled
+  'SMT disabled'            SMT is disabled
+  'SMT Host state unknown'  Kernel runs in a VM, Host SMT state unknown
+  ========================  ===========================================
+
+References
+----------
+.. [#f1] Affected Processors
+   https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
index 8090130..2522b11 100644 (file)
 
                        protected: nVHE-based mode with support for guests whose
                                   state is kept private from the host.
-                                  Not valid if the kernel is running in EL2.
 
                        Defaults to VHE/nVHE based on hardware support. Setting
                        mode to "protected" will disable kexec and hibernation
                                               srbds=off [X86,INTEL]
                                               no_entry_flush [PPC]
                                               no_uaccess_flush [PPC]
+                                              mmio_stale_data=off [X86]
 
                                Exceptions:
                                               This does not have any effect on
                                Equivalent to: l1tf=flush,nosmt [X86]
                                               mds=full,nosmt [X86]
                                               tsx_async_abort=full,nosmt [X86]
+                                              mmio_stale_data=full,nosmt [X86]
 
        mminit_loglevel=
                        [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
                        log everything. Information is printed at KERN_DEBUG
                        so loglevel=8 may also need to be specified.
 
+       mmio_stale_data=
+                       [X86,INTEL] Control mitigation for the Processor
+                       MMIO Stale Data vulnerabilities.
+
+                       Processor MMIO Stale Data is a class of
+                       vulnerabilities that may expose data after an MMIO
+                       operation. Exposed data could originate or end in
+                       the same CPU buffers as affected by MDS and TAA.
+                       Therefore, similar to MDS and TAA, the mitigation
+                       is to clear the affected CPU buffers.
+
+                       This parameter controls the mitigation. The
+                       options are:
+
+                       full       - Enable mitigation on vulnerable CPUs
+
+                       full,nosmt - Enable mitigation and disable SMT on
+                                    vulnerable CPUs.
+
+                       off        - Unconditionally disable mitigation
+
+                       On MDS or TAA affected machines,
+                       mmio_stale_data=off can be prevented by an active
+                       MDS or TAA mitigation as these vulnerabilities are
+                       mitigated with the same mechanism so in order to
+                       disable this mitigation, you need to specify
+                       mds=off and tsx_async_abort=off too.
+
+                       Not specifying this option is equivalent to
+                       mmio_stale_data=full.
+
+                       For details see:
+                       Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
+
        module.sig_enforce
                        [KNL] When CONFIG_MODULE_SIG is set, this means that
                        modules without (valid) signatures will fail to load.
index fe0ac08..0e8ddf0 100644 (file)
@@ -40,9 +40,8 @@ properties:
       value to be used for converting remote channel measurements to
       temperature.
     $ref: /schemas/types.yaml#/definitions/int32
-    items:
-      minimum: -128
-      maximum: 127
+    minimum: -128
+    maximum: 127
 
   ti,beta-compensation:
     description:
index f89ebde..de7c5e5 100644 (file)
@@ -30,6 +30,7 @@ properties:
       - socionext,uniphier-ld11-aidet
       - socionext,uniphier-ld20-aidet
       - socionext,uniphier-pxs3-aidet
+      - socionext,uniphier-nx1-aidet
 
   reg:
     maxItems: 1
index 871d2da..8781469 100644 (file)
@@ -13,8 +13,8 @@ disappeared as of Linux 3.0.
 
 There are two places where extended attributes can be found. The first
 place is between the end of each inode entry and the beginning of the
-next inode entry. For example, if inode.i\_extra\_isize = 28 and
-sb.inode\_size = 256, then there are 256 - (128 + 28) = 100 bytes
+next inode entry. For example, if inode.i_extra_isize = 28 and
+sb.inode_size = 256, then there are 256 - (128 + 28) = 100 bytes
 available for in-inode extended attribute storage. The second place
 where extended attributes can be found is in the block pointed to by
 ``inode.i_file_acl``. As of Linux 3.11, it is not possible for this
@@ -38,8 +38,8 @@ Extended attributes, when stored after the inode, have a header
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - h\_magic
+     - __le32
+     - h_magic
      - Magic number for identification, 0xEA020000. This value is set by the
        Linux driver, though e2fsprogs doesn't seem to check it(?)
 
@@ -55,28 +55,28 @@ The beginning of an extended attribute block is in
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - h\_magic
+     - __le32
+     - h_magic
      - Magic number for identification, 0xEA020000.
    * - 0x4
-     - \_\_le32
-     - h\_refcount
+     - __le32
+     - h_refcount
      - Reference count.
    * - 0x8
-     - \_\_le32
-     - h\_blocks
+     - __le32
+     - h_blocks
      - Number of disk blocks used.
    * - 0xC
-     - \_\_le32
-     - h\_hash
+     - __le32
+     - h_hash
      - Hash value of all attributes.
    * - 0x10
-     - \_\_le32
-     - h\_checksum
+     - __le32
+     - h_checksum
      - Checksum of the extended attribute block.
    * - 0x14
-     - \_\_u32
-     - h\_reserved[3]
+     - __u32
+     - h_reserved[3]
      - Zero.
 
 The checksum is calculated against the FS UUID, the 64-bit block number
@@ -100,46 +100,46 @@ Attributes stored inside an inode do not need be stored in sorted order.
      - Name
      - Description
    * - 0x0
-     - \_\_u8
-     - e\_name\_len
+     - __u8
+     - e_name_len
      - Length of name.
    * - 0x1
-     - \_\_u8
-     - e\_name\_index
+     - __u8
+     - e_name_index
      - Attribute name index. There is a discussion of this below.
    * - 0x2
-     - \_\_le16
-     - e\_value\_offs
+     - __le16
+     - e_value_offs
      - Location of this attribute's value on the disk block where it is stored.
        Multiple attributes can share the same value. For an inode attribute
        this value is relative to the start of the first entry; for a block this
        value is relative to the start of the block (i.e. the header).
    * - 0x4
-     - \_\_le32
-     - e\_value\_inum
+     - __le32
+     - e_value_inum
      - The inode where the value is stored. Zero indicates the value is in the
        same block as this entry. This field is only used if the
-       INCOMPAT\_EA\_INODE feature is enabled.
+       INCOMPAT_EA_INODE feature is enabled.
    * - 0x8
-     - \_\_le32
-     - e\_value\_size
+     - __le32
+     - e_value_size
      - Length of attribute value.
    * - 0xC
-     - \_\_le32
-     - e\_hash
+     - __le32
+     - e_hash
      - Hash value of attribute name and attribute value. The kernel doesn't
        update the hash for in-inode attributes, so for that case this value
        must be zero, because e2fsck validates any non-zero hash regardless of
        where the xattr lives.
    * - 0x10
      - char
-     - e\_name[e\_name\_len]
+     - e_name[e_name_len]
      - Attribute name. Does not include trailing NULL.
 
 Attribute values can follow the end of the entry table. There appears to
 be a requirement that they be aligned to 4-byte boundaries. The values
 are stored starting at the end of the block and grow towards the
-xattr\_header/xattr\_entry table. When the two collide, the overflow is
+xattr_header/xattr_entry table. When the two collide, the overflow is
 put into a separate disk block. If the disk block fills up, the
 filesystem returns -ENOSPC.
 
@@ -167,15 +167,15 @@ the key name. Here is a map of name index values to key prefixes:
    * - 1
      - “user.”
    * - 2
-     - “system.posix\_acl\_access”
+     - “system.posix_acl_access”
    * - 3
-     - “system.posix\_acl\_default”
+     - “system.posix_acl_default”
    * - 4
      - “trusted.”
    * - 6
      - “security.”
    * - 7
-     - “system.” (inline\_data only?)
+     - “system.” (inline_data only?)
    * - 8
      - “system.richacl” (SuSE kernels only?)
 
index 72075aa..976a180 100644 (file)
@@ -23,7 +23,7 @@ means that a block group addresses 32 gigabytes instead of 128 megabytes,
 also shrinking the amount of file system overhead for metadata.
 
 The administrator can set a block cluster size at mkfs time (which is
-stored in the s\_log\_cluster\_size field in the superblock); from then
+stored in the s_log_cluster_size field in the superblock); from then
 on, the block bitmaps track clusters, not individual blocks. This means
 that block groups can be several gigabytes in size (instead of just
 128MiB); however, the minimum allocation unit becomes a cluster, not a
index c7546db..91c45d8 100644 (file)
@@ -9,15 +9,15 @@ group.
 The inode bitmap records which entries in the inode table are in use.
 
 As with most bitmaps, one bit represents the usage status of one data
-block or inode table entry. This implies a block group size of 8 \*
-number\_of\_bytes\_in\_a\_logical\_block.
+block or inode table entry. This implies a block group size of 8 *
+number_of_bytes_in_a_logical_block.
 
 NOTE: If ``BLOCK_UNINIT`` is set for a given block group, various parts
 of the kernel and e2fsprogs code pretends that the block bitmap contains
 zeros (i.e. all blocks in the group are free). However, it is not
 necessarily the case that no blocks are in use -- if ``meta_bg`` is set,
 the bitmaps and group descriptor live inside the group. Unfortunately,
-ext2fs\_test\_block\_bitmap2() will return '0' for those locations,
+ext2fs_test_block_bitmap2() will return '0' for those locations,
 which produces confusing debugfs output.
 
 Inode Table
index d5d652a..46d78f8 100644 (file)
@@ -56,39 +56,39 @@ established that the super block and the group descriptor table, if
 present, will be at the beginning of the block group. The bitmaps and
 the inode table can be anywhere, and it is quite possible for the
 bitmaps to come after the inode table, or for both to be in different
-groups (flex\_bg). Leftover space is used for file data blocks, indirect
+groups (flex_bg). Leftover space is used for file data blocks, indirect
 block maps, extent tree blocks, and extended attributes.
 
 Flexible Block Groups
 ---------------------
 
 Starting in ext4, there is a new feature called flexible block groups
-(flex\_bg). In a flex\_bg, several block groups are tied together as one
+(flex_bg). In a flex_bg, several block groups are tied together as one
 logical block group; the bitmap spaces and the inode table space in the
-first block group of the flex\_bg are expanded to include the bitmaps
-and inode tables of all other block groups in the flex\_bg. For example,
-if the flex\_bg size is 4, then group 0 will contain (in order) the
+first block group of the flex_bg are expanded to include the bitmaps
+and inode tables of all other block groups in the flex_bg. For example,
+if the flex_bg size is 4, then group 0 will contain (in order) the
 superblock, group descriptors, data block bitmaps for groups 0-3, inode
 bitmaps for groups 0-3, inode tables for groups 0-3, and the remaining
 space in group 0 is for file data. The effect of this is to group the
 block group metadata close together for faster loading, and to enable
 large files to be continuous on disk. Backup copies of the superblock
 and group descriptors are always at the beginning of block groups, even
-if flex\_bg is enabled. The number of block groups that make up a
-flex\_bg is given by 2 ^ ``sb.s_log_groups_per_flex``.
+if flex_bg is enabled. The number of block groups that make up a
+flex_bg is given by 2 ^ ``sb.s_log_groups_per_flex``.
 
 Meta Block Groups
 -----------------
 
-Without the option META\_BG, for safety concerns, all block group
+Without the option META_BG, for safety concerns, all block group
 descriptors copies are kept in the first block group. Given the default
 128MiB(2^27 bytes) block group size and 64-byte group descriptors, ext4
 can have at most 2^27/64 = 2^21 block groups. This limits the entire
 filesystem size to 2^21 * 2^27 = 2^48bytes or 256TiB.
 
 The solution to this problem is to use the metablock group feature
-(META\_BG), which is already in ext3 for all 2.6 releases. With the
-META\_BG feature, ext4 filesystems are partitioned into many metablock
+(META_BG), which is already in ext3 for all 2.6 releases. With the
+META_BG feature, ext4 filesystems are partitioned into many metablock
 groups. Each metablock group is a cluster of block groups whose group
 descriptor structures can be stored in a single disk block. For ext4
 filesystems with 4 KB block size, a single metablock group partition
@@ -110,7 +110,7 @@ bytes, a meta-block group contains 32 block groups for filesystems with
 a 1KB block size, and 128 block groups for filesystems with a 4KB
 blocksize. Filesystems can either be created using this new block group
 descriptor layout, or existing filesystems can be resized on-line, and
-the field s\_first\_meta\_bg in the superblock will indicate the first
+the field s_first_meta_bg in the superblock will indicate the first
 block group using this new layout.
 
 Please see an important note about ``BLOCK_UNINIT`` in the section about
@@ -121,15 +121,15 @@ Lazy Block Group Initialization
 
 A new feature for ext4 are three block group descriptor flags that
 enable mkfs to skip initializing other parts of the block group
-metadata. Specifically, the INODE\_UNINIT and BLOCK\_UNINIT flags mean
+metadata. Specifically, the INODE_UNINIT and BLOCK_UNINIT flags mean
 that the inode and block bitmaps for that group can be calculated and
 therefore the on-disk bitmap blocks are not initialized. This is
 generally the case for an empty block group or a block group containing
-only fixed-location block group metadata. The INODE\_ZEROED flag means
+only fixed-location block group metadata. The INODE_ZEROED flag means
 that the inode table has been initialized; mkfs will unset this flag and
 rely on the kernel to initialize the inode tables in the background.
 
 By not writing zeroes to the bitmaps and inode table, mkfs time is
-reduced considerably. Note the feature flag is RO\_COMPAT\_GDT\_CSUM,
-but the dumpe2fs output prints this as “uninit\_bg”. They are the same
+reduced considerably. Note the feature flag is RO_COMPAT_GDT_CSUM,
+but the dumpe2fs output prints this as “uninit_bg”. They are the same
 thing.
index 30e2575..2bd9904 100644 (file)
@@ -1,7 +1,7 @@
 .. SPDX-License-Identifier: GPL-2.0
 
 +---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-| i.i\_block Offset   | Where It Points                                                                                                                                                                                                              |
+| i.i_block Offset   | Where It Points                                                                                                                                                                                                              |
 +=====================+==============================================================================================================================================================================================================================+
 | 0 to 11             | Direct map to file blocks 0 to 11.                                                                                                                                                                                           |
 +---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
index 5519e25..e232749 100644 (file)
@@ -4,7 +4,7 @@ Checksums
 ---------
 
 Starting in early 2012, metadata checksums were added to all major ext4
-and jbd2 data structures. The associated feature flag is metadata\_csum.
+and jbd2 data structures. The associated feature flag is metadata_csum.
 The desired checksum algorithm is indicated in the superblock, though as
 of October 2012 the only supported algorithm is crc32c. Some data
 structures did not have space to fit a full 32-bit checksum, so only the
@@ -20,7 +20,7 @@ encounters directory blocks that lack sufficient empty space to add a
 checksum, it will request that you run ``e2fsck -D`` to have the
 directories rebuilt with checksums. This has the added benefit of
 removing slack space from the directory files and rebalancing the htree
-indexes. If you \_ignore\_ this step, your directories will not be
+indexes. If you _ignore_ this step, your directories will not be
 protected by a checksum!
 
 The following table describes the data elements that go into each type
@@ -35,39 +35,39 @@ of checksum. The checksum function is whatever the superblock describes
      - Length
      - Ingredients
    * - Superblock
-     - \_\_le32
+     - __le32
      - The entire superblock up to the checksum field. The UUID lives inside
        the superblock.
    * - MMP
-     - \_\_le32
+     - __le32
      - UUID + the entire MMP block up to the checksum field.
    * - Extended Attributes
-     - \_\_le32
+     - __le32
      - UUID + the entire extended attribute block. The checksum field is set to
        zero.
    * - Directory Entries
-     - \_\_le32
+     - __le32
      - UUID + inode number + inode generation + the directory block up to the
        fake entry enclosing the checksum field.
    * - HTREE Nodes
-     - \_\_le32
+     - __le32
      - UUID + inode number + inode generation + all valid extents + HTREE tail.
        The checksum field is set to zero.
    * - Extents
-     - \_\_le32
+     - __le32
      - UUID + inode number + inode generation + the entire extent block up to
        the checksum field.
    * - Bitmaps
-     - \_\_le32 or \_\_le16
+     - __le32 or __le16
      - UUID + the entire bitmap. Checksums are stored in the group descriptor,
        and truncated if the group descriptor size is 32 bytes (i.e. ^64bit)
    * - Inodes
-     - \_\_le32
+     - __le32
      - UUID + inode number + inode generation + the entire inode. The checksum
        field is set to zero. Each inode has its own checksum.
    * - Group Descriptors
-     - \_\_le16
-     - If metadata\_csum, then UUID + group number + the entire descriptor;
-       else if gdt\_csum, then crc16(UUID + group number + the entire
+     - __le16
+     - If metadata_csum, then UUID + group number + the entire descriptor;
+       else if gdt_csum, then crc16(UUID + group number + the entire
        descriptor). In all cases, only the lower 16 bits are stored.
 
index 55f618b..6eece8e 100644 (file)
@@ -42,24 +42,24 @@ is at most 263 bytes long, though on disk you'll need to reference
      - Name
      - Description
    * - 0x0
-     - \_\_le32
+     - __le32
      - inode
      - Number of the inode that this directory entry points to.
    * - 0x4
-     - \_\_le16
-     - rec\_len
+     - __le16
+     - rec_len
      - Length of this directory entry. Must be a multiple of 4.
    * - 0x6
-     - \_\_le16
-     - name\_len
+     - __le16
+     - name_len
      - Length of the file name.
    * - 0x8
      - char
-     - name[EXT4\_NAME\_LEN]
+     - name[EXT4_NAME_LEN]
      - File name.
 
 Since file names cannot be longer than 255 bytes, the new directory
-entry format shortens the name\_len field and uses the space for a file
+entry format shortens the name_len field and uses the space for a file
 type flag, probably to avoid having to load every inode during directory
 tree traversal. This format is ``ext4_dir_entry_2``, which is at most
 263 bytes long, though on disk you'll need to reference
@@ -74,24 +74,24 @@ tree traversal. This format is ``ext4_dir_entry_2``, which is at most
      - Name
      - Description
    * - 0x0
-     - \_\_le32
+     - __le32
      - inode
      - Number of the inode that this directory entry points to.
    * - 0x4
-     - \_\_le16
-     - rec\_len
+     - __le16
+     - rec_len
      - Length of this directory entry.
    * - 0x6
-     - \_\_u8
-     - name\_len
+     - __u8
+     - name_len
      - Length of the file name.
    * - 0x7
-     - \_\_u8
-     - file\_type
+     - __u8
+     - file_type
      - File type code, see ftype_ table below.
    * - 0x8
      - char
-     - name[EXT4\_NAME\_LEN]
+     - name[EXT4_NAME_LEN]
      - File name.
 
 .. _ftype:
@@ -137,19 +137,19 @@ entry uses this extension, it may be up to 271 bytes.
      - Name
      - Description
    * - 0x0
-     - \_\_le32
+     - __le32
      - hash
      - The hash of the directory name
    * - 0x4
-     - \_\_le32
-     - minor\_hash
+     - __le32
+     - minor_hash
      - The minor hash of the directory name
 
 
 In order to add checksums to these classic directory blocks, a phony
 ``struct ext4_dir_entry`` is placed at the end of each leaf block to
 hold the checksum. The directory entry is 12 bytes long. The inode
-number and name\_len fields are set to zero to fool old software into
+number and name_len fields are set to zero to fool old software into
 ignoring an apparently empty directory entry, and the checksum is stored
 in the place where the name normally goes. The structure is
 ``struct ext4_dir_entry_tail``:
@@ -163,24 +163,24 @@ in the place where the name normally goes. The structure is
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - det\_reserved\_zero1
+     - __le32
+     - det_reserved_zero1
      - Inode number, which must be zero.
    * - 0x4
-     - \_\_le16
-     - det\_rec\_len
+     - __le16
+     - det_rec_len
      - Length of this directory entry, which must be 12.
    * - 0x6
-     - \_\_u8
-     - det\_reserved\_zero2
+     - __u8
+     - det_reserved_zero2
      - Length of the file name, which must be zero.
    * - 0x7
-     - \_\_u8
-     - det\_reserved\_ft
+     - __u8
+     - det_reserved_ft
      - File type, which must be 0xDE.
    * - 0x8
-     - \_\_le32
-     - det\_checksum
+     - __le32
+     - det_checksum
      - Directory leaf block checksum.
 
 The leaf directory block checksum is calculated against the FS UUID, the
@@ -194,7 +194,7 @@ Hash Tree Directories
 A linear array of directory entries isn't great for performance, so a
 new feature was added to ext3 to provide a faster (but peculiar)
 balanced tree keyed off a hash of the directory entry name. If the
-EXT4\_INDEX\_FL (0x1000) flag is set in the inode, this directory uses a
+EXT4_INDEX_FL (0x1000) flag is set in the inode, this directory uses a
 hashed btree (htree) to organize and find directory entries. For
 backwards read-only compatibility with ext2, this tree is actually
 hidden inside the directory file, masquerading as “empty” directory data
@@ -206,14 +206,14 @@ rest of the directory block is empty so that it moves on.
 The root of the tree always lives in the first data block of the
 directory. By ext2 custom, the '.' and '..' entries must appear at the
 beginning of this first block, so they are put here as two
-``struct ext4_dir_entry_2``\ s and not stored in the tree. The rest of
+``struct ext4_dir_entry_2`` s and not stored in the tree. The rest of
 the root node contains metadata about the tree and finally a hash->block
 map to find nodes that are lower in the htree. If
 ``dx_root.info.indirect_levels`` is non-zero then the htree has two
 levels; the data block pointed to by the root node's map is an interior
 node, which is indexed by a minor hash. Interior nodes in this tree
 contains a zeroed out ``struct ext4_dir_entry_2`` followed by a
-minor\_hash->block map to find leafe nodes. Leaf nodes contain a linear
+minor_hash->block map to find leafe nodes. Leaf nodes contain a linear
 array of all ``struct ext4_dir_entry_2``; all of these entries
 (presumably) hash to the same value. If there is an overflow, the
 entries simply overflow into the next leaf node, and the
@@ -245,83 +245,83 @@ of a data block:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
+     - __le32
      - dot.inode
      - inode number of this directory.
    * - 0x4
-     - \_\_le16
-     - dot.rec\_len
+     - __le16
+     - dot.rec_len
      - Length of this record, 12.
    * - 0x6
      - u8
-     - dot.name\_len
+     - dot.name_len
      - Length of the name, 1.
    * - 0x7
      - u8
-     - dot.file\_type
+     - dot.file_type
      - File type of this entry, 0x2 (directory) (if the feature flag is set).
    * - 0x8
      - char
      - dot.name[4]
-     - “.\\0\\0\\0”
+     - “.\0\0\0”
    * - 0xC
-     - \_\_le32
+     - __le32
      - dotdot.inode
      - inode number of parent directory.
    * - 0x10
-     - \_\_le16
-     - dotdot.rec\_len
-     - block\_size - 12. The record length is long enough to cover all htree
+     - __le16
+     - dotdot.rec_len
+     - block_size - 12. The record length is long enough to cover all htree
        data.
    * - 0x12
      - u8
-     - dotdot.name\_len
+     - dotdot.name_len
      - Length of the name, 2.
    * - 0x13
      - u8
-     - dotdot.file\_type
+     - dotdot.file_type
      - File type of this entry, 0x2 (directory) (if the feature flag is set).
    * - 0x14
      - char
-     - dotdot\_name[4]
-     - “..\\0\\0”
+     - dotdot_name[4]
+     - “..\0\0”
    * - 0x18
-     - \_\_le32
-     - struct dx\_root\_info.reserved\_zero
+     - __le32
+     - struct dx_root_info.reserved_zero
      - Zero.
    * - 0x1C
      - u8
-     - struct dx\_root\_info.hash\_version
+     - struct dx_root_info.hash_version
      - Hash type, see dirhash_ table below.
    * - 0x1D
      - u8
-     - struct dx\_root\_info.info\_length
+     - struct dx_root_info.info_length
      - Length of the tree information, 0x8.
    * - 0x1E
      - u8
-     - struct dx\_root\_info.indirect\_levels
-     - Depth of the htree. Cannot be larger than 3 if the INCOMPAT\_LARGEDIR
+     - struct dx_root_info.indirect_levels
+     - Depth of the htree. Cannot be larger than 3 if the INCOMPAT_LARGEDIR
        feature is set; cannot be larger than 2 otherwise.
    * - 0x1F
      - u8
-     - struct dx\_root\_info.unused\_flags
+     - struct dx_root_info.unused_flags
      -
    * - 0x20
-     - \_\_le16
+     - __le16
      - limit
-     - Maximum number of dx\_entries that can follow this header, plus 1 for
+     - Maximum number of dx_entries that can follow this header, plus 1 for
        the header itself.
    * - 0x22
-     - \_\_le16
+     - __le16
      - count
-     - Actual number of dx\_entries that follow this header, plus 1 for the
+     - Actual number of dx_entries that follow this header, plus 1 for the
        header itself.
    * - 0x24
-     - \_\_le32
+     - __le32
      - block
      - The block number (within the directory file) that goes with hash=0.
    * - 0x28
-     - struct dx\_entry
+     - struct dx_entry
      - entries[0]
      - As many 8-byte ``struct dx_entry`` as fits in the rest of the data block.
 
@@ -362,38 +362,38 @@ also the full length of a data block:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
+     - __le32
      - fake.inode
      - Zero, to make it look like this entry is not in use.
    * - 0x4
-     - \_\_le16
-     - fake.rec\_len
-     - The size of the block, in order to hide all of the dx\_node data.
+     - __le16
+     - fake.rec_len
+     - The size of the block, in order to hide all of the dx_node data.
    * - 0x6
      - u8
-     - name\_len
+     - name_len
      - Zero. There is no name for this “unused” directory entry.
    * - 0x7
      - u8
-     - file\_type
+     - file_type
      - Zero. There is no file type for this “unused” directory entry.
    * - 0x8
-     - \_\_le16
+     - __le16
      - limit
-     - Maximum number of dx\_entries that can follow this header, plus 1 for
+     - Maximum number of dx_entries that can follow this header, plus 1 for
        the header itself.
    * - 0xA
-     - \_\_le16
+     - __le16
      - count
-     - Actual number of dx\_entries that follow this header, plus 1 for the
+     - Actual number of dx_entries that follow this header, plus 1 for the
        header itself.
    * - 0xE
-     - \_\_le32
+     - __le32
      - block
      - The block number (within the directory file) that goes with the lowest
        hash value of this block. This value is stored in the parent block.
    * - 0x12
-     - struct dx\_entry
+     - struct dx_entry
      - entries[0]
      - As many 8-byte ``struct dx_entry`` as fits in the rest of the data block.
 
@@ -410,11 +410,11 @@ long:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
+     - __le32
      - hash
      - Hash code.
    * - 0x4
-     - \_\_le32
+     - __le32
      - block
      - Block number (within the directory file, not filesystem blocks) of the
        next node in the htree.
@@ -423,13 +423,13 @@ long:
 author.)
 
 If metadata checksums are enabled, the last 8 bytes of the directory
-block (precisely the length of one dx\_entry) are used to store a
+block (precisely the length of one dx_entry) are used to store a
 ``struct dx_tail``, which contains the checksum. The ``limit`` and
-``count`` entries in the dx\_root/dx\_node structures are adjusted as
-necessary to fit the dx\_tail into the block. If there is no space for
-the dx\_tail, the user is notified to run e2fsck -D to rebuild the
+``count`` entries in the dx_root/dx_node structures are adjusted as
+necessary to fit the dx_tail into the block. If there is no space for
+the dx_tail, the user is notified to run e2fsck -D to rebuild the
 directory index (which will ensure that there's space for the checksum.
-The dx\_tail structure is 8 bytes long and looks like this:
+The dx_tail structure is 8 bytes long and looks like this:
 
 .. list-table::
    :widths: 8 8 24 40
@@ -441,13 +441,13 @@ The dx\_tail structure is 8 bytes long and looks like this:
      - Description
    * - 0x0
      - u32
-     - dt\_reserved
+     - dt_reserved
      - Zero.
    * - 0x4
-     - \_\_le32
-     - dt\_checksum
+     - __le32
+     - dt_checksum
      - Checksum of the htree directory block.
 
 The checksum is calculated against the FS UUID, the htree index header
-(dx\_root or dx\_node), all of the htree indices (dx\_entry) that are in
-use, and the tail block (dx\_tail).
+(dx_root or dx_node), all of the htree indices (dx_entry) that are in
+use, and the tail block (dx_tail).
index ecc0d01..7a2ef26 100644 (file)
@@ -5,14 +5,14 @@ Large Extended Attribute Values
 
 To enable ext4 to store extended attribute values that do not fit in the
 inode or in the single extended attribute block attached to an inode,
-the EA\_INODE feature allows us to store the value in the data blocks of
+the EA_INODE feature allows us to store the value in the data blocks of
 a regular file inode. This “EA inode” is linked only from the extended
 attribute name index and must not appear in a directory entry. The
-inode's i\_atime field is used to store a checksum of the xattr value;
-and i\_ctime/i\_version store a 64-bit reference count, which enables
+inode's i_atime field is used to store a checksum of the xattr value;
+and i_ctime/i_version store a 64-bit reference count, which enables
 sharing of large xattr values between multiple owning inodes. For
 backward compatibility with older versions of this feature, the
-i\_mtime/i\_generation *may* store a back-reference to the inode number
-and i\_generation of the **one** owning inode (in cases where the EA
+i_mtime/i_generation *may* store a back-reference to the inode number
+and i_generation of the **one** owning inode (in cases where the EA
 inode is not referenced by multiple inodes) to verify that the EA inode
 is the correct one being accessed.
index 7ba6114..392ec44 100644 (file)
@@ -7,34 +7,34 @@ Each block group on the filesystem has one of these descriptors
 associated with it. As noted in the Layout section above, the group
 descriptors (if present) are the second item in the block group. The
 standard configuration is for each block group to contain a full copy of
-the block group descriptor table unless the sparse\_super feature flag
+the block group descriptor table unless the sparse_super feature flag
 is set.
 
 Notice how the group descriptor records the location of both bitmaps and
 the inode table (i.e. they can float). This means that within a block
 group, the only data structures with fixed locations are the superblock
-and the group descriptor table. The flex\_bg mechanism uses this
+and the group descriptor table. The flex_bg mechanism uses this
 property to group several block groups into a flex group and lay out all
 of the groups' bitmaps and inode tables into one long run in the first
 group of the flex group.
 
-If the meta\_bg feature flag is set, then several block groups are
-grouped together into a meta group. Note that in the meta\_bg case,
+If the meta_bg feature flag is set, then several block groups are
+grouped together into a meta group. Note that in the meta_bg case,
 however, the first and last two block groups within the larger meta
 group contain only group descriptors for the groups inside the meta
 group.
 
-flex\_bg and meta\_bg do not appear to be mutually exclusive features.
+flex_bg and meta_bg do not appear to be mutually exclusive features.
 
 In ext2, ext3, and ext4 (when the 64bit feature is not enabled), the
 block group descriptor was only 32 bytes long and therefore ends at
-bg\_checksum. On an ext4 filesystem with the 64bit feature enabled, the
+bg_checksum. On an ext4 filesystem with the 64bit feature enabled, the
 block group descriptor expands to at least the 64 bytes described below;
 the size is stored in the superblock.
 
-If gdt\_csum is set and metadata\_csum is not set, the block group
+If gdt_csum is set and metadata_csum is not set, the block group
 checksum is the crc16 of the FS UUID, the group number, and the group
-descriptor structure. If metadata\_csum is set, then the block group
+descriptor structure. If metadata_csum is set, then the block group
 checksum is the lower 16 bits of the checksum of the FS UUID, the group
 number, and the group descriptor structure. Both block and inode bitmap
 checksums are calculated against the FS UUID, the group number, and the
@@ -51,59 +51,59 @@ The block group descriptor is laid out in ``struct ext4_group_desc``.
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - bg\_block\_bitmap\_lo
+     - __le32
+     - bg_block_bitmap_lo
      - Lower 32-bits of location of block bitmap.
    * - 0x4
-     - \_\_le32
-     - bg\_inode\_bitmap\_lo
+     - __le32
+     - bg_inode_bitmap_lo
      - Lower 32-bits of location of inode bitmap.
    * - 0x8
-     - \_\_le32
-     - bg\_inode\_table\_lo
+     - __le32
+     - bg_inode_table_lo
      - Lower 32-bits of location of inode table.
    * - 0xC
-     - \_\_le16
-     - bg\_free\_blocks\_count\_lo
+     - __le16
+     - bg_free_blocks_count_lo
      - Lower 16-bits of free block count.
    * - 0xE
-     - \_\_le16
-     - bg\_free\_inodes\_count\_lo
+     - __le16
+     - bg_free_inodes_count_lo
      - Lower 16-bits of free inode count.
    * - 0x10
-     - \_\_le16
-     - bg\_used\_dirs\_count\_lo
+     - __le16
+     - bg_used_dirs_count_lo
      - Lower 16-bits of directory count.
    * - 0x12
-     - \_\_le16
-     - bg\_flags
+     - __le16
+     - bg_flags
      - Block group flags. See the bgflags_ table below.
    * - 0x14
-     - \_\_le32
-     - bg\_exclude\_bitmap\_lo
+     - __le32
+     - bg_exclude_bitmap_lo
      - Lower 32-bits of location of snapshot exclusion bitmap.
    * - 0x18
-     - \_\_le16
-     - bg\_block\_bitmap\_csum\_lo
+     - __le16
+     - bg_block_bitmap_csum_lo
      - Lower 16-bits of the block bitmap checksum.
    * - 0x1A
-     - \_\_le16
-     - bg\_inode\_bitmap\_csum\_lo
+     - __le16
+     - bg_inode_bitmap_csum_lo
      - Lower 16-bits of the inode bitmap checksum.
    * - 0x1C
-     - \_\_le16
-     - bg\_itable\_unused\_lo
+     - __le16
+     - bg_itable_unused_lo
      - Lower 16-bits of unused inode count. If set, we needn't scan past the
-       ``(sb.s_inodes_per_group - gdt.bg_itable_unused)``\ th entry in the
+       ``(sb.s_inodes_per_group - gdt.bg_itable_unused)`` th entry in the
        inode table for this group.
    * - 0x1E
-     - \_\_le16
-     - bg\_checksum
-     - Group descriptor checksum; crc16(sb\_uuid+group\_num+bg\_desc) if the
-       RO\_COMPAT\_GDT\_CSUM feature is set, or
-       crc32c(sb\_uuid+group\_num+bg\_desc) & 0xFFFF if the
-       RO\_COMPAT\_METADATA\_CSUM feature is set.  The bg\_checksum
-       field in bg\_desc is skipped when calculating crc16 checksum,
+     - __le16
+     - bg_checksum
+     - Group descriptor checksum; crc16(sb_uuid+group_num+bg_desc) if the
+       RO_COMPAT_GDT_CSUM feature is set, or
+       crc32c(sb_uuid+group_num+bg_desc) & 0xFFFF if the
+       RO_COMPAT_METADATA_CSUM feature is set.  The bg_checksum
+       field in bg_desc is skipped when calculating crc16 checksum,
        and set to zero if crc32c checksum is used.
    * -
      -
@@ -111,48 +111,48 @@ The block group descriptor is laid out in ``struct ext4_group_desc``.
      - These fields only exist if the 64bit feature is enabled and s_desc_size
        > 32.
    * - 0x20
-     - \_\_le32
-     - bg\_block\_bitmap\_hi
+     - __le32
+     - bg_block_bitmap_hi
      - Upper 32-bits of location of block bitmap.
    * - 0x24
-     - \_\_le32
-     - bg\_inode\_bitmap\_hi
+     - __le32
+     - bg_inode_bitmap_hi
      - Upper 32-bits of location of inodes bitmap.
    * - 0x28
-     - \_\_le32
-     - bg\_inode\_table\_hi
+     - __le32
+     - bg_inode_table_hi
      - Upper 32-bits of location of inodes table.
    * - 0x2C
-     - \_\_le16
-     - bg\_free\_blocks\_count\_hi
+     - __le16
+     - bg_free_blocks_count_hi
      - Upper 16-bits of free block count.
    * - 0x2E
-     - \_\_le16
-     - bg\_free\_inodes\_count\_hi
+     - __le16
+     - bg_free_inodes_count_hi
      - Upper 16-bits of free inode count.
    * - 0x30
-     - \_\_le16
-     - bg\_used\_dirs\_count\_hi
+     - __le16
+     - bg_used_dirs_count_hi
      - Upper 16-bits of directory count.
    * - 0x32
-     - \_\_le16
-     - bg\_itable\_unused\_hi
+     - __le16
+     - bg_itable_unused_hi
      - Upper 16-bits of unused inode count.
    * - 0x34
-     - \_\_le32
-     - bg\_exclude\_bitmap\_hi
+     - __le32
+     - bg_exclude_bitmap_hi
      - Upper 32-bits of location of snapshot exclusion bitmap.
    * - 0x38
-     - \_\_le16
-     - bg\_block\_bitmap\_csum\_hi
+     - __le16
+     - bg_block_bitmap_csum_hi
      - Upper 16-bits of the block bitmap checksum.
    * - 0x3A
-     - \_\_le16
-     - bg\_inode\_bitmap\_csum\_hi
+     - __le16
+     - bg_inode_bitmap_csum_hi
      - Upper 16-bits of the inode bitmap checksum.
    * - 0x3C
-     - \_\_u32
-     - bg\_reserved
+     - __u32
+     - bg_reserved
      - Padding to 64 bytes.
 
 .. _bgflags:
@@ -166,8 +166,8 @@ Block group flags can be any combination of the following:
    * - Value
      - Description
    * - 0x1
-     - inode table and bitmap are not initialized (EXT4\_BG\_INODE\_UNINIT).
+     - inode table and bitmap are not initialized (EXT4_BG_INODE_UNINIT).
    * - 0x2
-     - block bitmap is not initialized (EXT4\_BG\_BLOCK\_UNINIT).
+     - block bitmap is not initialized (EXT4_BG_BLOCK_UNINIT).
    * - 0x4
-     - inode table is zeroed (EXT4\_BG\_INODE\_ZEROED).
+     - inode table is zeroed (EXT4_BG_INODE_ZEROED).
index b9816d5..dc31f50 100644 (file)
@@ -1,6 +1,6 @@
 .. SPDX-License-Identifier: GPL-2.0
 
-The Contents of inode.i\_block
+The Contents of inode.i_block
 ------------------------------
 
 Depending on the type of file an inode describes, the 60 bytes of
@@ -47,7 +47,7 @@ In ext4, the file to logical block map has been replaced with an extent
 tree. Under the old scheme, allocating a contiguous run of 1,000 blocks
 requires an indirect block to map all 1,000 entries; with extents, the
 mapping is reduced to a single ``struct ext4_extent`` with
-``ee_len = 1000``. If flex\_bg is enabled, it is possible to allocate
+``ee_len = 1000``. If flex_bg is enabled, it is possible to allocate
 very large files with a single extent, at a considerable reduction in
 metadata block use, and some improvement in disk efficiency. The inode
 must have the extents flag (0x80000) flag set for this feature to be in
@@ -76,28 +76,28 @@ which is 12 bytes long:
      - Name
      - Description
    * - 0x0
-     - \_\_le16
-     - eh\_magic
+     - __le16
+     - eh_magic
      - Magic number, 0xF30A.
    * - 0x2
-     - \_\_le16
-     - eh\_entries
+     - __le16
+     - eh_entries
      - Number of valid entries following the header.
    * - 0x4
-     - \_\_le16
-     - eh\_max
+     - __le16
+     - eh_max
      - Maximum number of entries that could follow the header.
    * - 0x6
-     - \_\_le16
-     - eh\_depth
+     - __le16
+     - eh_depth
      - Depth of this extent node in the extent tree. 0 = this extent node
        points to data blocks; otherwise, this extent node points to other
        extent nodes. The extent tree can be at most 5 levels deep: a logical
        block number can be at most ``2^32``, and the smallest ``n`` that
        satisfies ``4*(((blocksize - 12)/12)^n) >= 2^32`` is 5.
    * - 0x8
-     - \_\_le32
-     - eh\_generation
+     - __le32
+     - eh_generation
      - Generation of the tree. (Used by Lustre, but not standard ext4).
 
 Internal nodes of the extent tree, also known as index nodes, are
@@ -112,22 +112,22 @@ recorded as ``struct ext4_extent_idx``, and are 12 bytes long:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - ei\_block
+     - __le32
+     - ei_block
      - This index node covers file blocks from 'block' onward.
    * - 0x4
-     - \_\_le32
-     - ei\_leaf\_lo
+     - __le32
+     - ei_leaf_lo
      - Lower 32-bits of the block number of the extent node that is the next
        level lower in the tree. The tree node pointed to can be either another
        internal node or a leaf node, described below.
    * - 0x8
-     - \_\_le16
-     - ei\_leaf\_hi
+     - __le16
+     - ei_leaf_hi
      - Upper 16-bits of the previous field.
    * - 0xA
-     - \_\_u16
-     - ei\_unused
+     - __u16
+     - ei_unused
      -
 
 Leaf nodes of the extent tree are recorded as ``struct ext4_extent``,
@@ -142,24 +142,24 @@ and are also 12 bytes long:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - ee\_block
+     - __le32
+     - ee_block
      - First file block number that this extent covers.
    * - 0x4
-     - \_\_le16
-     - ee\_len
+     - __le16
+     - ee_len
      - Number of blocks covered by extent. If the value of this field is <=
        32768, the extent is initialized. If the value of the field is > 32768,
        the extent is uninitialized and the actual extent length is ``ee_len`` -
        32768. Therefore, the maximum length of a initialized extent is 32768
        blocks, and the maximum length of an uninitialized extent is 32767.
    * - 0x6
-     - \_\_le16
-     - ee\_start\_hi
+     - __le16
+     - ee_start_hi
      - Upper 16-bits of the block number to which this extent points.
    * - 0x8
-     - \_\_le32
-     - ee\_start\_lo
+     - __le32
+     - ee_start_lo
      - Lower 32-bits of the block number to which this extent points.
 
 Prior to the introduction of metadata checksums, the extent header +
@@ -182,8 +182,8 @@ including) the checksum itself.
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - eb\_checksum
+     - __le32
+     - eb_checksum
      - Checksum of the extent block, crc32c(uuid+inum+igeneration+extentblock)
 
 Inline Data
index d107517..a728af0 100644 (file)
@@ -11,12 +11,12 @@ file is smaller than 60 bytes, then the data are stored inline in
 attribute space, then it might be found as an extended attribute
 “system.data” within the inode body (“ibody EA”). This of course
 constrains the amount of extended attributes one can attach to an inode.
-If the data size increases beyond i\_block + ibody EA, a regular block
+If the data size increases beyond i_block + ibody EA, a regular block
 is allocated and the contents moved to that block.
 
 Pending a change to compact the extended attribute key used to store
 inline data, one ought to be able to store 160 bytes of data in a
-256-byte inode (as of June 2015, when i\_extra\_isize is 28). Prior to
+256-byte inode (as of June 2015, when i_extra_isize is 28). Prior to
 that, the limit was 156 bytes due to inefficient use of inode space.
 
 The inline data feature requires the presence of an extended attribute
@@ -25,12 +25,12 @@ for “system.data”, even if the attribute value is zero length.
 Inline Directories
 ~~~~~~~~~~~~~~~~~~
 
-The first four bytes of i\_block are the inode number of the parent
+The first four bytes of i_block are the inode number of the parent
 directory. Following that is a 56-byte space for an array of directory
 entries; see ``struct ext4_dir_entry``. If there is a “system.data”
 attribute in the inode body, the EA value is an array of
 ``struct ext4_dir_entry`` as well. Note that for inline directories, the
-i\_block and EA space are treated as separate dirent blocks; directory
+i_block and EA space are treated as separate dirent blocks; directory
 entries cannot span the two.
 
 Inline directory entries are not checksummed, as the inode checksum
index 6c5ce66..cfc6c16 100644 (file)
@@ -38,138 +38,138 @@ The inode table entry is laid out in ``struct ext4_inode``.
      - Name
      - Description
    * - 0x0
-     - \_\_le16
-     - i\_mode
+     - __le16
+     - i_mode
      - File mode. See the table i_mode_ below.
    * - 0x2
-     - \_\_le16
-     - i\_uid
+     - __le16
+     - i_uid
      - Lower 16-bits of Owner UID.
    * - 0x4
-     - \_\_le32
-     - i\_size\_lo
+     - __le32
+     - i_size_lo
      - Lower 32-bits of size in bytes.
    * - 0x8
-     - \_\_le32
-     - i\_atime
-     - Last access time, in seconds since the epoch. However, if the EA\_INODE
+     - __le32
+     - i_atime
+     - Last access time, in seconds since the epoch. However, if the EA_INODE
        inode flag is set, this inode stores an extended attribute value and
        this field contains the checksum of the value.
    * - 0xC
-     - \_\_le32
-     - i\_ctime
+     - __le32
+     - i_ctime
      - Last inode change time, in seconds since the epoch. However, if the
-       EA\_INODE inode flag is set, this inode stores an extended attribute
+       EA_INODE inode flag is set, this inode stores an extended attribute
        value and this field contains the lower 32 bits of the attribute value's
        reference count.
    * - 0x10
-     - \_\_le32
-     - i\_mtime
+     - __le32
+     - i_mtime
      - Last data modification time, in seconds since the epoch. However, if the
-       EA\_INODE inode flag is set, this inode stores an extended attribute
+       EA_INODE inode flag is set, this inode stores an extended attribute
        value and this field contains the number of the inode that owns the
        extended attribute.
    * - 0x14
-     - \_\_le32
-     - i\_dtime
+     - __le32
+     - i_dtime
      - Deletion Time, in seconds since the epoch.
    * - 0x18
-     - \_\_le16
-     - i\_gid
+     - __le16
+     - i_gid
      - Lower 16-bits of GID.
    * - 0x1A
-     - \_\_le16
-     - i\_links\_count
+     - __le16
+     - i_links_count
      - Hard link count. Normally, ext4 does not permit an inode to have more
        than 65,000 hard links. This applies to files as well as directories,
        which means that there cannot be more than 64,998 subdirectories in a
        directory (each subdirectory's '..' entry counts as a hard link, as does
-       the '.' entry in the directory itself). With the DIR\_NLINK feature
+       the '.' entry in the directory itself). With the DIR_NLINK feature
        enabled, ext4 supports more than 64,998 subdirectories by setting this
        field to 1 to indicate that the number of hard links is not known.
    * - 0x1C
-     - \_\_le32
-     - i\_blocks\_lo
-     - Lower 32-bits of “block” count. If the huge\_file feature flag is not
+     - __le32
+     - i_blocks_lo
+     - Lower 32-bits of “block” count. If the huge_file feature flag is not
        set on the filesystem, the file consumes ``i_blocks_lo`` 512-byte blocks
-       on disk. If huge\_file is set and EXT4\_HUGE\_FILE\_FL is NOT set in
+       on disk. If huge_file is set and EXT4_HUGE_FILE_FL is NOT set in
        ``inode.i_flags``, then the file consumes ``i_blocks_lo + (i_blocks_hi
-       << 32)`` 512-byte blocks on disk. If huge\_file is set and
-       EXT4\_HUGE\_FILE\_FL IS set in ``inode.i_flags``, then this file
+       << 32)`` 512-byte blocks on disk. If huge_file is set and
+       EXT4_HUGE_FILE_FL IS set in ``inode.i_flags``, then this file
        consumes (``i_blocks_lo + i_blocks_hi`` << 32) filesystem blocks on
        disk.
    * - 0x20
-     - \_\_le32
-     - i\_flags
+     - __le32
+     - i_flags
      - Inode flags. See the table i_flags_ below.
    * - 0x24
      - 4 bytes
-     - i\_osd1
+     - i_osd1
      - See the table i_osd1_ for more details.
    * - 0x28
      - 60 bytes
-     - i\_block[EXT4\_N\_BLOCKS=15]
-     - Block map or extent tree. See the section “The Contents of inode.i\_block”.
+     - i_block[EXT4_N_BLOCKS=15]
+     - Block map or extent tree. See the section “The Contents of inode.i_block”.
    * - 0x64
-     - \_\_le32
-     - i\_generation
+     - __le32
+     - i_generation
      - File version (for NFS).
    * - 0x68
-     - \_\_le32
-     - i\_file\_acl\_lo
+     - __le32
+     - i_file_acl_lo
      - Lower 32-bits of extended attribute block. ACLs are of course one of
        many possible extended attributes; I think the name of this field is a
        result of the first use of extended attributes being for ACLs.
    * - 0x6C
-     - \_\_le32
-     - i\_size\_high / i\_dir\_acl
+     - __le32
+     - i_size_high / i_dir_acl
      - Upper 32-bits of file/directory size. In ext2/3 this field was named
-       i\_dir\_acl, though it was usually set to zero and never used.
+       i_dir_acl, though it was usually set to zero and never used.
    * - 0x70
-     - \_\_le32
-     - i\_obso\_faddr
+     - __le32
+     - i_obso_faddr
      - (Obsolete) fragment address.
    * - 0x74
      - 12 bytes
-     - i\_osd2
+     - i_osd2
      - See the table i_osd2_ for more details.
    * - 0x80
-     - \_\_le16
-     - i\_extra\_isize
+     - __le16
+     - i_extra_isize
      - Size of this inode - 128. Alternately, the size of the extended inode
        fields beyond the original ext2 inode, including this field.
    * - 0x82
-     - \_\_le16
-     - i\_checksum\_hi
+     - __le16
+     - i_checksum_hi
      - Upper 16-bits of the inode checksum.
    * - 0x84
-     - \_\_le32
-     - i\_ctime\_extra
+     - __le32
+     - i_ctime_extra
      - Extra change time bits. This provides sub-second precision. See Inode
        Timestamps section.
    * - 0x88
-     - \_\_le32
-     - i\_mtime\_extra
+     - __le32
+     - i_mtime_extra
      - Extra modification time bits. This provides sub-second precision.
    * - 0x8C
-     - \_\_le32
-     - i\_atime\_extra
+     - __le32
+     - i_atime_extra
      - Extra access time bits. This provides sub-second precision.
    * - 0x90
-     - \_\_le32
-     - i\_crtime
+     - __le32
+     - i_crtime
      - File creation time, in seconds since the epoch.
    * - 0x94
-     - \_\_le32
-     - i\_crtime\_extra
+     - __le32
+     - i_crtime_extra
      - Extra file creation time bits. This provides sub-second precision.
    * - 0x98
-     - \_\_le32
-     - i\_version\_hi
+     - __le32
+     - i_version_hi
      - Upper 32-bits for version number.
    * - 0x9C
-     - \_\_le32
-     - i\_projid
+     - __le32
+     - i_projid
      - Project ID.
 
 .. _i_mode:
@@ -183,45 +183,45 @@ The ``i_mode`` value is a combination of the following flags:
    * - Value
      - Description
    * - 0x1
-     - S\_IXOTH (Others may execute)
+     - S_IXOTH (Others may execute)
    * - 0x2
-     - S\_IWOTH (Others may write)
+     - S_IWOTH (Others may write)
    * - 0x4
-     - S\_IROTH (Others may read)
+     - S_IROTH (Others may read)
    * - 0x8
-     - S\_IXGRP (Group members may execute)
+     - S_IXGRP (Group members may execute)
    * - 0x10
-     - S\_IWGRP (Group members may write)
+     - S_IWGRP (Group members may write)
    * - 0x20
-     - S\_IRGRP (Group members may read)
+     - S_IRGRP (Group members may read)
    * - 0x40
-     - S\_IXUSR (Owner may execute)
+     - S_IXUSR (Owner may execute)
    * - 0x80
-     - S\_IWUSR (Owner may write)
+     - S_IWUSR (Owner may write)
    * - 0x100
-     - S\_IRUSR (Owner may read)
+     - S_IRUSR (Owner may read)
    * - 0x200
-     - S\_ISVTX (Sticky bit)
+     - S_ISVTX (Sticky bit)
    * - 0x400
-     - S\_ISGID (Set GID)
+     - S_ISGID (Set GID)
    * - 0x800
-     - S\_ISUID (Set UID)
+     - S_ISUID (Set UID)
    * -
      - These are mutually-exclusive file types:
    * - 0x1000
-     - S\_IFIFO (FIFO)
+     - S_IFIFO (FIFO)
    * - 0x2000
-     - S\_IFCHR (Character device)
+     - S_IFCHR (Character device)
    * - 0x4000
-     - S\_IFDIR (Directory)
+     - S_IFDIR (Directory)
    * - 0x6000
-     - S\_IFBLK (Block device)
+     - S_IFBLK (Block device)
    * - 0x8000
-     - S\_IFREG (Regular file)
+     - S_IFREG (Regular file)
    * - 0xA000
-     - S\_IFLNK (Symbolic link)
+     - S_IFLNK (Symbolic link)
    * - 0xC000
-     - S\_IFSOCK (Socket)
+     - S_IFSOCK (Socket)
 
 .. _i_flags:
 
@@ -234,56 +234,56 @@ The ``i_flags`` field is a combination of these values:
    * - Value
      - Description
    * - 0x1
-     - This file requires secure deletion (EXT4\_SECRM\_FL). (not implemented)
+     - This file requires secure deletion (EXT4_SECRM_FL). (not implemented)
    * - 0x2
      - This file should be preserved, should undeletion be desired
-       (EXT4\_UNRM\_FL). (not implemented)
+       (EXT4_UNRM_FL). (not implemented)
    * - 0x4
-     - File is compressed (EXT4\_COMPR\_FL). (not really implemented)
+     - File is compressed (EXT4_COMPR_FL). (not really implemented)
    * - 0x8
-     - All writes to the file must be synchronous (EXT4\_SYNC\_FL).
+     - All writes to the file must be synchronous (EXT4_SYNC_FL).
    * - 0x10
-     - File is immutable (EXT4\_IMMUTABLE\_FL).
+     - File is immutable (EXT4_IMMUTABLE_FL).
    * - 0x20
-     - File can only be appended (EXT4\_APPEND\_FL).
+     - File can only be appended (EXT4_APPEND_FL).
    * - 0x40
-     - The dump(1) utility should not dump this file (EXT4\_NODUMP\_FL).
+     - The dump(1) utility should not dump this file (EXT4_NODUMP_FL).
    * - 0x80
-     - Do not update access time (EXT4\_NOATIME\_FL).
+     - Do not update access time (EXT4_NOATIME_FL).
    * - 0x100
-     - Dirty compressed file (EXT4\_DIRTY\_FL). (not used)
+     - Dirty compressed file (EXT4_DIRTY_FL). (not used)
    * - 0x200
-     - File has one or more compressed clusters (EXT4\_COMPRBLK\_FL). (not used)
+     - File has one or more compressed clusters (EXT4_COMPRBLK_FL). (not used)
    * - 0x400
-     - Do not compress file (EXT4\_NOCOMPR\_FL). (not used)
+     - Do not compress file (EXT4_NOCOMPR_FL). (not used)
    * - 0x800
-     - Encrypted inode (EXT4\_ENCRYPT\_FL). This bit value previously was
-       EXT4\_ECOMPR\_FL (compression error), which was never used.
+     - Encrypted inode (EXT4_ENCRYPT_FL). This bit value previously was
+       EXT4_ECOMPR_FL (compression error), which was never used.
    * - 0x1000
-     - Directory has hashed indexes (EXT4\_INDEX\_FL).
+     - Directory has hashed indexes (EXT4_INDEX_FL).
    * - 0x2000
-     - AFS magic directory (EXT4\_IMAGIC\_FL).
+     - AFS magic directory (EXT4_IMAGIC_FL).
    * - 0x4000
      - File data must always be written through the journal
-       (EXT4\_JOURNAL\_DATA\_FL).
+       (EXT4_JOURNAL_DATA_FL).
    * - 0x8000
-     - File tail should not be merged (EXT4\_NOTAIL\_FL). (not used by ext4)
+     - File tail should not be merged (EXT4_NOTAIL_FL). (not used by ext4)
    * - 0x10000
      - All directory entry data should be written synchronously (see
-       ``dirsync``) (EXT4\_DIRSYNC\_FL).
+       ``dirsync``) (EXT4_DIRSYNC_FL).
    * - 0x20000
-     - Top of directory hierarchy (EXT4\_TOPDIR\_FL).
+     - Top of directory hierarchy (EXT4_TOPDIR_FL).
    * - 0x40000
-     - This is a huge file (EXT4\_HUGE\_FILE\_FL).
+     - This is a huge file (EXT4_HUGE_FILE_FL).
    * - 0x80000
-     - Inode uses extents (EXT4\_EXTENTS\_FL).
+     - Inode uses extents (EXT4_EXTENTS_FL).
    * - 0x100000
-     - Verity protected file (EXT4\_VERITY\_FL).
+     - Verity protected file (EXT4_VERITY_FL).
    * - 0x200000
      - Inode stores a large extended attribute value in its data blocks
-       (EXT4\_EA\_INODE\_FL).
+       (EXT4_EA_INODE_FL).
    * - 0x400000
-     - This file has blocks allocated past EOF (EXT4\_EOFBLOCKS\_FL).
+     - This file has blocks allocated past EOF (EXT4_EOFBLOCKS_FL).
        (deprecated)
    * - 0x01000000
      - Inode is a snapshot (``EXT4_SNAPFILE_FL``). (not in mainline)
@@ -294,21 +294,21 @@ The ``i_flags`` field is a combination of these values:
      - Snapshot shrink has completed (``EXT4_SNAPFILE_SHRUNK_FL``). (not in
        mainline)
    * - 0x10000000
-     - Inode has inline data (EXT4\_INLINE\_DATA\_FL).
+     - Inode has inline data (EXT4_INLINE_DATA_FL).
    * - 0x20000000
-     - Create children with the same project ID (EXT4\_PROJINHERIT\_FL).
+     - Create children with the same project ID (EXT4_PROJINHERIT_FL).
    * - 0x80000000
-     - Reserved for ext4 library (EXT4\_RESERVED\_FL).
+     - Reserved for ext4 library (EXT4_RESERVED_FL).
    * -
      - Aggregate flags:
    * - 0x705BDFFF
      - User-visible flags.
    * - 0x604BC0FF
-     - User-modifiable flags. Note that while EXT4\_JOURNAL\_DATA\_FL and
-       EXT4\_EXTENTS\_FL can be set with setattr, they are not in the kernel's
-       EXT4\_FL\_USER\_MODIFIABLE mask, since it needs to handle the setting of
+     - User-modifiable flags. Note that while EXT4_JOURNAL_DATA_FL and
+       EXT4_EXTENTS_FL can be set with setattr, they are not in the kernel's
+       EXT4_FL_USER_MODIFIABLE mask, since it needs to handle the setting of
        these flags in a special manner and they are masked out of the set of
-       flags that are saved directly to i\_flags.
+       flags that are saved directly to i_flags.
 
 .. _i_osd1:
 
@@ -325,9 +325,9 @@ Linux:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - l\_i\_version
-     - Inode version. However, if the EA\_INODE inode flag is set, this inode
+     - __le32
+     - l_i_version
+     - Inode version. However, if the EA_INODE inode flag is set, this inode
        stores an extended attribute value and this field contains the upper 32
        bits of the attribute value's reference count.
 
@@ -342,8 +342,8 @@ Hurd:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - h\_i\_translator
+     - __le32
+     - h_i_translator
      - ??
 
 Masix:
@@ -357,8 +357,8 @@ Masix:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - m\_i\_reserved
+     - __le32
+     - m_i_reserved
      - ??
 
 .. _i_osd2:
@@ -376,30 +376,30 @@ Linux:
      - Name
      - Description
    * - 0x0
-     - \_\_le16
-     - l\_i\_blocks\_high
+     - __le16
+     - l_i_blocks_high
      - Upper 16-bits of the block count. Please see the note attached to
-       i\_blocks\_lo.
+       i_blocks_lo.
    * - 0x2
-     - \_\_le16
-     - l\_i\_file\_acl\_high
+     - __le16
+     - l_i_file_acl_high
      - Upper 16-bits of the extended attribute block (historically, the file
        ACL location). See the Extended Attributes section below.
    * - 0x4
-     - \_\_le16
-     - l\_i\_uid\_high
+     - __le16
+     - l_i_uid_high
      - Upper 16-bits of the Owner UID.
    * - 0x6
-     - \_\_le16
-     - l\_i\_gid\_high
+     - __le16
+     - l_i_gid_high
      - Upper 16-bits of the GID.
    * - 0x8
-     - \_\_le16
-     - l\_i\_checksum\_lo
+     - __le16
+     - l_i_checksum_lo
      - Lower 16-bits of the inode checksum.
    * - 0xA
-     - \_\_le16
-     - l\_i\_reserved
+     - __le16
+     - l_i_reserved
      - Unused.
 
 Hurd:
@@ -413,24 +413,24 @@ Hurd:
      - Name
      - Description
    * - 0x0
-     - \_\_le16
-     - h\_i\_reserved1
+     - __le16
+     - h_i_reserved1
      - ??
    * - 0x2
-     - \_\_u16
-     - h\_i\_mode\_high
+     - __u16
+     - h_i_mode_high
      - Upper 16-bits of the file mode.
    * - 0x4
-     - \_\_le16
-     - h\_i\_uid\_high
+     - __le16
+     - h_i_uid_high
      - Upper 16-bits of the Owner UID.
    * - 0x6
-     - \_\_le16
-     - h\_i\_gid\_high
+     - __le16
+     - h_i_gid_high
      - Upper 16-bits of the GID.
    * - 0x8
-     - \_\_u32
-     - h\_i\_author
+     - __u32
+     - h_i_author
      - Author code?
 
 Masix:
@@ -444,17 +444,17 @@ Masix:
      - Name
      - Description
    * - 0x0
-     - \_\_le16
-     - h\_i\_reserved1
+     - __le16
+     - h_i_reserved1
      - ??
    * - 0x2
-     - \_\_u16
-     - m\_i\_file\_acl\_high
+     - __u16
+     - m_i_file_acl_high
      - Upper 16-bits of the extended attribute block (historically, the file
        ACL location).
    * - 0x4
-     - \_\_u32
-     - m\_i\_reserved2[2]
+     - __u32
+     - m_i_reserved2[2]
      - ??
 
 Inode Size
@@ -466,11 +466,11 @@ In ext2 and ext3, the inode structure size was fixed at 128 bytes
 on-disk inode at format time for all inodes in the filesystem to provide
 space beyond the end of the original ext2 inode. The on-disk inode
 record size is recorded in the superblock as ``s_inode_size``. The
-number of bytes actually used by struct ext4\_inode beyond the original
+number of bytes actually used by struct ext4_inode beyond the original
 128-byte ext2 inode is recorded in the ``i_extra_isize`` field for each
-inode, which allows struct ext4\_inode to grow for a new kernel without
+inode, which allows struct ext4_inode to grow for a new kernel without
 having to upgrade all of the on-disk inodes. Access to fields beyond
-EXT2\_GOOD\_OLD\_INODE\_SIZE should be verified to be within
+EXT2_GOOD_OLD_INODE_SIZE should be verified to be within
 ``i_extra_isize``. By default, ext4 inode records are 256 bytes, and (as
 of August 2019) the inode structure is 160 bytes
 (``i_extra_isize = 32``). The extra space between the end of the inode
@@ -516,7 +516,7 @@ creation time (crtime); this field is 64-bits wide and decoded in the
 same manner as 64-bit [cma]time. Neither crtime nor dtime are accessible
 through the regular stat() interface, though debugfs will report them.
 
-We use the 32-bit signed time value plus (2^32 \* (extra epoch bits)).
+We use the 32-bit signed time value plus (2^32 * (extra epoch bits)).
 In other words:
 
 .. list-table::
@@ -525,8 +525,8 @@ In other words:
 
    * - Extra epoch bits
      - MSB of 32-bit time
-     - Adjustment for signed 32-bit to 64-bit tv\_sec
-     - Decoded 64-bit tv\_sec
+     - Adjustment for signed 32-bit to 64-bit tv_sec
+     - Decoded 64-bit tv_sec
      - valid time range
    * - 0 0
      - 1
index 5fad388..a6bef52 100644 (file)
@@ -63,8 +63,8 @@ Generally speaking, the journal has this format:
    :header-rows: 1
 
    * - Superblock
-     - descriptor\_block (data\_blocks or revocation\_block) [more data or
-       revocations] commmit\_block
+     - descriptor_block (data_blocks or revocation_block) [more data or
+       revocations] commmit_block
      - [more transactions...]
    * - 
      - One transaction
@@ -93,8 +93,8 @@ superblock.
    * - 1024 bytes of padding
      - ext4 Superblock
      - Journal Superblock
-     - descriptor\_block (data\_blocks or revocation\_block) [more data or
-       revocations] commmit\_block
+     - descriptor_block (data_blocks or revocation_block) [more data or
+       revocations] commmit_block
      - [more transactions...]
    * - 
      -
@@ -117,17 +117,17 @@ Every block in the journal starts with a common 12-byte header
      - Name
      - Description
    * - 0x0
-     - \_\_be32
-     - h\_magic
+     - __be32
+     - h_magic
      - jbd2 magic number, 0xC03B3998.
    * - 0x4
-     - \_\_be32
-     - h\_blocktype
+     - __be32
+     - h_blocktype
      - Description of what this block contains. See the jbd2_blocktype_ table
        below.
    * - 0x8
-     - \_\_be32
-     - h\_sequence
+     - __be32
+     - h_sequence
      - The transaction ID that goes with this block.
 
 .. _jbd2_blocktype:
@@ -177,99 +177,99 @@ which is 1024 bytes long:
      -
      - Static information describing the journal.
    * - 0x0
-     - journal\_header\_t (12 bytes)
-     - s\_header
+     - journal_header_t (12 bytes)
+     - s_header
      - Common header identifying this as a superblock.
    * - 0xC
-     - \_\_be32
-     - s\_blocksize
+     - __be32
+     - s_blocksize
      - Journal device block size.
    * - 0x10
-     - \_\_be32
-     - s\_maxlen
+     - __be32
+     - s_maxlen
      - Total number of blocks in this journal.
    * - 0x14
-     - \_\_be32
-     - s\_first
+     - __be32
+     - s_first
      - First block of log information.
    * -
      -
      -
      - Dynamic information describing the current state of the log.
    * - 0x18
-     - \_\_be32
-     - s\_sequence
+     - __be32
+     - s_sequence
      - First commit ID expected in log.
    * - 0x1C
-     - \_\_be32
-     - s\_start
+     - __be32
+     - s_start
      - Block number of the start of log. Contrary to the comments, this field
        being zero does not imply that the journal is clean!
    * - 0x20
-     - \_\_be32
-     - s\_errno
-     - Error value, as set by jbd2\_journal\_abort().
+     - __be32
+     - s_errno
+     - Error value, as set by jbd2_journal_abort().
    * -
      -
      -
      - The remaining fields are only valid in a v2 superblock.
    * - 0x24
-     - \_\_be32
-     - s\_feature\_compat;
+     - __be32
+     - s_feature_compat;
      - Compatible feature set. See the table jbd2_compat_ below.
    * - 0x28
-     - \_\_be32
-     - s\_feature\_incompat
+     - __be32
+     - s_feature_incompat
      - Incompatible feature set. See the table jbd2_incompat_ below.
    * - 0x2C
-     - \_\_be32
-     - s\_feature\_ro\_compat
+     - __be32
+     - s_feature_ro_compat
      - Read-only compatible feature set. There aren't any of these currently.
    * - 0x30
-     - \_\_u8
-     - s\_uuid[16]
+     - __u8
+     - s_uuid[16]
      - 128-bit uuid for journal. This is compared against the copy in the ext4
        super block at mount time.
    * - 0x40
-     - \_\_be32
-     - s\_nr\_users
+     - __be32
+     - s_nr_users
      - Number of file systems sharing this journal.
    * - 0x44
-     - \_\_be32
-     - s\_dynsuper
+     - __be32
+     - s_dynsuper
      - Location of dynamic super block copy. (Not used?)
    * - 0x48
-     - \_\_be32
-     - s\_max\_transaction
+     - __be32
+     - s_max_transaction
      - Limit of journal blocks per transaction. (Not used?)
    * - 0x4C
-     - \_\_be32
-     - s\_max\_trans\_data
+     - __be32
+     - s_max_trans_data
      - Limit of data blocks per transaction. (Not used?)
    * - 0x50
-     - \_\_u8
-     - s\_checksum\_type
+     - __u8
+     - s_checksum_type
      - Checksum algorithm used for the journal.  See jbd2_checksum_type_ for
        more info.
    * - 0x51
-     - \_\_u8[3]
-     - s\_padding2
+     - __u8[3]
+     - s_padding2
      -
    * - 0x54
-     - \_\_be32
-     - s\_num\_fc\_blocks
+     - __be32
+     - s_num_fc_blocks
      - Number of fast commit blocks in the journal.
    * - 0x58
-     - \_\_u32
-     - s\_padding[42]
+     - __u32
+     - s_padding[42]
      -
    * - 0xFC
-     - \_\_be32
-     - s\_checksum
+     - __be32
+     - s_checksum
      - Checksum of the entire superblock, with this field set to zero.
    * - 0x100
-     - \_\_u8
-     - s\_users[16\*48]
+     - __u8
+     - s_users[16*48]
      - ids of all file systems sharing the log. e2fsprogs/Linux don't allow
        shared external journals, but I imagine Lustre (or ocfs2?), which use
        the jbd2 code, might.
@@ -286,7 +286,7 @@ The journal compat features are any combination of the following:
      - Description
    * - 0x1
      - Journal maintains checksums on the data blocks.
-       (JBD2\_FEATURE\_COMPAT\_CHECKSUM)
+       (JBD2_FEATURE_COMPAT_CHECKSUM)
 
 .. _jbd2_incompat:
 
@@ -299,23 +299,23 @@ The journal incompat features are any combination of the following:
    * - Value
      - Description
    * - 0x1
-     - Journal has block revocation records. (JBD2\_FEATURE\_INCOMPAT\_REVOKE)
+     - Journal has block revocation records. (JBD2_FEATURE_INCOMPAT_REVOKE)
    * - 0x2
      - Journal can deal with 64-bit block numbers.
-       (JBD2\_FEATURE\_INCOMPAT\_64BIT)
+       (JBD2_FEATURE_INCOMPAT_64BIT)
    * - 0x4
-     - Journal commits asynchronously. (JBD2\_FEATURE\_INCOMPAT\_ASYNC\_COMMIT)
+     - Journal commits asynchronously. (JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)
    * - 0x8
      - This journal uses v2 of the checksum on-disk format. Each journal
        metadata block gets its own checksum, and the block tags in the
        descriptor table contain checksums for each of the data blocks in the
-       journal. (JBD2\_FEATURE\_INCOMPAT\_CSUM\_V2)
+       journal. (JBD2_FEATURE_INCOMPAT_CSUM_V2)
    * - 0x10
      - This journal uses v3 of the checksum on-disk format. This is the same as
        v2, but the journal block tag size is fixed regardless of the size of
-       block numbers. (JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3)
+       block numbers. (JBD2_FEATURE_INCOMPAT_CSUM_V3)
    * - 0x20
-     - Journal has fast commit blocks. (JBD2\_FEATURE\_INCOMPAT\_FAST\_COMMIT)
+     - Journal has fast commit blocks. (JBD2_FEATURE_INCOMPAT_FAST_COMMIT)
 
 .. _jbd2_checksum_type:
 
@@ -355,11 +355,11 @@ Descriptor blocks consume at least 36 bytes, but use a full block:
      - Name
      - Descriptor
    * - 0x0
-     - journal\_header\_t
+     - journal_header_t
      - (open coded)
      - Common block header.
    * - 0xC
-     - struct journal\_block\_tag\_s
+     - struct journal_block_tag_s
      - open coded array[]
      - Enough tags either to fill up the block or to describe all the data
        blocks that follow this descriptor block.
@@ -367,7 +367,7 @@ Descriptor blocks consume at least 36 bytes, but use a full block:
 Journal block tags have any of the following formats, depending on which
 journal feature and block tag flags are set.
 
-If JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3 is set, the journal block tag is
+If JBD2_FEATURE_INCOMPAT_CSUM_V3 is set, the journal block tag is
 defined as ``struct journal_block_tag3_s``, which looks like the
 following. The size is 16 or 32 bytes.
 
@@ -380,24 +380,24 @@ following. The size is 16 or 32 bytes.
      - Name
      - Descriptor
    * - 0x0
-     - \_\_be32
-     - t\_blocknr
+     - __be32
+     - t_blocknr
      - Lower 32-bits of the location of where the corresponding data block
        should end up on disk.
    * - 0x4
-     - \_\_be32
-     - t\_flags
+     - __be32
+     - t_flags
      - Flags that go with the descriptor. See the table jbd2_tag_flags_ for
        more info.
    * - 0x8
-     - \_\_be32
-     - t\_blocknr\_high
+     - __be32
+     - t_blocknr_high
      - Upper 32-bits of the location of where the corresponding data block
-       should end up on disk. This is zero if JBD2\_FEATURE\_INCOMPAT\_64BIT is
+       should end up on disk. This is zero if JBD2_FEATURE_INCOMPAT_64BIT is
        not enabled.
    * - 0xC
-     - \_\_be32
-     - t\_checksum
+     - __be32
+     - t_checksum
      - Checksum of the journal UUID, the sequence number, and the data block.
    * -
      -
@@ -433,7 +433,7 @@ The journal tag flags are any combination of the following:
    * - 0x8
      - This is the last tag in this descriptor block.
 
-If JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3 is NOT set, the journal block tag
+If JBD2_FEATURE_INCOMPAT_CSUM_V3 is NOT set, the journal block tag
 is defined as ``struct journal_block_tag_s``, which looks like the
 following. The size is 8, 12, 24, or 28 bytes:
 
@@ -446,18 +446,18 @@ following. The size is 8, 12, 24, or 28 bytes:
      - Name
      - Descriptor
    * - 0x0
-     - \_\_be32
-     - t\_blocknr
+     - __be32
+     - t_blocknr
      - Lower 32-bits of the location of where the corresponding data block
        should end up on disk.
    * - 0x4
-     - \_\_be16
-     - t\_checksum
+     - __be16
+     - t_checksum
      - Checksum of the journal UUID, the sequence number, and the data block.
        Note that only the lower 16 bits are stored.
    * - 0x6
-     - \_\_be16
-     - t\_flags
+     - __be16
+     - t_flags
      - Flags that go with the descriptor. See the table jbd2_tag_flags_ for
        more info.
    * -
@@ -466,8 +466,8 @@ following. The size is 8, 12, 24, or 28 bytes:
      - This next field is only present if the super block indicates support for
        64-bit block numbers.
    * - 0x8
-     - \_\_be32
-     - t\_blocknr\_high
+     - __be32
+     - t_blocknr_high
      - Upper 32-bits of the location of where the corresponding data block
        should end up on disk.
    * -
@@ -483,8 +483,8 @@ following. The size is 8, 12, 24, or 28 bytes:
        ``j_uuid`` field in ``struct journal_s``, but only tune2fs touches that
        field.
 
-If JBD2\_FEATURE\_INCOMPAT\_CSUM\_V2 or
-JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3 are set, the end of the block is a
+If JBD2_FEATURE_INCOMPAT_CSUM_V2 or
+JBD2_FEATURE_INCOMPAT_CSUM_V3 are set, the end of the block is a
 ``struct jbd2_journal_block_tail``, which looks like this:
 
 .. list-table::
@@ -496,8 +496,8 @@ JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3 are set, the end of the block is a
      - Name
      - Descriptor
    * - 0x0
-     - \_\_be32
-     - t\_checksum
+     - __be32
+     - t_checksum
      - Checksum of the journal UUID + the descriptor block, with this field set
        to zero.
 
@@ -538,25 +538,25 @@ length, but use a full block:
      - Name
      - Description
    * - 0x0
-     - journal\_header\_t
-     - r\_header
+     - journal_header_t
+     - r_header
      - Common block header.
    * - 0xC
-     - \_\_be32
-     - r\_count
+     - __be32
+     - r_count
      - Number of bytes used in this block.
    * - 0x10
-     - \_\_be32 or \_\_be64
+     - __be32 or __be64
      - blocks[0]
      - Blocks to revoke.
 
-After r\_count is a linear array of block numbers that are effectively
+After r_count is a linear array of block numbers that are effectively
 revoked by this transaction. The size of each block number is 8 bytes if
 the superblock advertises 64-bit block number support, or 4 bytes
 otherwise.
 
-If JBD2\_FEATURE\_INCOMPAT\_CSUM\_V2 or
-JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3 are set, the end of the revocation
+If JBD2_FEATURE_INCOMPAT_CSUM_V2 or
+JBD2_FEATURE_INCOMPAT_CSUM_V3 are set, the end of the revocation
 block is a ``struct jbd2_journal_revoke_tail``, which has this format:
 
 .. list-table::
@@ -568,8 +568,8 @@ block is a ``struct jbd2_journal_revoke_tail``, which has this format:
      - Name
      - Description
    * - 0x0
-     - \_\_be32
-     - r\_checksum
+     - __be32
+     - r_checksum
      - Checksum of the journal UUID + revocation block
 
 Commit Block
@@ -592,38 +592,38 @@ bytes long (but uses a full block):
      - Name
      - Descriptor
    * - 0x0
-     - journal\_header\_s
+     - journal_header_s
      - (open coded)
      - Common block header.
    * - 0xC
      - unsigned char
-     - h\_chksum\_type
+     - h_chksum_type
      - The type of checksum to use to verify the integrity of the data blocks
        in the transaction. See jbd2_checksum_type_ for more info.
    * - 0xD
      - unsigned char
-     - h\_chksum\_size
+     - h_chksum_size
      - The number of bytes used by the checksum. Most likely 4.
    * - 0xE
      - unsigned char
-     - h\_padding[2]
+     - h_padding[2]
      -
    * - 0x10
-     - \_\_be32
-     - h\_chksum[JBD2\_CHECKSUM\_BYTES]
+     - __be32
+     - h_chksum[JBD2_CHECKSUM_BYTES]
      - 32 bytes of space to store checksums. If
-       JBD2\_FEATURE\_INCOMPAT\_CSUM\_V2 or JBD2\_FEATURE\_INCOMPAT\_CSUM\_V3
+       JBD2_FEATURE_INCOMPAT_CSUM_V2 or JBD2_FEATURE_INCOMPAT_CSUM_V3
        are set, the first ``__be32`` is the checksum of the journal UUID and
        the entire commit block, with this field zeroed. If
-       JBD2\_FEATURE\_COMPAT\_CHECKSUM is set, the first ``__be32`` is the
+       JBD2_FEATURE_COMPAT_CHECKSUM is set, the first ``__be32`` is the
        crc32 of all the blocks already written to the transaction.
    * - 0x30
-     - \_\_be64
-     - h\_commit\_sec
+     - __be64
+     - h_commit_sec
      - The time that the transaction was committed, in seconds since the epoch.
    * - 0x38
-     - \_\_be32
-     - h\_commit\_nsec
+     - __be32
+     - h_commit_nsec
      - Nanoseconds component of the above timestamp.
 
 Fast commits
index 2566098..174dd65 100644 (file)
@@ -7,8 +7,8 @@ Multiple mount protection (MMP) is a feature that protects the
 filesystem against multiple hosts trying to use the filesystem
 simultaneously. When a filesystem is opened (for mounting, or fsck,
 etc.), the MMP code running on the node (call it node A) checks a
-sequence number. If the sequence number is EXT4\_MMP\_SEQ\_CLEAN, the
-open continues. If the sequence number is EXT4\_MMP\_SEQ\_FSCK, then
+sequence number. If the sequence number is EXT4_MMP_SEQ_CLEAN, the
+open continues. If the sequence number is EXT4_MMP_SEQ_FSCK, then
 fsck is (hopefully) running, and open fails immediately. Otherwise, the
 open code will wait for twice the specified MMP check interval and check
 the sequence number again. If the sequence number has changed, then the
@@ -40,38 +40,38 @@ The MMP structure (``struct mmp_struct``) is as follows:
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - mmp\_magic
+     - __le32
+     - mmp_magic
      - Magic number for MMP, 0x004D4D50 (“MMP”).
    * - 0x4
-     - \_\_le32
-     - mmp\_seq
+     - __le32
+     - mmp_seq
      - Sequence number, updated periodically.
    * - 0x8
-     - \_\_le64
-     - mmp\_time
+     - __le64
+     - mmp_time
      - Time that the MMP block was last updated.
    * - 0x10
      - char[64]
-     - mmp\_nodename
+     - mmp_nodename
      - Hostname of the node that opened the filesystem.
    * - 0x50
      - char[32]
-     - mmp\_bdevname
+     - mmp_bdevname
      - Block device name of the filesystem.
    * - 0x70
-     - \_\_le16
-     - mmp\_check\_interval
+     - __le16
+     - mmp_check_interval
      - The MMP re-check interval, in seconds.
    * - 0x72
-     - \_\_le16
-     - mmp\_pad1
+     - __le16
+     - mmp_pad1
      - Zero.
    * - 0x74
-     - \_\_le32[226]
-     - mmp\_pad2
+     - __le32[226]
+     - mmp_pad2
      - Zero.
    * - 0x3FC
-     - \_\_le32
-     - mmp\_checksum
+     - __le32
+     - mmp_checksum
      - Checksum of the MMP block.
index 123ebfd..0fad6ed 100644 (file)
@@ -7,7 +7,7 @@ An ext4 file system is split into a series of block groups. To reduce
 performance difficulties due to fragmentation, the block allocator tries
 very hard to keep each file's blocks within the same group, thereby
 reducing seek times. The size of a block group is specified in
-``sb.s_blocks_per_group`` blocks, though it can also calculated as 8 \*
+``sb.s_blocks_per_group`` blocks, though it can also calculated as 8 *
 ``block_size_in_bytes``. With the default block size of 4KiB, each group
 will contain 32,768 blocks, for a length of 128MiB. The number of block
 groups is the size of the device divided by the size of a block group.
index 94f304e..fc06369 100644 (file)
@@ -34,7 +34,7 @@ ext4 reserves some inode for special features, as follows:
    * - 10
      - Replica inode, used for some non-upstream feature?
    * - 11
-     - Traditional first non-reserved inode. Usually this is the lost+found directory. See s\_first\_ino in the superblock.
+     - Traditional first non-reserved inode. Usually this is the lost+found directory. See s_first_ino in the superblock.
 
 Note that there are also some inodes allocated from non-reserved inode numbers
 for other filesystem features which are not referenced from standard directory
@@ -47,9 +47,9 @@ hierarchy. These are generally reference from the superblock. They are:
    * - Superblock field
      - Description
 
-   * - s\_lpf\_ino
+   * - s_lpf_ino
      - Inode number of lost+found directory.
-   * - s\_prj\_quota\_inum
+   * - s_prj_quota_inum
      - Inode number of quota file tracking project quotas
-   * - s\_orphan\_file\_inum
+   * - s_orphan_file_inum
      - Inode number of file tracking orphan inodes.
index f6a548e..2688885 100644 (file)
@@ -7,7 +7,7 @@ The superblock records various information about the enclosing
 filesystem, such as block counts, inode counts, supported features,
 maintenance information, and more.
 
-If the sparse\_super feature flag is set, redundant copies of the
+If the sparse_super feature flag is set, redundant copies of the
 superblock and group descriptors are kept only in the groups whose group
 number is either 0 or a power of 3, 5, or 7. If the flag is not set,
 redundant copies are kept in all groups.
@@ -27,107 +27,107 @@ The ext4 superblock is laid out as follows in
      - Name
      - Description
    * - 0x0
-     - \_\_le32
-     - s\_inodes\_count
+     - __le32
+     - s_inodes_count
      - Total inode count.
    * - 0x4
-     - \_\_le32
-     - s\_blocks\_count\_lo
+     - __le32
+     - s_blocks_count_lo
      - Total block count.
    * - 0x8
-     - \_\_le32
-     - s\_r\_blocks\_count\_lo
+     - __le32
+     - s_r_blocks_count_lo
      - This number of blocks can only be allocated by the super-user.
    * - 0xC
-     - \_\_le32
-     - s\_free\_blocks\_count\_lo
+     - __le32
+     - s_free_blocks_count_lo
      - Free block count.
    * - 0x10
-     - \_\_le32
-     - s\_free\_inodes\_count
+     - __le32
+     - s_free_inodes_count
      - Free inode count.
    * - 0x14
-     - \_\_le32
-     - s\_first\_data\_block
+     - __le32
+     - s_first_data_block
      - First data block. This must be at least 1 for 1k-block filesystems and
        is typically 0 for all other block sizes.
    * - 0x18
-     - \_\_le32
-     - s\_log\_block\_size
-     - Block size is 2 ^ (10 + s\_log\_block\_size).
+     - __le32
+     - s_log_block_size
+     - Block size is 2 ^ (10 + s_log_block_size).
    * - 0x1C
-     - \_\_le32
-     - s\_log\_cluster\_size
-     - Cluster size is 2 ^ (10 + s\_log\_cluster\_size) blocks if bigalloc is
-       enabled. Otherwise s\_log\_cluster\_size must equal s\_log\_block\_size.
+     - __le32
+     - s_log_cluster_size
+     - Cluster size is 2 ^ (10 + s_log_cluster_size) blocks if bigalloc is
+       enabled. Otherwise s_log_cluster_size must equal s_log_block_size.
    * - 0x20
-     - \_\_le32
-     - s\_blocks\_per\_group
+     - __le32
+     - s_blocks_per_group
      - Blocks per group.
    * - 0x24
-     - \_\_le32
-     - s\_clusters\_per\_group
+     - __le32
+     - s_clusters_per_group
      - Clusters per group, if bigalloc is enabled. Otherwise
-       s\_clusters\_per\_group must equal s\_blocks\_per\_group.
+       s_clusters_per_group must equal s_blocks_per_group.
    * - 0x28
-     - \_\_le32
-     - s\_inodes\_per\_group
+     - __le32
+     - s_inodes_per_group
      - Inodes per group.
    * - 0x2C
-     - \_\_le32
-     - s\_mtime
+     - __le32
+     - s_mtime
      - Mount time, in seconds since the epoch.
    * - 0x30
-     - \_\_le32
-     - s\_wtime
+     - __le32
+     - s_wtime
      - Write time, in seconds since the epoch.
    * - 0x34
-     - \_\_le16
-     - s\_mnt\_count
+     - __le16
+     - s_mnt_count
      - Number of mounts since the last fsck.
    * - 0x36
-     - \_\_le16
-     - s\_max\_mnt\_count
+     - __le16
+     - s_max_mnt_count
      - Number of mounts beyond which a fsck is needed.
    * - 0x38
-     - \_\_le16
-     - s\_magic
+     - __le16
+     - s_magic
      - Magic signature, 0xEF53
    * - 0x3A
-     - \_\_le16
-     - s\_state
+     - __le16
+     - s_state
      - File system state. See super_state_ for more info.
    * - 0x3C
-     - \_\_le16
-     - s\_errors
+     - __le16
+     - s_errors
      - Behaviour when detecting errors. See super_errors_ for more info.
    * - 0x3E
-     - \_\_le16
-     - s\_minor\_rev\_level
+     - __le16
+     - s_minor_rev_level
      - Minor revision level.
    * - 0x40
-     - \_\_le32
-     - s\_lastcheck
+     - __le32
+     - s_lastcheck
      - Time of last check, in seconds since the epoch.
    * - 0x44
-     - \_\_le32
-     - s\_checkinterval
+     - __le32
+     - s_checkinterval
      - Maximum time between checks, in seconds.
    * - 0x48
-     - \_\_le32
-     - s\_creator\_os
+     - __le32
+     - s_creator_os
      - Creator OS. See the table super_creator_ for more info.
    * - 0x4C
-     - \_\_le32
-     - s\_rev\_level
+     - __le32
+     - s_rev_level
      - Revision level. See the table super_revision_ for more info.
    * - 0x50
-     - \_\_le16
-     - s\_def\_resuid
+     - __le16
+     - s_def_resuid
      - Default uid for reserved blocks.
    * - 0x52
-     - \_\_le16
-     - s\_def\_resgid
+     - __le16
+     - s_def_resgid
      - Default gid for reserved blocks.
    * -
      -
@@ -143,50 +143,50 @@ The ext4 superblock is laid out as follows in
        about a feature in either the compatible or incompatible feature set, it
        must abort and not try to meddle with things it doesn't understand...
    * - 0x54
-     - \_\_le32
-     - s\_first\_ino
+     - __le32
+     - s_first_ino
      - First non-reserved inode.
    * - 0x58
-     - \_\_le16
-     - s\_inode\_size
+     - __le16
+     - s_inode_size
      - Size of inode structure, in bytes.
    * - 0x5A
-     - \_\_le16
-     - s\_block\_group\_nr
+     - __le16
+     - s_block_group_nr
      - Block group # of this superblock.
    * - 0x5C
-     - \_\_le32
-     - s\_feature\_compat
+     - __le32
+     - s_feature_compat
      - Compatible feature set flags. Kernel can still read/write this fs even
        if it doesn't understand a flag; fsck should not do that. See the
        super_compat_ table for more info.
    * - 0x60
-     - \_\_le32
-     - s\_feature\_incompat
+     - __le32
+     - s_feature_incompat
      - Incompatible feature set. If the kernel or fsck doesn't understand one
        of these bits, it should stop. See the super_incompat_ table for more
        info.
    * - 0x64
-     - \_\_le32
-     - s\_feature\_ro\_compat
+     - __le32
+     - s_feature_ro_compat
      - Readonly-compatible feature set. If the kernel doesn't understand one of
        these bits, it can still mount read-only. See the super_rocompat_ table
        for more info.
    * - 0x68
-     - \_\_u8
-     - s\_uuid[16]
+     - __u8
+     - s_uuid[16]
      - 128-bit UUID for volume.
    * - 0x78
      - char
-     - s\_volume\_name[16]
+     - s_volume_name[16]
      - Volume label.
    * - 0x88
      - char
-     - s\_last\_mounted[64]
+     - s_last_mounted[64]
      - Directory where filesystem was last mounted.
    * - 0xC8
-     - \_\_le32
-     - s\_algorithm\_usage\_bitmap
+     - __le32
+     - s_algorithm_usage_bitmap
      - For compression (Not used in e2fsprogs/Linux)
    * -
      -
@@ -194,18 +194,18 @@ The ext4 superblock is laid out as follows in
      - Performance hints.  Directory preallocation should only happen if the
        EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
    * - 0xCC
-     - \_\_u8
-     - s\_prealloc\_blocks
+     - __u8
+     - s_prealloc_blocks
      - #. of blocks to try to preallocate for ... files? (Not used in
        e2fsprogs/Linux)
    * - 0xCD
-     - \_\_u8
-     - s\_prealloc\_dir\_blocks
+     - __u8
+     - s_prealloc_dir_blocks
      - #. of blocks to preallocate for directories. (Not used in
        e2fsprogs/Linux)
    * - 0xCE
-     - \_\_le16
-     - s\_reserved\_gdt\_blocks
+     - __le16
+     - s_reserved_gdt_blocks
      - Number of reserved GDT entries for future filesystem expansion.
    * -
      -
@@ -213,281 +213,281 @@ The ext4 superblock is laid out as follows in
      - Journalling support is valid only if EXT4_FEATURE_COMPAT_HAS_JOURNAL is
        set.
    * - 0xD0
-     - \_\_u8
-     - s\_journal\_uuid[16]
+     - __u8
+     - s_journal_uuid[16]
      - UUID of journal superblock
    * - 0xE0
-     - \_\_le32
-     - s\_journal\_inum
+     - __le32
+     - s_journal_inum
      - inode number of journal file.
    * - 0xE4
-     - \_\_le32
-     - s\_journal\_dev
+     - __le32
+     - s_journal_dev
      - Device number of journal file, if the external journal feature flag is
        set.
    * - 0xE8
-     - \_\_le32
-     - s\_last\_orphan
+     - __le32
+     - s_last_orphan
      - Start of list of orphaned inodes to delete.
    * - 0xEC
-     - \_\_le32
-     - s\_hash\_seed[4]
+     - __le32
+     - s_hash_seed[4]
      - HTREE hash seed.
    * - 0xFC
-     - \_\_u8
-     - s\_def\_hash\_version
+     - __u8
+     - s_def_hash_version
      - Default hash algorithm to use for directory hashes. See super_def_hash_
        for more info.
    * - 0xFD
-     - \_\_u8
-     - s\_jnl\_backup\_type
-     - If this value is 0 or EXT3\_JNL\_BACKUP\_BLOCKS (1), then the
+     - __u8
+     - s_jnl_backup_type
+     - If this value is 0 or EXT3_JNL_BACKUP_BLOCKS (1), then the
        ``s_jnl_blocks`` field contains a duplicate copy of the inode's
        ``i_block[]`` array and ``i_size``.
    * - 0xFE
-     - \_\_le16
-     - s\_desc\_size
+     - __le16
+     - s_desc_size
      - Size of group descriptors, in bytes, if the 64bit incompat feature flag
        is set.
    * - 0x100
-     - \_\_le32
-     - s\_default\_mount\_opts
+     - __le32
+     - s_default_mount_opts
      - Default mount options. See the super_mountopts_ table for more info.
    * - 0x104
-     - \_\_le32
-     - s\_first\_meta\_bg
-     - First metablock block group, if the meta\_bg feature is enabled.
+     - __le32
+     - s_first_meta_bg
+     - First metablock block group, if the meta_bg feature is enabled.
    * - 0x108
-     - \_\_le32
-     - s\_mkfs\_time
+     - __le32
+     - s_mkfs_time
      - When the filesystem was created, in seconds since the epoch.
    * - 0x10C
-     - \_\_le32
-     - s\_jnl\_blocks[17]
+     - __le32
+     - s_jnl_blocks[17]
      - Backup copy of the journal inode's ``i_block[]`` array in the first 15
-       elements and i\_size\_high and i\_size in the 16th and 17th elements,
+       elements and i_size_high and i_size in the 16th and 17th elements,
        respectively.
    * -
      -
      -
      - 64bit support is valid only if EXT4_FEATURE_COMPAT_64BIT is set.
    * - 0x150
-     - \_\_le32
-     - s\_blocks\_count\_hi
+     - __le32
+     - s_blocks_count_hi
      - High 32-bits of the block count.
    * - 0x154
-     - \_\_le32
-     - s\_r\_blocks\_count\_hi
+     - __le32
+     - s_r_blocks_count_hi
      - High 32-bits of the reserved block count.
    * - 0x158
-     - \_\_le32
-     - s\_free\_blocks\_count\_hi
+     - __le32
+     - s_free_blocks_count_hi
      - High 32-bits of the free block count.
    * - 0x15C
-     - \_\_le16
-     - s\_min\_extra\_isize
+     - __le16
+     - s_min_extra_isize
      - All inodes have at least # bytes.
    * - 0x15E
-     - \_\_le16
-     - s\_want\_extra\_isize
+     - __le16
+     - s_want_extra_isize
      - New inodes should reserve # bytes.
    * - 0x160
-     - \_\_le32
-     - s\_flags
+     - __le32
+     - s_flags
      - Miscellaneous flags. See the super_flags_ table for more info.
    * - 0x164
-     - \_\_le16
-     - s\_raid\_stride
+     - __le16
+     - s_raid_stride
      - RAID stride. This is the number of logical blocks read from or written
        to the disk before moving to the next disk. This affects the placement
        of filesystem metadata, which will hopefully make RAID storage faster.
    * - 0x166
-     - \_\_le16
-     - s\_mmp\_interval
+     - __le16
+     - s_mmp_interval
      - #. seconds to wait in multi-mount prevention (MMP) checking. In theory,
        MMP is a mechanism to record in the superblock which host and device
        have mounted the filesystem, in order to prevent multiple mounts. This
        feature does not seem to be implemented...
    * - 0x168
-     - \_\_le64
-     - s\_mmp\_block
+     - __le64
+     - s_mmp_block
      - Block # for multi-mount protection data.
    * - 0x170
-     - \_\_le32
-     - s\_raid\_stripe\_width
+     - __le32
+     - s_raid_stripe_width
      - RAID stripe width. This is the number of logical blocks read from or
        written to the disk before coming back to the current disk. This is used
        by the block allocator to try to reduce the number of read-modify-write
        operations in a RAID5/6.
    * - 0x174
-     - \_\_u8
-     - s\_log\_groups\_per\_flex
+     - __u8
+     - s_log_groups_per_flex
      - Size of a flexible block group is 2 ^ ``s_log_groups_per_flex``.
    * - 0x175
-     - \_\_u8
-     - s\_checksum\_type
+     - __u8
+     - s_checksum_type
      - Metadata checksum algorithm type. The only valid value is 1 (crc32c).
    * - 0x176
-     - \_\_le16
-     - s\_reserved\_pad
+     - __le16
+     - s_reserved_pad
      -
    * - 0x178
-     - \_\_le64
-     - s\_kbytes\_written
+     - __le64
+     - s_kbytes_written
      - Number of KiB written to this filesystem over its lifetime.
    * - 0x180
-     - \_\_le32
-     - s\_snapshot\_inum
+     - __le32
+     - s_snapshot_inum
      - inode number of active snapshot. (Not used in e2fsprogs/Linux.)
    * - 0x184
-     - \_\_le32
-     - s\_snapshot\_id
+     - __le32
+     - s_snapshot_id
      - Sequential ID of active snapshot. (Not used in e2fsprogs/Linux.)
    * - 0x188
-     - \_\_le64
-     - s\_snapshot\_r\_blocks\_count
+     - __le64
+     - s_snapshot_r_blocks_count
      - Number of blocks reserved for active snapshot's future use. (Not used in
        e2fsprogs/Linux.)
    * - 0x190
-     - \_\_le32
-     - s\_snapshot\_list
+     - __le32
+     - s_snapshot_list
      - inode number of the head of the on-disk snapshot list. (Not used in
        e2fsprogs/Linux.)
    * - 0x194
-     - \_\_le32
-     - s\_error\_count
+     - __le32
+     - s_error_count
      - Number of errors seen.
    * - 0x198
-     - \_\_le32
-     - s\_first\_error\_time
+     - __le32
+     - s_first_error_time
      - First time an error happened, in seconds since the epoch.
    * - 0x19C
-     - \_\_le32
-     - s\_first\_error\_ino
+     - __le32
+     - s_first_error_ino
      - inode involved in first error.
    * - 0x1A0
-     - \_\_le64
-     - s\_first\_error\_block
+     - __le64
+     - s_first_error_block
      - Number of block involved of first error.
    * - 0x1A8
-     - \_\_u8
-     - s\_first\_error\_func[32]
+     - __u8
+     - s_first_error_func[32]
      - Name of function where the error happened.
    * - 0x1C8
-     - \_\_le32
-     - s\_first\_error\_line
+     - __le32
+     - s_first_error_line
      - Line number where error happened.
    * - 0x1CC
-     - \_\_le32
-     - s\_last\_error\_time
+     - __le32
+     - s_last_error_time
      - Time of most recent error, in seconds since the epoch.
    * - 0x1D0
-     - \_\_le32
-     - s\_last\_error\_ino
+     - __le32
+     - s_last_error_ino
      - inode involved in most recent error.
    * - 0x1D4
-     - \_\_le32
-     - s\_last\_error\_line
+     - __le32
+     - s_last_error_line
      - Line number where most recent error happened.
    * - 0x1D8
-     - \_\_le64
-     - s\_last\_error\_block
+     - __le64
+     - s_last_error_block
      - Number of block involved in most recent error.
    * - 0x1E0
-     - \_\_u8
-     - s\_last\_error\_func[32]
+     - __u8
+     - s_last_error_func[32]
      - Name of function where the most recent error happened.
    * - 0x200
-     - \_\_u8
-     - s\_mount\_opts[64]
+     - __u8
+     - s_mount_opts[64]
      - ASCIIZ string of mount options.
    * - 0x240
-     - \_\_le32
-     - s\_usr\_quota\_inum
+     - __le32
+     - s_usr_quota_inum
      - Inode number of user `quota <quota>`__ file.
    * - 0x244
-     - \_\_le32
-     - s\_grp\_quota\_inum
+     - __le32
+     - s_grp_quota_inum
      - Inode number of group `quota <quota>`__ file.
    * - 0x248
-     - \_\_le32
-     - s\_overhead\_blocks
+     - __le32
+     - s_overhead_blocks
      - Overhead blocks/clusters in fs. (Huh? This field is always zero, which
        means that the kernel calculates it dynamically.)
    * - 0x24C
-     - \_\_le32
-     - s\_backup\_bgs[2]
-     - Block groups containing superblock backups (if sparse\_super2)
+     - __le32
+     - s_backup_bgs[2]
+     - Block groups containing superblock backups (if sparse_super2)
    * - 0x254
-     - \_\_u8
-     - s\_encrypt\_algos[4]
+     - __u8
+     - s_encrypt_algos[4]
      - Encryption algorithms in use. There can be up to four algorithms in use
        at any time; valid algorithm codes are given in the super_encrypt_ table
        below.
    * - 0x258
-     - \_\_u8
-     - s\_encrypt\_pw\_salt[16]
+     - __u8
+     - s_encrypt_pw_salt[16]
      - Salt for the string2key algorithm for encryption.
    * - 0x268
-     - \_\_le32
-     - s\_lpf\_ino
+     - __le32
+     - s_lpf_ino
      - Inode number of lost+found
    * - 0x26C
-     - \_\_le32
-     - s\_prj\_quota\_inum
+     - __le32
+     - s_prj_quota_inum
      - Inode that tracks project quotas.
    * - 0x270
-     - \_\_le32
-     - s\_checksum\_seed
-     - Checksum seed used for metadata\_csum calculations. This value is
-       crc32c(~0, $orig\_fs\_uuid).
+     - __le32
+     - s_checksum_seed
+     - Checksum seed used for metadata_csum calculations. This value is
+       crc32c(~0, $orig_fs_uuid).
    * - 0x274
-     - \_\_u8
-     - s\_wtime_hi
+     - __u8
+     - s_wtime_hi
      - Upper 8 bits of the s_wtime field.
    * - 0x275
-     - \_\_u8
-     - s\_mtime_hi
+     - __u8
+     - s_mtime_hi
      - Upper 8 bits of the s_mtime field.
    * - 0x276
-     - \_\_u8
-     - s\_mkfs_time_hi
+     - __u8
+     - s_mkfs_time_hi
      - Upper 8 bits of the s_mkfs_time field.
    * - 0x277
-     - \_\_u8
-     - s\_lastcheck_hi
+     - __u8
+     - s_lastcheck_hi
      - Upper 8 bits of the s_lastcheck_hi field.
    * - 0x278
-     - \_\_u8
-     - s\_first_error_time_hi
+     - __u8
+     - s_first_error_time_hi
      - Upper 8 bits of the s_first_error_time_hi field.
    * - 0x279
-     - \_\_u8
-     - s\_last_error_time_hi
+     - __u8
+     - s_last_error_time_hi
      - Upper 8 bits of the s_last_error_time_hi field.
    * - 0x27A
-     - \_\_u8
-     - s\_pad[2]
+     - __u8
+     - s_pad[2]
      - Zero padding.
    * - 0x27C
-     - \_\_le16
-     - s\_encoding
+     - __le16
+     - s_encoding
      - Filename charset encoding.
    * - 0x27E
-     - \_\_le16
-     - s\_encoding_flags
+     - __le16
+     - s_encoding_flags
      - Filename charset encoding flags.
    * - 0x280
-     - \_\_le32
-     - s\_orphan\_file\_inum
+     - __le32
+     - s_orphan_file_inum
      - Orphan file inode number.
    * - 0x284
-     - \_\_le32
-     - s\_reserved[94]
+     - __le32
+     - s_reserved[94]
      - Padding to the end of the block.
    * - 0x3FC
-     - \_\_le32
-     - s\_checksum
+     - __le32
+     - s_checksum
      - Superblock checksum.
 
 .. _super_state:
@@ -574,44 +574,44 @@ following:
    * - Value
      - Description
    * - 0x1
-     - Directory preallocation (COMPAT\_DIR\_PREALLOC).
+     - Directory preallocation (COMPAT_DIR_PREALLOC).
    * - 0x2
      - “imagic inodes”. Not clear from the code what this does
-       (COMPAT\_IMAGIC\_INODES).
+       (COMPAT_IMAGIC_INODES).
    * - 0x4
-     - Has a journal (COMPAT\_HAS\_JOURNAL).
+     - Has a journal (COMPAT_HAS_JOURNAL).
    * - 0x8
-     - Supports extended attributes (COMPAT\_EXT\_ATTR).
+     - Supports extended attributes (COMPAT_EXT_ATTR).
    * - 0x10
      - Has reserved GDT blocks for filesystem expansion
-       (COMPAT\_RESIZE\_INODE). Requires RO\_COMPAT\_SPARSE\_SUPER.
+       (COMPAT_RESIZE_INODE). Requires RO_COMPAT_SPARSE_SUPER.
    * - 0x20
-     - Has directory indices (COMPAT\_DIR\_INDEX).
+     - Has directory indices (COMPAT_DIR_INDEX).
    * - 0x40
      - “Lazy BG”. Not in Linux kernel, seems to have been for uninitialized
-       block groups? (COMPAT\_LAZY\_BG)
+       block groups? (COMPAT_LAZY_BG)
    * - 0x80
-     - “Exclude inode”. Not used. (COMPAT\_EXCLUDE\_INODE).
+     - “Exclude inode”. Not used. (COMPAT_EXCLUDE_INODE).
    * - 0x100
      - “Exclude bitmap”. Seems to be used to indicate the presence of
        snapshot-related exclude bitmaps? Not defined in kernel or used in
-       e2fsprogs (COMPAT\_EXCLUDE\_BITMAP).
+       e2fsprogs (COMPAT_EXCLUDE_BITMAP).
    * - 0x200
-     - Sparse Super Block, v2. If this flag is set, the SB field s\_backup\_bgs
+     - Sparse Super Block, v2. If this flag is set, the SB field s_backup_bgs
        points to the two block groups that contain backup superblocks
-       (COMPAT\_SPARSE\_SUPER2).
+       (COMPAT_SPARSE_SUPER2).
    * - 0x400
      - Fast commits supported. Although fast commits blocks are
        backward incompatible, fast commit blocks are not always
        present in the journal. If fast commit blocks are present in
        the journal, JBD2 incompat feature
-       (JBD2\_FEATURE\_INCOMPAT\_FAST\_COMMIT) gets
-       set (COMPAT\_FAST\_COMMIT).
+       (JBD2_FEATURE_INCOMPAT_FAST_COMMIT) gets
+       set (COMPAT_FAST_COMMIT).
    * - 0x1000
      - Orphan file allocated. This is the special file for more efficient
        tracking of unlinked but still open inodes. When there may be any
        entries in the file, we additionally set proper rocompat feature
-       (RO\_COMPAT\_ORPHAN\_PRESENT).
+       (RO_COMPAT_ORPHAN_PRESENT).
 
 .. _super_incompat:
 
@@ -625,45 +625,45 @@ following:
    * - Value
      - Description
    * - 0x1
-     - Compression (INCOMPAT\_COMPRESSION).
+     - Compression (INCOMPAT_COMPRESSION).
    * - 0x2
-     - Directory entries record the file type. See ext4\_dir\_entry\_2 below
-       (INCOMPAT\_FILETYPE).
+     - Directory entries record the file type. See ext4_dir_entry_2 below
+       (INCOMPAT_FILETYPE).
    * - 0x4
-     - Filesystem needs recovery (INCOMPAT\_RECOVER).
+     - Filesystem needs recovery (INCOMPAT_RECOVER).
    * - 0x8
-     - Filesystem has a separate journal device (INCOMPAT\_JOURNAL\_DEV).
+     - Filesystem has a separate journal device (INCOMPAT_JOURNAL_DEV).
    * - 0x10
      - Meta block groups. See the earlier discussion of this feature
-       (INCOMPAT\_META\_BG).
+       (INCOMPAT_META_BG).
    * - 0x40
-     - Files in this filesystem use extents (INCOMPAT\_EXTENTS).
+     - Files in this filesystem use extents (INCOMPAT_EXTENTS).
    * - 0x80
-     - Enable a filesystem size of 2^64 blocks (INCOMPAT\_64BIT).
+     - Enable a filesystem size of 2^64 blocks (INCOMPAT_64BIT).
    * - 0x100
-     - Multiple mount protection (INCOMPAT\_MMP).
+     - Multiple mount protection (INCOMPAT_MMP).
    * - 0x200
      - Flexible block groups. See the earlier discussion of this feature
-       (INCOMPAT\_FLEX\_BG).
+       (INCOMPAT_FLEX_BG).
    * - 0x400
      - Inodes can be used to store large extended attribute values
-       (INCOMPAT\_EA\_INODE).
+       (INCOMPAT_EA_INODE).
    * - 0x1000
-     - Data in directory entry (INCOMPAT\_DIRDATA). (Not implemented?)
+     - Data in directory entry (INCOMPAT_DIRDATA). (Not implemented?)
    * - 0x2000
      - Metadata checksum seed is stored in the superblock. This feature enables
-       the administrator to change the UUID of a metadata\_csum filesystem
+       the administrator to change the UUID of a metadata_csum filesystem
        while the filesystem is mounted; without it, the checksum definition
-       requires all metadata blocks to be rewritten (INCOMPAT\_CSUM\_SEED).
+       requires all metadata blocks to be rewritten (INCOMPAT_CSUM_SEED).
    * - 0x4000
-     - Large directory >2GB or 3-level htree (INCOMPAT\_LARGEDIR). Prior to
+     - Large directory >2GB or 3-level htree (INCOMPAT_LARGEDIR). Prior to
        this feature, directories could not be larger than 4GiB and could not
        have an htree more than 2 levels deep. If this feature is enabled,
        directories can be larger than 4GiB and have a maximum htree depth of 3.
    * - 0x8000
-     - Data in inode (INCOMPAT\_INLINE\_DATA).
+     - Data in inode (INCOMPAT_INLINE_DATA).
    * - 0x10000
-     - Encrypted inodes are present on the filesystem. (INCOMPAT\_ENCRYPT).
+     - Encrypted inodes are present on the filesystem. (INCOMPAT_ENCRYPT).
 
 .. _super_rocompat:
 
@@ -678,54 +678,54 @@ the following:
      - Description
    * - 0x1
      - Sparse superblocks. See the earlier discussion of this feature
-       (RO\_COMPAT\_SPARSE\_SUPER).
+       (RO_COMPAT_SPARSE_SUPER).
    * - 0x2
      - This filesystem has been used to store a file greater than 2GiB
-       (RO\_COMPAT\_LARGE\_FILE).
+       (RO_COMPAT_LARGE_FILE).
    * - 0x4
-     - Not used in kernel or e2fsprogs (RO\_COMPAT\_BTREE\_DIR).
+     - Not used in kernel or e2fsprogs (RO_COMPAT_BTREE_DIR).
    * - 0x8
      - This filesystem has files whose sizes are represented in units of
        logical blocks, not 512-byte sectors. This implies a very large file
-       indeed! (RO\_COMPAT\_HUGE\_FILE)
+       indeed! (RO_COMPAT_HUGE_FILE)
    * - 0x10
      - Group descriptors have checksums. In addition to detecting corruption,
        this is useful for lazy formatting with uninitialized groups
-       (RO\_COMPAT\_GDT\_CSUM).
+       (RO_COMPAT_GDT_CSUM).
    * - 0x20
      - Indicates that the old ext3 32,000 subdirectory limit no longer applies
-       (RO\_COMPAT\_DIR\_NLINK). A directory's i\_links\_count will be set to 1
+       (RO_COMPAT_DIR_NLINK). A directory's i_links_count will be set to 1
        if it is incremented past 64,999.
    * - 0x40
      - Indicates that large inodes exist on this filesystem
-       (RO\_COMPAT\_EXTRA\_ISIZE).
+       (RO_COMPAT_EXTRA_ISIZE).
    * - 0x80
-     - This filesystem has a snapshot (RO\_COMPAT\_HAS\_SNAPSHOT).
+     - This filesystem has a snapshot (RO_COMPAT_HAS_SNAPSHOT).
    * - 0x100
-     - `Quota <Quota>`__ (RO\_COMPAT\_QUOTA).
+     - `Quota <Quota>`__ (RO_COMPAT_QUOTA).
    * - 0x200
      - This filesystem supports “bigalloc”, which means that file extents are
        tracked in units of clusters (of blocks) instead of blocks
-       (RO\_COMPAT\_BIGALLOC).
+       (RO_COMPAT_BIGALLOC).
    * - 0x400
      - This filesystem supports metadata checksumming.
-       (RO\_COMPAT\_METADATA\_CSUM; implies RO\_COMPAT\_GDT\_CSUM, though
-       GDT\_CSUM must not be set)
+       (RO_COMPAT_METADATA_CSUM; implies RO_COMPAT_GDT_CSUM, though
+       GDT_CSUM must not be set)
    * - 0x800
      - Filesystem supports replicas. This feature is neither in the kernel nor
-       e2fsprogs. (RO\_COMPAT\_REPLICA)
+       e2fsprogs. (RO_COMPAT_REPLICA)
    * - 0x1000
      - Read-only filesystem image; the kernel will not mount this image
        read-write and most tools will refuse to write to the image.
-       (RO\_COMPAT\_READONLY)
+       (RO_COMPAT_READONLY)
    * - 0x2000
-     - Filesystem tracks project quotas. (RO\_COMPAT\_PROJECT)
+     - Filesystem tracks project quotas. (RO_COMPAT_PROJECT)
    * - 0x8000
-     - Verity inodes may be present on the filesystem. (RO\_COMPAT\_VERITY)
+     - Verity inodes may be present on the filesystem. (RO_COMPAT_VERITY)
    * - 0x10000
      - Indicates orphan file may have valid orphan entries and thus we need
        to clean them up when mounting the filesystem
-       (RO\_COMPAT\_ORPHAN\_PRESENT).
+       (RO_COMPAT_ORPHAN_PRESENT).
 
 .. _super_def_hash:
 
@@ -761,36 +761,36 @@ The ``s_default_mount_opts`` field is any combination of the following:
    * - Value
      - Description
    * - 0x0001
-     - Print debugging info upon (re)mount. (EXT4\_DEFM\_DEBUG)
+     - Print debugging info upon (re)mount. (EXT4_DEFM_DEBUG)
    * - 0x0002
      - New files take the gid of the containing directory (instead of the fsgid
-       of the current process). (EXT4\_DEFM\_BSDGROUPS)
+       of the current process). (EXT4_DEFM_BSDGROUPS)
    * - 0x0004
-     - Support userspace-provided extended attributes. (EXT4\_DEFM\_XATTR\_USER)
+     - Support userspace-provided extended attributes. (EXT4_DEFM_XATTR_USER)
    * - 0x0008
-     - Support POSIX access control lists (ACLs). (EXT4\_DEFM\_ACL)
+     - Support POSIX access control lists (ACLs). (EXT4_DEFM_ACL)
    * - 0x0010
-     - Do not support 32-bit UIDs. (EXT4\_DEFM\_UID16)
+     - Do not support 32-bit UIDs. (EXT4_DEFM_UID16)
    * - 0x0020
      - All data and metadata are commited to the journal.
-       (EXT4\_DEFM\_JMODE\_DATA)
+       (EXT4_DEFM_JMODE_DATA)
    * - 0x0040
      - All data are flushed to the disk before metadata are committed to the
-       journal. (EXT4\_DEFM\_JMODE\_ORDERED)
+       journal. (EXT4_DEFM_JMODE_ORDERED)
    * - 0x0060
      - Data ordering is not preserved; data may be written after the metadata
-       has been written. (EXT4\_DEFM\_JMODE\_WBACK)
+       has been written. (EXT4_DEFM_JMODE_WBACK)
    * - 0x0100
-     - Disable write flushes. (EXT4\_DEFM\_NOBARRIER)
+     - Disable write flushes. (EXT4_DEFM_NOBARRIER)
    * - 0x0200
      - Track which blocks in a filesystem are metadata and therefore should not
        be used as data blocks. This option will be enabled by default on 3.18,
-       hopefully. (EXT4\_DEFM\_BLOCK\_VALIDITY)
+       hopefully. (EXT4_DEFM_BLOCK_VALIDITY)
    * - 0x0400
      - Enable DISCARD support, where the storage device is told about blocks
-       becoming unused. (EXT4\_DEFM\_DISCARD)
+       becoming unused. (EXT4_DEFM_DISCARD)
    * - 0x0800
-     - Disable delayed allocation. (EXT4\_DEFM\_NODELALLOC)
+     - Disable delayed allocation. (EXT4_DEFM_NODELALLOC)
 
 .. _super_flags:
 
@@ -820,12 +820,12 @@ The ``s_encrypt_algos`` list can contain any of the following:
    * - Value
      - Description
    * - 0
-     - Invalid algorithm (ENCRYPTION\_MODE\_INVALID).
+     - Invalid algorithm (ENCRYPTION_MODE_INVALID).
    * - 1
-     - 256-bit AES in XTS mode (ENCRYPTION\_MODE\_AES\_256\_XTS).
+     - 256-bit AES in XTS mode (ENCRYPTION_MODE_AES_256_XTS).
    * - 2
-     - 256-bit AES in GCM mode (ENCRYPTION\_MODE\_AES\_256\_GCM).
+     - 256-bit AES in GCM mode (ENCRYPTION_MODE_AES_256_GCM).
    * - 3
-     - 256-bit AES in CBC mode (ENCRYPTION\_MODE\_AES\_256\_CBC).
+     - 256-bit AES in CBC mode (ENCRYPTION_MODE_AES_256_CBC).
 
 Total size of the superblock is 1024 bytes.
index 2bf40ad..216b3f3 100644 (file)
@@ -45,10 +45,12 @@ Name              Alias           Usage               Preserved
 ``$r23``-``$r31`` ``$s0``-``$s8`` Static registers    Yes
 ================= =============== =================== ============
 
-Note: The register ``$r21`` is reserved in the ELF psABI, but used by the Linux
-kernel for storing the percpu base address. It normally has no ABI name, but is
-called ``$u0`` in the kernel. You may also see ``$v0`` or ``$v1`` in some old code,
-however they are deprecated aliases of ``$a0`` and ``$a1`` respectively.
+.. Note::
+    The register ``$r21`` is reserved in the ELF psABI, but used by the Linux
+    kernel for storing the percpu base address. It normally has no ABI name,
+    but is called ``$u0`` in the kernel. You may also see ``$v0`` or ``$v1``
+    in some old code,however they are deprecated aliases of ``$a0`` and ``$a1``
+    respectively.
 
 FPRs
 ----
@@ -69,8 +71,9 @@ Name              Alias              Usage               Preserved
 ``$f24``-``$f31`` ``$fs0``-``$fs7``  Static registers    Yes
 ================= ================== =================== ============
 
-Note: You may see ``$fv0`` or ``$fv1`` in some old code, however they are deprecated
-aliases of ``$fa0`` and ``$fa1`` respectively.
+.. Note::
+    You may see ``$fv0`` or ``$fv1`` in some old code, however they are
+    deprecated aliases of ``$fa0`` and ``$fa1`` respectively.
 
 VRs
 ----
index 8d88f7a..7988f41 100644 (file)
@@ -145,12 +145,16 @@ Documentation of Loongson's LS7A chipset:
 
   https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-EN.pdf (in English)
 
-Note: CPUINTC is CSR.ECFG/CSR.ESTAT and its interrupt controller described
-in Section 7.4 of "LoongArch Reference Manual, Vol 1"; LIOINTC is "Legacy I/O
-Interrupts" described in Section 11.1 of "Loongson 3A5000 Processor Reference
-Manual"; EIOINTC is "Extended I/O Interrupts" described in Section 11.2 of
-"Loongson 3A5000 Processor Reference Manual"; HTVECINTC is "HyperTransport
-Interrupts" described in Section 14.3 of "Loongson 3A5000 Processor Reference
-Manual"; PCH-PIC/PCH-MSI is "Interrupt Controller" described in Section 5 of
-"Loongson 7A1000 Bridge User Manual"; PCH-LPC is "LPC Interrupts" described in
-Section 24.3 of "Loongson 7A1000 Bridge User Manual".
+.. Note::
+    - CPUINTC is CSR.ECFG/CSR.ESTAT and its interrupt controller described
+      in Section 7.4 of "LoongArch Reference Manual, Vol 1";
+    - LIOINTC is "Legacy I/OInterrupts" described in Section 11.1 of
+      "Loongson 3A5000 Processor Reference Manual";
+    - EIOINTC is "Extended I/O Interrupts" described in Section 11.2 of
+      "Loongson 3A5000 Processor Reference Manual";
+    - HTVECINTC is "HyperTransport Interrupts" described in Section 14.3 of
+      "Loongson 3A5000 Processor Reference Manual";
+    - PCH-PIC/PCH-MSI is "Interrupt Controller" described in Section 5 of
+      "Loongson 7A1000 Bridge User Manual";
+    - PCH-LPC is "LPC Interrupts" described in Section 24.3 of
+      "Loongson 7A1000 Bridge User Manual".
index 0421656..9f41961 100644 (file)
@@ -2925,6 +2925,43 @@ plpmtud_probe_interval - INTEGER
 
        Default: 0
 
+reconf_enable - BOOLEAN
+        Enable or disable extension of Stream Reconfiguration functionality
+        specified in RFC6525. This extension provides the ability to "reset"
+        a stream, and it includes the Parameters of "Outgoing/Incoming SSN
+        Reset", "SSN/TSN Reset" and "Add Outgoing/Incoming Streams".
+
+       - 1: Enable extension.
+       - 0: Disable extension.
+
+       Default: 0
+
+intl_enable - BOOLEAN
+        Enable or disable extension of User Message Interleaving functionality
+        specified in RFC8260. This extension allows the interleaving of user
+        messages sent on different streams. With this feature enabled, I-DATA
+        chunk will replace DATA chunk to carry user messages if also supported
+        by the peer. Note that to use this feature, one needs to set this option
+        to 1 and also needs to set socket options SCTP_FRAGMENT_INTERLEAVE to 2
+        and SCTP_INTERLEAVING_SUPPORTED to 1.
+
+       - 1: Enable extension.
+       - 0: Disable extension.
+
+       Default: 0
+
+ecn_enable - BOOLEAN
+        Control use of Explicit Congestion Notification (ECN) by SCTP.
+        Like in TCP, ECN is used only when both ends of the SCTP connection
+        indicate support for it. This feature is useful in avoiding losses
+        due to congestion by allowing supporting routers to signal congestion
+        before having to drop packets.
+
+        1: Enable ecn.
+        0: Disable ecn.
+
+        Default: 1
+
 
 ``/proc/sys/net/core/*``
 ========================
index d43da70..704f31d 100644 (file)
@@ -104,7 +104,7 @@ Whenever possible, use the PHY side RGMII delay for these reasons:
 
 * PHY device drivers in PHYLIB being reusable by nature, being able to
   configure correctly a specified delay enables more designs with similar delay
-  requirements to be operate correctly
+  requirements to be operated correctly
 
 For cases where the PHY is not capable of providing this delay, but the
 Ethernet MAC driver is capable of doing so, the correct phy_interface_t value
index e31a1a9..11686ee 100644 (file)
@@ -46,10 +46,11 @@ LA64中每个寄存器为64位宽。 ``$r0`` 的内容总是固定为0,而其
 ``$r23``-``$r31`` ``$s0``-``$s8`` 静态寄存器          是
 ================= =============== =================== ==========
 
-注意:``$r21``寄存器在ELF psABI中保留未使用,但是在Linux内核用于保存每CPU
-变量基地址。该寄存器没有ABI命名,不过在内核中称为``$u0``。在一些遗留代码
-中有时可能见到``$v0``和``$v1``,它们是``$a0``和``$a1``的别名,属于已经废弃
-的用法。
+.. note::
+    注意: ``$r21`` 寄存器在ELF psABI中保留未使用,但是在Linux内核用于保
+    存每CPU变量基地址。该寄存器没有ABI命名,不过在内核中称为 ``$u0`` 。在
+    一些遗留代码中有时可能见到 ``$v0`` 和 ``$v1`` ,它们是 ``$a0`` 和
+    ``$a1`` 的别名,属于已经废弃的用法。
 
 浮点寄存器
 ----------
@@ -68,8 +69,9 @@ LA64中每个寄存器为64位宽。 ``$r0`` 的内容总是固定为0,而其
 ``$f24``-``$f31`` ``$fs0``-``$fs7``  静态寄存器          是
 ================= ================== =================== ==========
 
-注意:在一些遗留代码中有时可能见到 ``$v0`` 和 ``$v1`` ,它们是 ``$a0``
-和 ``$a1`` 的别名,属于已经废弃的用法。
+.. note::
+    注意:在一些遗留代码中有时可能见到 ``$v0`` 和 ``$v1`` ,它们是
+    ``$a0`` 和 ``$a1`` 的别名,属于已经废弃的用法。
 
 
 向量寄存器
index 2a4c3ad..fb5d23b 100644 (file)
@@ -147,9 +147,11 @@ PCH-LPC::
 
   https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-EN.pdf (英文版)
 
-注:CPUINTC即《龙芯架构参考手册卷一》第7.4节所描述的CSR.ECFG/CSR.ESTAT寄存器及其中断
-控制逻辑;LIOINTC即《龙芯3A5000处理器使用手册》第11.1节所描述的“传统I/O中断”;EIOINTC
-即《龙芯3A5000处理器使用手册》第11.2节所描述的“扩展I/O中断”;HTVECINTC即《龙芯3A5000
-处理器使用手册》第14.3节所描述的“HyperTransport中断”;PCH-PIC/PCH-MSI即《龙芯7A1000桥
-片用户手册》第5章所描述的“中断控制器”;PCH-LPC即《龙芯7A1000桥片用户手册》第24.3节所
-描述的“LPC中断”。
+.. note::
+    - CPUINTC:即《龙芯架构参考手册卷一》第7.4节所描述的CSR.ECFG/CSR.ESTAT寄存器及其
+      中断控制逻辑;
+    - LIOINTC:即《龙芯3A5000处理器使用手册》第11.1节所描述的“传统I/O中断”;
+    - EIOINTC:即《龙芯3A5000处理器使用手册》第11.2节所描述的“扩展I/O中断”;
+    - HTVECINTC:即《龙芯3A5000处理器使用手册》第14.3节所描述的“HyperTransport中断”;
+    - PCH-PIC/PCH-MSI:即《龙芯7A1000桥片用户手册》第5章所描述的“中断控制器”;
+    - PCH-LPC:即《龙芯7A1000桥片用户手册》第24.3节所描述的“LPC中断”。
index 1fc9ead..6cc8258 100644 (file)
@@ -3662,7 +3662,7 @@ BPF JIT for ARM
 M:     Shubham Bansal <illusionist.neo@gmail.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     arch/arm/net/
 
 BPF JIT for ARM64
@@ -3686,14 +3686,15 @@ BPF JIT for NFP NICs
 M:     Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
-S:     Supported
+S:     Odd Fixes
 F:     drivers/net/ethernet/netronome/nfp/bpf/
 
 BPF JIT for POWERPC (32-BIT AND 64-BIT)
 M:     Naveen N. Rao <naveen.n.rao@linux.ibm.com>
+M:     Michael Ellerman <mpe@ellerman.id.au>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
-S:     Maintained
+S:     Supported
 F:     arch/powerpc/net/
 
 BPF JIT for RISC-V (32-bit)
@@ -3719,7 +3720,7 @@ M:        Heiko Carstens <hca@linux.ibm.com>
 M:     Vasily Gorbik <gor@linux.ibm.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
-S:     Maintained
+S:     Supported
 F:     arch/s390/net/
 X:     arch/s390/net/pnet.c
 
@@ -3727,14 +3728,14 @@ BPF JIT for SPARC (32-BIT AND 64-BIT)
 M:     David S. Miller <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     arch/sparc/net/
 
 BPF JIT for X86 32-BIT
 M:     Wang YanQing <udknight@gmail.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     arch/x86/net/bpf_jit_comp32.c
 
 BPF JIT for X86 64-BIT
@@ -3757,6 +3758,19 @@ F:       include/linux/bpf_lsm.h
 F:     kernel/bpf/bpf_lsm.c
 F:     security/bpf/
 
+BPF L7 FRAMEWORK
+M:     John Fastabend <john.fastabend@gmail.com>
+M:     Jakub Sitnicki <jakub@cloudflare.com>
+L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     include/linux/skmsg.h
+F:     net/core/skmsg.c
+F:     net/core/sock_map.c
+F:     net/ipv4/tcp_bpf.c
+F:     net/ipv4/udp_bpf.c
+F:     net/unix/unix_bpf.c
+
 BPFTOOL
 M:     Quentin Monnet <quentin@isovalent.com>
 L:     bpf@vger.kernel.org
@@ -9276,6 +9290,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
 F:     Documentation/devicetree/bindings/i2c/i2c.txt
 F:     Documentation/i2c/
 F:     drivers/i2c/*
+F:     include/dt-bindings/i2c/i2c.h
 F:     include/linux/i2c-dev.h
 F:     include/linux/i2c-smbus.h
 F:     include/linux/i2c.h
@@ -9291,6 +9306,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
 F:     Documentation/devicetree/bindings/i2c/
 F:     drivers/i2c/algos/
 F:     drivers/i2c/busses/
+F:     include/dt-bindings/i2c/
 
 I2C-TAOS-EVM DRIVER
 M:     Jean Delvare <jdelvare@suse.com>
@@ -10872,7 +10888,6 @@ F:      arch/riscv/include/asm/kvm*
 F:     arch/riscv/include/uapi/asm/kvm*
 F:     arch/riscv/kvm/
 F:     tools/testing/selftests/kvm/*/riscv/
-F:     tools/testing/selftests/kvm/riscv/
 
 KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
 M:     Christian Borntraeger <borntraeger@linux.ibm.com>
@@ -11097,20 +11112,6 @@ S:     Maintained
 F:     include/net/l3mdev.h
 F:     net/l3mdev
 
-L7 BPF FRAMEWORK
-M:     John Fastabend <john.fastabend@gmail.com>
-M:     Daniel Borkmann <daniel@iogearbox.net>
-M:     Jakub Sitnicki <jakub@cloudflare.com>
-L:     netdev@vger.kernel.org
-L:     bpf@vger.kernel.org
-S:     Maintained
-F:     include/linux/skmsg.h
-F:     net/core/skmsg.c
-F:     net/core/sock_map.c
-F:     net/ipv4/tcp_bpf.c
-F:     net/ipv4/udp_bpf.c
-F:     net/unix/unix_bpf.c
-
 LANDLOCK SECURITY MODULE
 M:     Mickaël Salaün <mic@digikod.net>
 L:     linux-security-module@vger.kernel.org
@@ -13801,6 +13802,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 F:     Documentation/devicetree/bindings/net/
 F:     drivers/connector/
 F:     drivers/net/
+F:     include/dt-bindings/net/
 F:     include/linux/etherdevice.h
 F:     include/linux/fcdevice.h
 F:     include/linux/fddidevice.h
@@ -13952,7 +13954,6 @@ F:      net/ipv6/tcp*.c
 NETWORKING [TLS]
 M:     Boris Pismenny <borisp@nvidia.com>
 M:     John Fastabend <john.fastabend@gmail.com>
-M:     Daniel Borkmann <daniel@iogearbox.net>
 M:     Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -14869,6 +14870,7 @@ F:      include/dt-bindings/
 
 OPENCOMPUTE PTP CLOCK DRIVER
 M:     Jonathan Lemon <jonathan.lemon@gmail.com>
+M:     Vadim Fedorenko <vadfed@fb.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/ptp/ptp_ocp.c
@@ -19305,7 +19307,7 @@ R:      Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 R:     Mika Westerberg <mika.westerberg@linux.intel.com>
 R:     Jan Dabros <jsd@semihalf.com>
 L:     linux-i2c@vger.kernel.org
-S:     Maintained
+S:     Supported
 F:     drivers/i2c/busses/i2c-designware-*
 
 SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
index 1a6678d..513c1fb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 19
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Superb Owl
 
 # *DOCUMENTATION*
index 443e8b0..14af1fd 100644 (file)
                        port@0 {
                                reg = <0>;
                                label = "lan1";
+                               phy-mode = "internal";
                        };
 
                        port@1 {
                                reg = <1>;
                                label = "lan2";
+                               phy-mode = "internal";
                        };
 
                        port@2 {
                                reg = <2>;
                                label = "lan3";
+                               phy-mode = "internal";
                        };
 
                        port@3 {
                                reg = <3>;
                                label = "lan4";
+                               phy-mode = "internal";
                        };
 
                        port@4 {
                                reg = <4>;
                                label = "lan5";
+                               phy-mode = "internal";
                        };
 
                        port@5 {
index 47a1e25..de32152 100644 (file)
@@ -362,11 +362,6 @@ struct kvm_vcpu_arch {
        struct arch_timer_cpu timer_cpu;
        struct kvm_pmu pmu;
 
-       /*
-        * Anything that is not used directly from assembly code goes
-        * here.
-        */
-
        /*
         * Guest registers we preserve during guest debugging.
         *
index 3c8af03..0e80db4 100644 (file)
@@ -113,6 +113,9 @@ static __always_inline bool has_vhe(void)
        /*
         * Code only run in VHE/NVHE hyp context can assume VHE is present or
         * absent. Otherwise fall back to caps.
+        * This allows the compiler to discard VHE-specific code from the
+        * nVHE object, reducing the number of external symbol references
+        * needed to link.
         */
        if (is_vhe_hyp_code())
                return true;
index 42ea2bd..8d88433 100644 (file)
@@ -1974,15 +1974,7 @@ static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)
 #ifdef CONFIG_KVM
 static bool is_kvm_protected_mode(const struct arm64_cpu_capabilities *entry, int __unused)
 {
-       if (kvm_get_mode() != KVM_MODE_PROTECTED)
-               return false;
-
-       if (is_kernel_in_hyp_mode()) {
-               pr_warn("Protected KVM not available with VHE\n");
-               return false;
-       }
-
-       return true;
+       return kvm_get_mode() == KVM_MODE_PROTECTED;
 }
 #endif /* CONFIG_KVM */
 
@@ -3109,7 +3101,6 @@ void cpu_set_feature(unsigned int num)
        WARN_ON(num >= MAX_CPU_FEATURES);
        elf_hwcap |= BIT(num);
 }
-EXPORT_SYMBOL_GPL(cpu_set_feature);
 
 bool cpu_have_feature(unsigned int num)
 {
index d42a205..bd5df50 100644 (file)
@@ -102,7 +102,6 @@ SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
  * x19-x29 per the AAPCS, and we created frame records upon entry, so we need
  * to restore x0-x8, x29, and x30.
  */
-ftrace_common_return:
        /* Restore function arguments */
        ldp     x0, x1, [sp]
        ldp     x2, x3, [sp, #S_X2]
index f447c4a..ea5dc7c 100644 (file)
@@ -78,47 +78,76 @@ static struct plt_entry *get_ftrace_plt(struct module *mod, unsigned long addr)
 }
 
 /*
- * Turn on the call to ftrace_caller() in instrumented function
+ * Find the address the callsite must branch to in order to reach '*addr'.
+ *
+ * Due to the limited range of 'BL' instructions, modules may be placed too far
+ * away to branch directly and must use a PLT.
+ *
+ * Returns true when '*addr' contains a reachable target address, or has been
+ * modified to contain a PLT address. Returns false otherwise.
  */
-int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+static bool ftrace_find_callable_addr(struct dyn_ftrace *rec,
+                                     struct module *mod,
+                                     unsigned long *addr)
 {
        unsigned long pc = rec->ip;
-       u32 old, new;
-       long offset = (long)pc - (long)addr;
+       long offset = (long)*addr - (long)pc;
+       struct plt_entry *plt;
 
-       if (offset < -SZ_128M || offset >= SZ_128M) {
-               struct module *mod;
-               struct plt_entry *plt;
+       /*
+        * When the target is within range of the 'BL' instruction, use 'addr'
+        * as-is and branch to that directly.
+        */
+       if (offset >= -SZ_128M && offset < SZ_128M)
+               return true;
 
-               if (!IS_ENABLED(CONFIG_ARM64_MODULE_PLTS))
-                       return -EINVAL;
+       /*
+        * When the target is outside of the range of a 'BL' instruction, we
+        * must use a PLT to reach it. We can only place PLTs for modules, and
+        * only when module PLT support is built-in.
+        */
+       if (!IS_ENABLED(CONFIG_ARM64_MODULE_PLTS))
+               return false;
 
-               /*
-                * On kernels that support module PLTs, the offset between the
-                * branch instruction and its target may legally exceed the
-                * range of an ordinary relative 'bl' opcode. In this case, we
-                * need to branch via a trampoline in the module.
-                *
-                * NOTE: __module_text_address() must be called with preemption
-                * disabled, but we can rely on ftrace_lock to ensure that 'mod'
-                * retains its validity throughout the remainder of this code.
-                */
+       /*
+        * 'mod' is only set at module load time, but if we end up
+        * dealing with an out-of-range condition, we can assume it
+        * is due to a module being loaded far away from the kernel.
+        *
+        * NOTE: __module_text_address() must be called with preemption
+        * disabled, but we can rely on ftrace_lock to ensure that 'mod'
+        * retains its validity throughout the remainder of this code.
+        */
+       if (!mod) {
                preempt_disable();
                mod = __module_text_address(pc);
                preempt_enable();
+       }
 
-               if (WARN_ON(!mod))
-                       return -EINVAL;
+       if (WARN_ON(!mod))
+               return false;
 
-               plt = get_ftrace_plt(mod, addr);
-               if (!plt) {
-                       pr_err("ftrace: no module PLT for %ps\n", (void *)addr);
-                       return -EINVAL;
-               }
-
-               addr = (unsigned long)plt;
+       plt = get_ftrace_plt(mod, *addr);
+       if (!plt) {
+               pr_err("ftrace: no module PLT for %ps\n", (void *)*addr);
+               return false;
        }
 
+       *addr = (unsigned long)plt;
+       return true;
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+       unsigned long pc = rec->ip;
+       u32 old, new;
+
+       if (!ftrace_find_callable_addr(rec, NULL, &addr))
+               return -EINVAL;
+
        old = aarch64_insn_gen_nop();
        new = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK);
 
@@ -132,6 +161,11 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
        unsigned long pc = rec->ip;
        u32 old, new;
 
+       if (!ftrace_find_callable_addr(rec, NULL, &old_addr))
+               return -EINVAL;
+       if (!ftrace_find_callable_addr(rec, NULL, &addr))
+               return -EINVAL;
+
        old = aarch64_insn_gen_branch_imm(pc, old_addr,
                                          AARCH64_INSN_BRANCH_LINK);
        new = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK);
@@ -181,54 +215,15 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
                    unsigned long addr)
 {
        unsigned long pc = rec->ip;
-       bool validate = true;
        u32 old = 0, new;
-       long offset = (long)pc - (long)addr;
 
-       if (offset < -SZ_128M || offset >= SZ_128M) {
-               u32 replaced;
-
-               if (!IS_ENABLED(CONFIG_ARM64_MODULE_PLTS))
-                       return -EINVAL;
-
-               /*
-                * 'mod' is only set at module load time, but if we end up
-                * dealing with an out-of-range condition, we can assume it
-                * is due to a module being loaded far away from the kernel.
-                */
-               if (!mod) {
-                       preempt_disable();
-                       mod = __module_text_address(pc);
-                       preempt_enable();
-
-                       if (WARN_ON(!mod))
-                               return -EINVAL;
-               }
-
-               /*
-                * The instruction we are about to patch may be a branch and
-                * link instruction that was redirected via a PLT entry. In
-                * this case, the normal validation will fail, but we can at
-                * least check that we are dealing with a branch and link
-                * instruction that points into the right module.
-                */
-               if (aarch64_insn_read((void *)pc, &replaced))
-                       return -EFAULT;
-
-               if (!aarch64_insn_is_bl(replaced) ||
-                   !within_module(pc + aarch64_get_branch_offset(replaced),
-                                  mod))
-                       return -EINVAL;
-
-               validate = false;
-       } else {
-               old = aarch64_insn_gen_branch_imm(pc, addr,
-                                                 AARCH64_INSN_BRANCH_LINK);
-       }
+       if (!ftrace_find_callable_addr(rec, mod, &addr))
+               return -EINVAL;
 
+       old = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK);
        new = aarch64_insn_gen_nop();
 
-       return ftrace_modify_code(pc, old, new, validate);
+       return ftrace_modify_code(pc, old, new, true);
 }
 
 void arch_ftrace_update_code(int command)
index cf3a759..fea3223 100644 (file)
@@ -303,14 +303,13 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
        early_fixmap_init();
        early_ioremap_init();
 
+       setup_machine_fdt(__fdt_pointer);
+
        /*
         * Initialise the static keys early as they may be enabled by the
-        * cpufeature code, early parameters, and DT setup.
+        * cpufeature code and early parameters.
         */
        jump_label_init();
-
-       setup_machine_fdt(__fdt_pointer);
-
        parse_early_param();
 
        /*
index 4e39ace..3b8d062 100644 (file)
@@ -1230,6 +1230,9 @@ bool kvm_arch_timer_get_input_level(int vintid)
        struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
        struct arch_timer_context *timer;
 
+       if (WARN(!vcpu, "No vcpu context!\n"))
+               return false;
+
        if (vintid == vcpu_vtimer(vcpu)->irq.irq)
                timer = vcpu_vtimer(vcpu);
        else if (vintid == vcpu_ptimer(vcpu)->irq.irq)
index 400bb0f..a018814 100644 (file)
@@ -150,8 +150,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        if (ret)
                goto out_free_stage2_pgd;
 
-       if (!zalloc_cpumask_var(&kvm->arch.supported_cpus, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&kvm->arch.supported_cpus, GFP_KERNEL)) {
+               ret = -ENOMEM;
                goto out_free_stage2_pgd;
+       }
        cpumask_copy(kvm->arch.supported_cpus, cpu_possible_mask);
 
        kvm_vgic_early_init(kvm);
@@ -2271,7 +2273,11 @@ static int __init early_kvm_mode_cfg(char *arg)
                return -EINVAL;
 
        if (strcmp(arg, "protected") == 0) {
-               kvm_mode = KVM_MODE_PROTECTED;
+               if (!is_kernel_in_hyp_mode())
+                       kvm_mode = KVM_MODE_PROTECTED;
+               else
+                       pr_warn_once("Protected KVM not available with VHE\n");
+
                return 0;
        }
 
index 3d251a4..6012b08 100644 (file)
@@ -80,6 +80,7 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
        vcpu->arch.flags &= ~KVM_ARM64_FP_ENABLED;
        vcpu->arch.flags |= KVM_ARM64_FP_HOST;
 
+       vcpu->arch.flags &= ~KVM_ARM64_HOST_SVE_ENABLED;
        if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
                vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
 
@@ -93,6 +94,7 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
         * operations. Do this for ZA as well for now for simplicity.
         */
        if (system_supports_sme()) {
+               vcpu->arch.flags &= ~KVM_ARM64_HOST_SME_ENABLED;
                if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
                        vcpu->arch.flags |= KVM_ARM64_HOST_SME_ENABLED;
 
index 78edf07..1e78acf 100644 (file)
@@ -314,15 +314,11 @@ static int host_stage2_adjust_range(u64 addr, struct kvm_mem_range *range)
 int host_stage2_idmap_locked(phys_addr_t addr, u64 size,
                             enum kvm_pgtable_prot prot)
 {
-       hyp_assert_lock_held(&host_kvm.lock);
-
        return host_stage2_try(__host_stage2_idmap, addr, addr + size, prot);
 }
 
 int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id)
 {
-       hyp_assert_lock_held(&host_kvm.lock);
-
        return host_stage2_try(kvm_pgtable_stage2_set_owner, &host_kvm.pgt,
                               addr, size, &host_s2_pool, owner_id);
 }
index b6d86e4..35a4331 100644 (file)
@@ -243,15 +243,9 @@ u64 pvm_read_id_reg(const struct kvm_vcpu *vcpu, u32 id)
        case SYS_ID_AA64MMFR2_EL1:
                return get_pvm_id_aa64mmfr2(vcpu);
        default:
-               /*
-                * Should never happen because all cases are covered in
-                * pvm_sys_reg_descs[].
-                */
-               WARN_ON(1);
-               break;
+               /* Unhandled ID register, RAZ */
+               return 0;
        }
-
-       return 0;
 }
 
 static u64 read_id_reg(const struct kvm_vcpu *vcpu,
@@ -332,6 +326,16 @@ static bool pvm_gic_read_sre(struct kvm_vcpu *vcpu,
 /* Mark the specified system register as an AArch64 feature id register. */
 #define AARCH64(REG) { SYS_DESC(REG), .access = pvm_access_id_aarch64 }
 
+/*
+ * sys_reg_desc initialiser for architecturally unallocated cpufeature ID
+ * register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2
+ * (1 <= crm < 8, 0 <= Op2 < 8).
+ */
+#define ID_UNALLOCATED(crm, op2) {                     \
+       Op0(3), Op1(0), CRn(0), CRm(crm), Op2(op2),     \
+       .access = pvm_access_id_aarch64,                \
+}
+
 /* Mark the specified system register as Read-As-Zero/Write-Ignored */
 #define RAZ_WI(REG) { SYS_DESC(REG), .access = pvm_access_raz_wi }
 
@@ -375,24 +379,46 @@ static const struct sys_reg_desc pvm_sys_reg_descs[] = {
        AARCH32(SYS_MVFR0_EL1),
        AARCH32(SYS_MVFR1_EL1),
        AARCH32(SYS_MVFR2_EL1),
+       ID_UNALLOCATED(3,3),
        AARCH32(SYS_ID_PFR2_EL1),
        AARCH32(SYS_ID_DFR1_EL1),
        AARCH32(SYS_ID_MMFR5_EL1),
+       ID_UNALLOCATED(3,7),
 
        /* AArch64 ID registers */
        /* CRm=4 */
        AARCH64(SYS_ID_AA64PFR0_EL1),
        AARCH64(SYS_ID_AA64PFR1_EL1),
+       ID_UNALLOCATED(4,2),
+       ID_UNALLOCATED(4,3),
        AARCH64(SYS_ID_AA64ZFR0_EL1),
+       ID_UNALLOCATED(4,5),
+       ID_UNALLOCATED(4,6),
+       ID_UNALLOCATED(4,7),
        AARCH64(SYS_ID_AA64DFR0_EL1),
        AARCH64(SYS_ID_AA64DFR1_EL1),
+       ID_UNALLOCATED(5,2),
+       ID_UNALLOCATED(5,3),
        AARCH64(SYS_ID_AA64AFR0_EL1),
        AARCH64(SYS_ID_AA64AFR1_EL1),
+       ID_UNALLOCATED(5,6),
+       ID_UNALLOCATED(5,7),
        AARCH64(SYS_ID_AA64ISAR0_EL1),
        AARCH64(SYS_ID_AA64ISAR1_EL1),
+       AARCH64(SYS_ID_AA64ISAR2_EL1),
+       ID_UNALLOCATED(6,3),
+       ID_UNALLOCATED(6,4),
+       ID_UNALLOCATED(6,5),
+       ID_UNALLOCATED(6,6),
+       ID_UNALLOCATED(6,7),
        AARCH64(SYS_ID_AA64MMFR0_EL1),
        AARCH64(SYS_ID_AA64MMFR1_EL1),
        AARCH64(SYS_ID_AA64MMFR2_EL1),
+       ID_UNALLOCATED(7,3),
+       ID_UNALLOCATED(7,4),
+       ID_UNALLOCATED(7,5),
+       ID_UNALLOCATED(7,6),
+       ID_UNALLOCATED(7,7),
 
        /* Scalable Vector Registers are restricted. */
 
index 77a67e9..e070cda 100644 (file)
@@ -429,11 +429,11 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
                vgic_mmio_read_pending, vgic_mmio_write_spending,
-               NULL, vgic_uaccess_write_spending, 1,
+               vgic_uaccess_read_pending, vgic_uaccess_write_spending, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
                vgic_mmio_read_pending, vgic_mmio_write_cpending,
-               NULL, vgic_uaccess_write_cpending, 1,
+               vgic_uaccess_read_pending, vgic_uaccess_write_cpending, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
                vgic_mmio_read_active, vgic_mmio_write_sactive,
index f7aa7bc..f15e29c 100644 (file)
@@ -353,42 +353,6 @@ static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
-                                                 gpa_t addr, unsigned int len)
-{
-       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
-       u32 value = 0;
-       int i;
-
-       /*
-        * pending state of interrupt is latched in pending_latch variable.
-        * Userspace will save and restore pending state and line_level
-        * separately.
-        * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.rst
-        * for handling of ISPENDR and ICPENDR.
-        */
-       for (i = 0; i < len * 8; i++) {
-               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-               bool state = irq->pending_latch;
-
-               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
-                       int err;
-
-                       err = irq_get_irqchip_state(irq->host_irq,
-                                                   IRQCHIP_STATE_PENDING,
-                                                   &state);
-                       WARN_ON(err);
-               }
-
-               if (state)
-                       value |= (1U << i);
-
-               vgic_put_irq(vcpu->kvm, irq);
-       }
-
-       return value;
-}
-
 static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
                                         gpa_t addr, unsigned int len,
                                         unsigned long val)
@@ -666,7 +630,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
                vgic_mmio_read_pending, vgic_mmio_write_spending,
-               vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1,
+               vgic_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
                vgic_mmio_read_pending, vgic_mmio_write_cpending,
@@ -750,7 +714,7 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0,
                vgic_mmio_read_pending, vgic_mmio_write_spending,
-               vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4,
+               vgic_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICPENDR0,
                vgic_mmio_read_pending, vgic_mmio_write_cpending,
index 49837d3..997d0fc 100644 (file)
@@ -226,8 +226,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
-                                    gpa_t addr, unsigned int len)
+static unsigned long __read_pending(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len,
+                                   bool is_user)
 {
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
        u32 value = 0;
@@ -239,6 +240,15 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                unsigned long flags;
                bool val;
 
+               /*
+                * When used from userspace with a GICv3 model:
+                *
+                * Pending state of interrupt is latched in pending_latch
+                * variable.  Userspace will save and restore pending state
+                * and line_level separately.
+                * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.rst
+                * for handling of ISPENDR and ICPENDR.
+                */
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
                        int err;
@@ -248,10 +258,20 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                                                    IRQCHIP_STATE_PENDING,
                                                    &val);
                        WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
-               } else if (vgic_irq_is_mapped_level(irq)) {
+               } else if (!is_user && vgic_irq_is_mapped_level(irq)) {
                        val = vgic_get_phys_line_level(irq);
                } else {
-                       val = irq_is_pending(irq);
+                       switch (vcpu->kvm->arch.vgic.vgic_model) {
+                       case KVM_DEV_TYPE_ARM_VGIC_V3:
+                               if (is_user) {
+                                       val = irq->pending_latch;
+                                       break;
+                               }
+                               fallthrough;
+                       default:
+                               val = irq_is_pending(irq);
+                               break;
+                       }
                }
 
                value |= ((u32)val << i);
@@ -263,6 +283,18 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
        return value;
 }
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+                                    gpa_t addr, unsigned int len)
+{
+       return __read_pending(vcpu, addr, len, false);
+}
+
+unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu,
+                                       gpa_t addr, unsigned int len)
+{
+       return __read_pending(vcpu, addr, len, true);
+}
+
 static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
 {
        return (vgic_irq_is_sgi(irq->intid) &&
index 3fa696f..6082d4b 100644 (file)
@@ -149,6 +149,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
 unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                                     gpa_t addr, unsigned int len);
 
+unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu,
+                                       gpa_t addr, unsigned int len);
+
 void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
                              gpa_t addr, unsigned int len,
                              unsigned long val);
index 8d5f050..d78ae63 100644 (file)
@@ -66,7 +66,7 @@ static void flush_context(void)
         * the next context-switch, we broadcast TLB flush + I-cache
         * invalidation over the inner shareable domain on rollover.
         */
-        kvm_call_hyp(__kvm_flush_vm_context);
+       kvm_call_hyp(__kvm_flush_vm_context);
 }
 
 static bool check_update_reserved_vmid(u64 vmid, u64 newvmid)
index 0ea6cc2..21c9079 100644 (file)
@@ -218,8 +218,6 @@ SYM_FUNC_ALIAS(__dma_flush_area, __pi___dma_flush_area)
  */
 SYM_FUNC_START(__pi___dma_map_area)
        add     x1, x0, x1
-       cmp     w2, #DMA_FROM_DEVICE
-       b.eq    __pi_dcache_inval_poc
        b       __pi_dcache_clean_poc
 SYM_FUNC_END(__pi___dma_map_area)
 SYM_FUNC_ALIAS(__dma_map_area, __pi___dma_map_area)
index 9d50815..78311a6 100644 (file)
@@ -101,6 +101,7 @@ SECTIONS
 
        STABS_DEBUG
        DWARF_DEBUG
+       ELF_DETAILS
 
        .gptab.sdata : {
                *(.gptab.data)
index b0a034b..42e6966 100644 (file)
 
                clocks = <&cgu X1000_CLK_RTCLK>,
                         <&cgu X1000_CLK_EXCLK>,
-                        <&cgu X1000_CLK_PCLK>;
-               clock-names = "rtc", "ext", "pclk";
+                        <&cgu X1000_CLK_PCLK>,
+                        <&cgu X1000_CLK_TCU>;
+               clock-names = "rtc", "ext", "pclk", "tcu";
 
                interrupt-controller;
                #interrupt-cells = <1>;
index dbf21af..65a5da7 100644 (file)
 
                clocks = <&cgu X1830_CLK_RTCLK>,
                         <&cgu X1830_CLK_EXCLK>,
-                        <&cgu X1830_CLK_PCLK>;
-               clock-names = "rtc", "ext", "pclk";
+                        <&cgu X1830_CLK_PCLK>,
+                        <&cgu X1830_CLK_TCU>;
+               clock-names = "rtc", "ext", "pclk", "tcu";
 
                interrupt-controller;
                #interrupt-cells = <1>;
index a89aaad..930c450 100644 (file)
@@ -44,6 +44,7 @@ static __init unsigned int ranchu_measure_hpt_freq(void)
                      __func__);
 
        rtc_base = of_iomap(np, 0);
+       of_node_put(np);
        if (!rtc_base)
                panic("%s(): Failed to ioremap Goldfish RTC base!", __func__);
 
index 5204fc6..1187729 100644 (file)
@@ -208,6 +208,12 @@ void __init ltq_soc_init(void)
                        of_address_to_resource(np_sysgpe, 0, &res_sys[2]))
                panic("Failed to get core resources");
 
+       of_node_put(np_status);
+       of_node_put(np_ebu);
+       of_node_put(np_sys1);
+       of_node_put(np_syseth);
+       of_node_put(np_sysgpe);
+
        if ((request_mem_region(res_status.start, resource_size(&res_status),
                                res_status.name) < 0) ||
                (request_mem_region(res_ebu.start, resource_size(&res_ebu),
index b732495..20622bf 100644 (file)
@@ -408,6 +408,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
                if (!ltq_eiu_membase)
                        panic("Failed to remap eiu memory");
        }
+       of_node_put(eiu_node);
 
        return 0;
 }
index 084f6ca..d444a1b 100644 (file)
@@ -441,6 +441,10 @@ void __init ltq_soc_init(void)
                        of_address_to_resource(np_ebu, 0, &res_ebu))
                panic("Failed to get core resources");
 
+       of_node_put(np_pmu);
+       of_node_put(np_cgu);
+       of_node_put(np_ebu);
+
        if (!request_mem_region(res_pmu.start, resource_size(&res_pmu),
                                res_pmu.name) ||
                !request_mem_region(res_cgu.start, resource_size(&res_cgu),
index bbf1e38..2cb708c 100644 (file)
@@ -214,6 +214,8 @@ static void update_gic_frequency_dt(void)
 
        if (of_update_property(node, &gic_frequency_prop) < 0)
                pr_err("error updating gic frequency property\n");
+
+       of_node_put(node);
 }
 
 #endif
index 1299156..d9c8c4e 100644 (file)
@@ -98,13 +98,18 @@ static int __init pic32_of_prepare_platform_data(struct of_dev_auxdata *lookup)
                np = of_find_compatible_node(NULL, NULL, lookup->compatible);
                if (np) {
                        lookup->name = (char *)np->name;
-                       if (lookup->phys_addr)
+                       if (lookup->phys_addr) {
+                               of_node_put(np);
                                continue;
+                       }
                        if (!of_address_to_resource(np, 0, &res))
                                lookup->phys_addr = res.start;
+                       of_node_put(np);
                }
        }
 
+       of_node_put(root);
+
        return 0;
 }
 
index 7174e9a..777b515 100644 (file)
@@ -32,6 +32,9 @@ static unsigned int pic32_xlate_core_timer_irq(void)
                goto default_map;
 
        irq = irq_of_parse_and_map(node, 0);
+
+       of_node_put(node);
+
        if (!irq)
                goto default_map;
 
index 587c7b9..ea8072a 100644 (file)
@@ -40,6 +40,8 @@ __iomem void *plat_of_remap_node(const char *node)
        if (of_address_to_resource(np, 0, &res))
                panic("Failed to get resource for %s", node);
 
+       of_node_put(np);
+
        if (!request_mem_region(res.start,
                                resource_size(&res),
                                res.name))
index 7b7f25b..9240bcd 100644 (file)
@@ -640,8 +640,6 @@ static int icu_get_irq(unsigned int irq)
 
        printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
 
-       atomic_inc(&irq_err_count);
-
        return -1;
 }
 
index c22f581..32ffef9 100644 (file)
@@ -364,8 +364,13 @@ config RISCV_ISA_SVPBMT
        select RISCV_ALTERNATIVE
        default y
        help
-          Adds support to dynamically detect the presence of the SVPBMT extension
-          (Supervisor-mode: page-based memory types) and enable its usage.
+          Adds support to dynamically detect the presence of the SVPBMT
+          ISA-extension (Supervisor-mode: page-based memory types) and
+          enable its usage.
+
+          The memory type for a page contains a combination of attributes
+          that indicate the cacheability, idempotency, and ordering
+          properties for access to that page.
 
           The SVPBMT extension is only available on 64Bit cpus.
 
index ebfcd5c..457ac72 100644 (file)
@@ -35,6 +35,7 @@ config ERRATA_SIFIVE_CIP_1200
 
 config ERRATA_THEAD
        bool "T-HEAD errata"
+       depends on !XIP_KERNEL
        select RISCV_ALTERNATIVE
        help
          All T-HEAD errata Kconfig depend on this Kconfig. Disabling
index 8c32591..3095d08 100644 (file)
                        riscv,ndev = <186>;
                };
 
+               pdma: dma-controller@3000000 {
+                       compatible = "sifive,fu540-c000-pdma", "sifive,pdma0";
+                       reg = <0x0 0x3000000 0x0 0x8000>;
+                       interrupt-parent = <&plic>;
+                       interrupts = <5 6>, <7 8>, <9 10>, <11 12>;
+                       dma-channels = <4>;
+                       #dma-cells = <1>;
+               };
+
                clkcfg: clkcfg@20002000 {
                        compatible = "microchip,mpfs-clkcfg";
                        reg = <0x0 0x20002000 0x0 0x1000>, <0x0 0x3E001000 0x0 0x1000>;
index a6f62a6..12b05ce 100644 (file)
@@ -293,7 +293,6 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
                                                  unsigned int stage)
 {
        u32 cpu_req_feature = cpufeature_probe(stage);
-       u32 cpu_apply_feature = 0;
        struct alt_entry *alt;
        u32 tmp;
 
@@ -307,10 +306,8 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
                }
 
                tmp = (1U << alt->errata_id);
-               if (cpu_req_feature & tmp) {
+               if (cpu_req_feature & tmp)
                        patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
-                       cpu_apply_feature |= tmp;
-               }
        }
 }
 #endif
index 9f764df..6cd9399 100644 (file)
@@ -97,7 +97,7 @@ void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu)
                 * We ran out of VMIDs so we increment vmid_version and
                 * start assigning VMIDs from 1.
                 *
-                * This also means existing VMIDs assignement to all Guest
+                * This also means existing VMIDs assignment to all Guest
                 * instances is invalid and we have force VMID re-assignement
                 * for all Guest instances. The Guest instances that were not
                 * running will automatically pick-up new VMIDs because will
index 03deb4d..928dcf7 100644 (file)
@@ -124,6 +124,51 @@ static u64 get_cc_mask(void)
        return BIT_ULL(gpa_width - 1);
 }
 
+/*
+ * The TDX module spec states that #VE may be injected for a limited set of
+ * reasons:
+ *
+ *  - Emulation of the architectural #VE injection on EPT violation;
+ *
+ *  - As a result of guest TD execution of a disallowed instruction,
+ *    a disallowed MSR access, or CPUID virtualization;
+ *
+ *  - A notification to the guest TD about anomalous behavior;
+ *
+ * The last one is opt-in and is not used by the kernel.
+ *
+ * The Intel Software Developer's Manual describes cases when instruction
+ * length field can be used in section "Information for VM Exits Due to
+ * Instruction Execution".
+ *
+ * For TDX, it ultimately means GET_VEINFO provides reliable instruction length
+ * information if #VE occurred due to instruction execution, but not for EPT
+ * violations.
+ */
+static int ve_instr_len(struct ve_info *ve)
+{
+       switch (ve->exit_reason) {
+       case EXIT_REASON_HLT:
+       case EXIT_REASON_MSR_READ:
+       case EXIT_REASON_MSR_WRITE:
+       case EXIT_REASON_CPUID:
+       case EXIT_REASON_IO_INSTRUCTION:
+               /* It is safe to use ve->instr_len for #VE due instructions */
+               return ve->instr_len;
+       case EXIT_REASON_EPT_VIOLATION:
+               /*
+                * For EPT violations, ve->insn_len is not defined. For those,
+                * the kernel must decode instructions manually and should not
+                * be using this function.
+                */
+               WARN_ONCE(1, "ve->instr_len is not defined for EPT violations");
+               return 0;
+       default:
+               WARN_ONCE(1, "Unexpected #VE-type: %lld\n", ve->exit_reason);
+               return ve->instr_len;
+       }
+}
+
 static u64 __cpuidle __halt(const bool irq_disabled, const bool do_sti)
 {
        struct tdx_hypercall_args args = {
@@ -147,7 +192,7 @@ static u64 __cpuidle __halt(const bool irq_disabled, const bool do_sti)
        return __tdx_hypercall(&args, do_sti ? TDX_HCALL_ISSUE_STI : 0);
 }
 
-static bool handle_halt(void)
+static int handle_halt(struct ve_info *ve)
 {
        /*
         * Since non safe halt is mainly used in CPU offlining
@@ -158,9 +203,9 @@ static bool handle_halt(void)
        const bool do_sti = false;
 
        if (__halt(irq_disabled, do_sti))
-               return false;
+               return -EIO;
 
-       return true;
+       return ve_instr_len(ve);
 }
 
 void __cpuidle tdx_safe_halt(void)
@@ -180,7 +225,7 @@ void __cpuidle tdx_safe_halt(void)
                WARN_ONCE(1, "HLT instruction emulation failed\n");
 }
 
-static bool read_msr(struct pt_regs *regs)
+static int read_msr(struct pt_regs *regs, struct ve_info *ve)
 {
        struct tdx_hypercall_args args = {
                .r10 = TDX_HYPERCALL_STANDARD,
@@ -194,14 +239,14 @@ static bool read_msr(struct pt_regs *regs)
         * (GHCI), section titled "TDG.VP.VMCALL<Instruction.RDMSR>".
         */
        if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT))
-               return false;
+               return -EIO;
 
        regs->ax = lower_32_bits(args.r11);
        regs->dx = upper_32_bits(args.r11);
-       return true;
+       return ve_instr_len(ve);
 }
 
-static bool write_msr(struct pt_regs *regs)
+static int write_msr(struct pt_regs *regs, struct ve_info *ve)
 {
        struct tdx_hypercall_args args = {
                .r10 = TDX_HYPERCALL_STANDARD,
@@ -215,10 +260,13 @@ static bool write_msr(struct pt_regs *regs)
         * can be found in TDX Guest-Host-Communication Interface
         * (GHCI) section titled "TDG.VP.VMCALL<Instruction.WRMSR>".
         */
-       return !__tdx_hypercall(&args, 0);
+       if (__tdx_hypercall(&args, 0))
+               return -EIO;
+
+       return ve_instr_len(ve);
 }
 
-static bool handle_cpuid(struct pt_regs *regs)
+static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve)
 {
        struct tdx_hypercall_args args = {
                .r10 = TDX_HYPERCALL_STANDARD,
@@ -236,7 +284,7 @@ static bool handle_cpuid(struct pt_regs *regs)
         */
        if (regs->ax < 0x40000000 || regs->ax > 0x4FFFFFFF) {
                regs->ax = regs->bx = regs->cx = regs->dx = 0;
-               return true;
+               return ve_instr_len(ve);
        }
 
        /*
@@ -245,7 +293,7 @@ static bool handle_cpuid(struct pt_regs *regs)
         * (GHCI), section titled "VP.VMCALL<Instruction.CPUID>".
         */
        if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT))
-               return false;
+               return -EIO;
 
        /*
         * As per TDX GHCI CPUID ABI, r12-r15 registers contain contents of
@@ -257,7 +305,7 @@ static bool handle_cpuid(struct pt_regs *regs)
        regs->cx = args.r14;
        regs->dx = args.r15;
 
-       return true;
+       return ve_instr_len(ve);
 }
 
 static bool mmio_read(int size, unsigned long addr, unsigned long *val)
@@ -283,10 +331,10 @@ static bool mmio_write(int size, unsigned long addr, unsigned long val)
                               EPT_WRITE, addr, val);
 }
 
-static bool handle_mmio(struct pt_regs *regs, struct ve_info *ve)
+static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
 {
+       unsigned long *reg, val, vaddr;
        char buffer[MAX_INSN_SIZE];
-       unsigned long *reg, val;
        struct insn insn = {};
        enum mmio_type mmio;
        int size, extend_size;
@@ -294,34 +342,49 @@ static bool handle_mmio(struct pt_regs *regs, struct ve_info *ve)
 
        /* Only in-kernel MMIO is supported */
        if (WARN_ON_ONCE(user_mode(regs)))
-               return false;
+               return -EFAULT;
 
        if (copy_from_kernel_nofault(buffer, (void *)regs->ip, MAX_INSN_SIZE))
-               return false;
+               return -EFAULT;
 
        if (insn_decode(&insn, buffer, MAX_INSN_SIZE, INSN_MODE_64))
-               return false;
+               return -EINVAL;
 
        mmio = insn_decode_mmio(&insn, &size);
        if (WARN_ON_ONCE(mmio == MMIO_DECODE_FAILED))
-               return false;
+               return -EINVAL;
 
        if (mmio != MMIO_WRITE_IMM && mmio != MMIO_MOVS) {
                reg = insn_get_modrm_reg_ptr(&insn, regs);
                if (!reg)
-                       return false;
+                       return -EINVAL;
        }
 
-       ve->instr_len = insn.length;
+       /*
+        * Reject EPT violation #VEs that split pages.
+        *
+        * MMIO accesses are supposed to be naturally aligned and therefore
+        * never cross page boundaries. Seeing split page accesses indicates
+        * a bug or a load_unaligned_zeropad() that stepped into an MMIO page.
+        *
+        * load_unaligned_zeropad() will recover using exception fixups.
+        */
+       vaddr = (unsigned long)insn_get_addr_ref(&insn, regs);
+       if (vaddr / PAGE_SIZE != (vaddr + size - 1) / PAGE_SIZE)
+               return -EFAULT;
 
        /* Handle writes first */
        switch (mmio) {
        case MMIO_WRITE:
                memcpy(&val, reg, size);
-               return mmio_write(size, ve->gpa, val);
+               if (!mmio_write(size, ve->gpa, val))
+                       return -EIO;
+               return insn.length;
        case MMIO_WRITE_IMM:
                val = insn.immediate.value;
-               return mmio_write(size, ve->gpa, val);
+               if (!mmio_write(size, ve->gpa, val))
+                       return -EIO;
+               return insn.length;
        case MMIO_READ:
        case MMIO_READ_ZERO_EXTEND:
        case MMIO_READ_SIGN_EXTEND:
@@ -334,15 +397,15 @@ static bool handle_mmio(struct pt_regs *regs, struct ve_info *ve)
                 * decoded or handled properly. It was likely not using io.h
                 * helpers or accessed MMIO accidentally.
                 */
-               return false;
+               return -EINVAL;
        default:
                WARN_ONCE(1, "Unknown insn_decode_mmio() decode value?");
-               return false;
+               return -EINVAL;
        }
 
        /* Handle reads */
        if (!mmio_read(size, ve->gpa, &val))
-               return false;
+               return -EIO;
 
        switch (mmio) {
        case MMIO_READ:
@@ -364,13 +427,13 @@ static bool handle_mmio(struct pt_regs *regs, struct ve_info *ve)
        default:
                /* All other cases has to be covered with the first switch() */
                WARN_ON_ONCE(1);
-               return false;
+               return -EINVAL;
        }
 
        if (extend_size)
                memset(reg, extend_val, extend_size);
        memcpy(reg, &val, size);
-       return true;
+       return insn.length;
 }
 
 static bool handle_in(struct pt_regs *regs, int size, int port)
@@ -421,13 +484,14 @@ static bool handle_out(struct pt_regs *regs, int size, int port)
  *
  * Return True on success or False on failure.
  */
-static bool handle_io(struct pt_regs *regs, u32 exit_qual)
+static int handle_io(struct pt_regs *regs, struct ve_info *ve)
 {
+       u32 exit_qual = ve->exit_qual;
        int size, port;
-       bool in;
+       bool in, ret;
 
        if (VE_IS_IO_STRING(exit_qual))
-               return false;
+               return -EIO;
 
        in   = VE_IS_IO_IN(exit_qual);
        size = VE_GET_IO_SIZE(exit_qual);
@@ -435,9 +499,13 @@ static bool handle_io(struct pt_regs *regs, u32 exit_qual)
 
 
        if (in)
-               return handle_in(regs, size, port);
+               ret = handle_in(regs, size, port);
        else
-               return handle_out(regs, size, port);
+               ret = handle_out(regs, size, port);
+       if (!ret)
+               return -EIO;
+
+       return ve_instr_len(ve);
 }
 
 /*
@@ -447,13 +515,19 @@ static bool handle_io(struct pt_regs *regs, u32 exit_qual)
 __init bool tdx_early_handle_ve(struct pt_regs *regs)
 {
        struct ve_info ve;
+       int insn_len;
 
        tdx_get_ve_info(&ve);
 
        if (ve.exit_reason != EXIT_REASON_IO_INSTRUCTION)
                return false;
 
-       return handle_io(regs, ve.exit_qual);
+       insn_len = handle_io(regs, &ve);
+       if (insn_len < 0)
+               return false;
+
+       regs->ip += insn_len;
+       return true;
 }
 
 void tdx_get_ve_info(struct ve_info *ve)
@@ -486,54 +560,65 @@ void tdx_get_ve_info(struct ve_info *ve)
        ve->instr_info  = upper_32_bits(out.r10);
 }
 
-/* Handle the user initiated #VE */
-static bool virt_exception_user(struct pt_regs *regs, struct ve_info *ve)
+/*
+ * Handle the user initiated #VE.
+ *
+ * On success, returns the number of bytes RIP should be incremented (>=0)
+ * or -errno on error.
+ */
+static int virt_exception_user(struct pt_regs *regs, struct ve_info *ve)
 {
        switch (ve->exit_reason) {
        case EXIT_REASON_CPUID:
-               return handle_cpuid(regs);
+               return handle_cpuid(regs, ve);
        default:
                pr_warn("Unexpected #VE: %lld\n", ve->exit_reason);
-               return false;
+               return -EIO;
        }
 }
 
-/* Handle the kernel #VE */
-static bool virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve)
+/*
+ * Handle the kernel #VE.
+ *
+ * On success, returns the number of bytes RIP should be incremented (>=0)
+ * or -errno on error.
+ */
+static int virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve)
 {
        switch (ve->exit_reason) {
        case EXIT_REASON_HLT:
-               return handle_halt();
+               return handle_halt(ve);
        case EXIT_REASON_MSR_READ:
-               return read_msr(regs);
+               return read_msr(regs, ve);
        case EXIT_REASON_MSR_WRITE:
-               return write_msr(regs);
+               return write_msr(regs, ve);
        case EXIT_REASON_CPUID:
-               return handle_cpuid(regs);
+               return handle_cpuid(regs, ve);
        case EXIT_REASON_EPT_VIOLATION:
                return handle_mmio(regs, ve);
        case EXIT_REASON_IO_INSTRUCTION:
-               return handle_io(regs, ve->exit_qual);
+               return handle_io(regs, ve);
        default:
                pr_warn("Unexpected #VE: %lld\n", ve->exit_reason);
-               return false;
+               return -EIO;
        }
 }
 
 bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve)
 {
-       bool ret;
+       int insn_len;
 
        if (user_mode(regs))
-               ret = virt_exception_user(regs, ve);
+               insn_len = virt_exception_user(regs, ve);
        else
-               ret = virt_exception_kernel(regs, ve);
+               insn_len = virt_exception_kernel(regs, ve);
+       if (insn_len < 0)
+               return false;
 
        /* After successful #VE handling, move the IP */
-       if (ret)
-               regs->ip += ve->instr_len;
+       regs->ip += insn_len;
 
-       return ret;
+       return true;
 }
 
 static bool tdx_tlb_flush_required(bool private)
index 8b392b6..3de6d8b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <asm/apic.h>
 #include <asm/desc.h>
+#include <asm/sev.h>
 #include <asm/hypervisor.h>
 #include <asm/hyperv-tlfs.h>
 #include <asm/mshyperv.h>
@@ -405,6 +406,11 @@ void __init hyperv_init(void)
        }
 
        if (hv_isolation_type_snp()) {
+               /* Negotiate GHCB Version. */
+               if (!hv_ghcb_negotiate_protocol())
+                       hv_ghcb_terminate(SEV_TERM_SET_GEN,
+                                         GHCB_SEV_ES_PROT_UNSUPPORTED);
+
                hv_ghcb_pg = alloc_percpu(union hv_ghcb *);
                if (!hv_ghcb_pg)
                        goto free_vp_assist_page;
index 2b99411..1dbcbd9 100644 (file)
@@ -53,6 +53,8 @@ union hv_ghcb {
        } hypercall;
 } __packed __aligned(HV_HYP_PAGE_SIZE);
 
+static u16 hv_ghcb_version __ro_after_init;
+
 u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
 {
        union hv_ghcb *hv_ghcb;
@@ -96,12 +98,85 @@ u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
        return status;
 }
 
+static inline u64 rd_ghcb_msr(void)
+{
+       return __rdmsr(MSR_AMD64_SEV_ES_GHCB);
+}
+
+static inline void wr_ghcb_msr(u64 val)
+{
+       native_wrmsrl(MSR_AMD64_SEV_ES_GHCB, val);
+}
+
+static enum es_result hv_ghcb_hv_call(struct ghcb *ghcb, u64 exit_code,
+                                  u64 exit_info_1, u64 exit_info_2)
+{
+       /* Fill in protocol and format specifiers */
+       ghcb->protocol_version = hv_ghcb_version;
+       ghcb->ghcb_usage       = GHCB_DEFAULT_USAGE;
+
+       ghcb_set_sw_exit_code(ghcb, exit_code);
+       ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
+       ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
+
+       VMGEXIT();
+
+       if (ghcb->save.sw_exit_info_1 & GENMASK_ULL(31, 0))
+               return ES_VMM_ERROR;
+       else
+               return ES_OK;
+}
+
+void hv_ghcb_terminate(unsigned int set, unsigned int reason)
+{
+       u64 val = GHCB_MSR_TERM_REQ;
+
+       /* Tell the hypervisor what went wrong. */
+       val |= GHCB_SEV_TERM_REASON(set, reason);
+
+       /* Request Guest Termination from Hypvervisor */
+       wr_ghcb_msr(val);
+       VMGEXIT();
+
+       while (true)
+               asm volatile("hlt\n" : : : "memory");
+}
+
+bool hv_ghcb_negotiate_protocol(void)
+{
+       u64 ghcb_gpa;
+       u64 val;
+
+       /* Save ghcb page gpa. */
+       ghcb_gpa = rd_ghcb_msr();
+
+       /* Do the GHCB protocol version negotiation */
+       wr_ghcb_msr(GHCB_MSR_SEV_INFO_REQ);
+       VMGEXIT();
+       val = rd_ghcb_msr();
+
+       if (GHCB_MSR_INFO(val) != GHCB_MSR_SEV_INFO_RESP)
+               return false;
+
+       if (GHCB_MSR_PROTO_MAX(val) < GHCB_PROTOCOL_MIN ||
+           GHCB_MSR_PROTO_MIN(val) > GHCB_PROTOCOL_MAX)
+               return false;
+
+       hv_ghcb_version = min_t(size_t, GHCB_MSR_PROTO_MAX(val),
+                            GHCB_PROTOCOL_MAX);
+
+       /* Write ghcb page back after negotiating protocol. */
+       wr_ghcb_msr(ghcb_gpa);
+       VMGEXIT();
+
+       return true;
+}
+
 void hv_ghcb_msr_write(u64 msr, u64 value)
 {
        union hv_ghcb *hv_ghcb;
        void **ghcb_base;
        unsigned long flags;
-       struct es_em_ctxt ctxt;
 
        if (!hv_ghcb_pg)
                return;
@@ -120,8 +195,7 @@ void hv_ghcb_msr_write(u64 msr, u64 value)
        ghcb_set_rax(&hv_ghcb->ghcb, lower_32_bits(value));
        ghcb_set_rdx(&hv_ghcb->ghcb, upper_32_bits(value));
 
-       if (sev_es_ghcb_hv_call(&hv_ghcb->ghcb, false, &ctxt,
-                               SVM_EXIT_MSR, 1, 0))
+       if (hv_ghcb_hv_call(&hv_ghcb->ghcb, SVM_EXIT_MSR, 1, 0))
                pr_warn("Fail to write msr via ghcb %llx.\n", msr);
 
        local_irq_restore(flags);
@@ -133,7 +207,6 @@ void hv_ghcb_msr_read(u64 msr, u64 *value)
        union hv_ghcb *hv_ghcb;
        void **ghcb_base;
        unsigned long flags;
-       struct es_em_ctxt ctxt;
 
        /* Check size of union hv_ghcb here. */
        BUILD_BUG_ON(sizeof(union hv_ghcb) != HV_HYP_PAGE_SIZE);
@@ -152,8 +225,7 @@ void hv_ghcb_msr_read(u64 msr, u64 *value)
        }
 
        ghcb_set_rcx(&hv_ghcb->ghcb, msr);
-       if (sev_es_ghcb_hv_call(&hv_ghcb->ghcb, false, &ctxt,
-                               SVM_EXIT_MSR, 0, 0))
+       if (hv_ghcb_hv_call(&hv_ghcb->ghcb, SVM_EXIT_MSR, 0, 0))
                pr_warn("Fail to read msr via ghcb %llx.\n", msr);
        else
                *value = (u64)lower_32_bits(hv_ghcb->ghcb.save.rax)
index 393f2bb..03acc82 100644 (file)
 #define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 #define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
+#define X86_BUG_MMIO_STALE_DATA                X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 5a39ed5..e8f58dd 100644 (file)
@@ -4,9 +4,6 @@
 
 #include <asm/e820/types.h>
 
-struct device;
-struct resource;
-
 extern struct e820_table *e820_table;
 extern struct e820_table *e820_table_kexec;
 extern struct e820_table *e820_table_firmware;
@@ -46,8 +43,6 @@ extern void e820__register_nosave_regions(unsigned long limit_pfn);
 
 extern int  e820__get_entry_type(u64 start, u64 end);
 
-extern void remove_e820_regions(struct device *dev, struct resource *avail);
-
 /*
  * Returns true iff the specified range [start,end) is completely contained inside
  * the ISA region.
index 71943dc..9636742 100644 (file)
@@ -323,7 +323,7 @@ static inline u32 efi64_convert_status(efi_status_t status)
 #define __efi64_argmap_get_memory_space_descriptor(phys, desc) \
        (__efi64_split(phys), (desc))
 
-#define __efi64_argmap_set_memory_space_descriptor(phys, size, flags) \
+#define __efi64_argmap_set_memory_space_attributes(phys, size, flags) \
        (__efi64_split(phys), __efi64_split(size), __efi64_split(flags))
 
 /*
index 3a240a6..9217bd6 100644 (file)
@@ -1047,14 +1047,77 @@ struct kvm_x86_msr_filter {
 };
 
 enum kvm_apicv_inhibit {
+
+       /********************************************************************/
+       /* INHIBITs that are relevant to both Intel's APICv and AMD's AVIC. */
+       /********************************************************************/
+
+       /*
+        * APIC acceleration is disabled by a module parameter
+        * and/or not supported in hardware.
+        */
        APICV_INHIBIT_REASON_DISABLE,
+
+       /*
+        * APIC acceleration is inhibited because AutoEOI feature is
+        * being used by a HyperV guest.
+        */
        APICV_INHIBIT_REASON_HYPERV,
+
+       /*
+        * APIC acceleration is inhibited because the userspace didn't yet
+        * enable the kernel/split irqchip.
+        */
+       APICV_INHIBIT_REASON_ABSENT,
+
+       /* APIC acceleration is inhibited because KVM_GUESTDBG_BLOCKIRQ
+        * (out of band, debug measure of blocking all interrupts on this vCPU)
+        * was enabled, to avoid AVIC/APICv bypassing it.
+        */
+       APICV_INHIBIT_REASON_BLOCKIRQ,
+
+       /*
+        * For simplicity, the APIC acceleration is inhibited
+        * first time either APIC ID or APIC base are changed by the guest
+        * from their reset values.
+        */
+       APICV_INHIBIT_REASON_APIC_ID_MODIFIED,
+       APICV_INHIBIT_REASON_APIC_BASE_MODIFIED,
+
+       /******************************************************/
+       /* INHIBITs that are relevant only to the AMD's AVIC. */
+       /******************************************************/
+
+       /*
+        * AVIC is inhibited on a vCPU because it runs a nested guest.
+        *
+        * This is needed because unlike APICv, the peers of this vCPU
+        * cannot use the doorbell mechanism to signal interrupts via AVIC when
+        * a vCPU runs nested.
+        */
        APICV_INHIBIT_REASON_NESTED,
+
+       /*
+        * On SVM, the wait for the IRQ window is implemented with pending vIRQ,
+        * which cannot be injected when the AVIC is enabled, thus AVIC
+        * is inhibited while KVM waits for IRQ window.
+        */
        APICV_INHIBIT_REASON_IRQWIN,
+
+       /*
+        * PIT (i8254) 're-inject' mode, relies on EOI intercept,
+        * which AVIC doesn't support for edge triggered interrupts.
+        */
        APICV_INHIBIT_REASON_PIT_REINJ,
+
+       /*
+        * AVIC is inhibited because the guest has x2apic in its CPUID.
+        */
        APICV_INHIBIT_REASON_X2APIC,
-       APICV_INHIBIT_REASON_BLOCKIRQ,
-       APICV_INHIBIT_REASON_ABSENT,
+
+       /*
+        * AVIC is disabled because SEV doesn't support it.
+        */
        APICV_INHIBIT_REASON_SEV,
 };
 
index a82f603..61f0c20 100644 (file)
@@ -179,9 +179,13 @@ int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible);
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 void hv_ghcb_msr_write(u64 msr, u64 value);
 void hv_ghcb_msr_read(u64 msr, u64 *value);
+bool hv_ghcb_negotiate_protocol(void);
+void hv_ghcb_terminate(unsigned int set, unsigned int reason);
 #else
 static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
 static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
+static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
+static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
 #endif
 
 extern bool hv_isolation_type_snp(void);
index 403e83b..d27e058 100644 (file)
                                                 * Not susceptible to
                                                 * TSX Async Abort (TAA) vulnerabilities.
                                                 */
+#define ARCH_CAP_SBDR_SSDP_NO          BIT(13) /*
+                                                * Not susceptible to SBDR and SSDP
+                                                * variants of Processor MMIO stale data
+                                                * vulnerabilities.
+                                                */
+#define ARCH_CAP_FBSDP_NO              BIT(14) /*
+                                                * Not susceptible to FBSDP variant of
+                                                * Processor MMIO stale data
+                                                * vulnerabilities.
+                                                */
+#define ARCH_CAP_PSDP_NO               BIT(15) /*
+                                                * Not susceptible to PSDP variant of
+                                                * Processor MMIO stale data
+                                                * vulnerabilities.
+                                                */
+#define ARCH_CAP_FB_CLEAR              BIT(17) /*
+                                                * VERW clears CPU fill buffer
+                                                * even on MDS_NO CPUs.
+                                                */
+#define ARCH_CAP_FB_CLEAR_CTRL         BIT(18) /*
+                                                * MSR_IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]
+                                                * bit available to control VERW
+                                                * behavior.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*
 #define MSR_IA32_MCU_OPT_CTRL          0x00000123
 #define RNGDS_MITG_DIS                 BIT(0)  /* SRBDS support */
 #define RTM_ALLOW                      BIT(1)  /* TSX development mode */
+#define FB_CLEAR_DIS                   BIT(3)  /* CPU Fill buffer clear disable */
 
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
index acbaeaf..da251a5 100644 (file)
@@ -269,6 +269,8 @@ DECLARE_STATIC_KEY_FALSE(mds_idle_clear);
 
 DECLARE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush);
 
+DECLARE_STATIC_KEY_FALSE(mmio_stale_data_clear);
+
 #include <asm/segment.h>
 
 /**
index f52a886..70533fd 100644 (file)
@@ -69,6 +69,8 @@ void pcibios_scan_specific_bus(int busn);
 
 /* pci-irq.c */
 
+struct pci_dev;
+
 struct irq_info {
        u8 bus, devfn;                  /* Bus, device and function */
        struct {
@@ -246,3 +248,9 @@ static inline void mmio_config_writel(void __iomem *pos, u32 val)
 # define x86_default_pci_init_irq      NULL
 # define x86_default_pci_fixup_irqs    NULL
 #endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_ACPI)
+extern bool pci_use_e820;
+#else
+#define pci_use_e820 false
+#endif
index 7590ac2..f8b9ee9 100644 (file)
@@ -108,19 +108,16 @@ extern unsigned long _brk_end;
 void *extend_brk(size_t size, size_t align);
 
 /*
- * Reserve space in the brk section.  The name must be unique within the file,
- * and somewhat descriptive.  The size is in bytes.
+ * Reserve space in the .brk section, which is a block of memory from which the
+ * caller is allowed to allocate very early (before even memblock is available)
+ * by calling extend_brk().  All allocated memory will be eventually converted
+ * to memblock.  Any leftover unallocated memory will be freed.
  *
- * The allocation is done using inline asm (rather than using a section
- * attribute on a normal variable) in order to allow the use of @nobits, so
- * that it doesn't take up any space in the vmlinux file.
+ * The size is in bytes.
  */
-#define RESERVE_BRK(name, size)                                                \
-       asm(".pushsection .brk_reservation,\"aw\",@nobits\n\t"          \
-           ".brk." #name ":\n\t"                                       \
-           ".skip " __stringify(size) "\n\t"                           \
-           ".size .brk." #name ", " __stringify(size) "\n\t"           \
-           ".popsection\n\t")
+#define RESERVE_BRK(name, size)                                        \
+       __section(".bss..brk") __aligned(1) __used      \
+       static char __brk_##name[size]
 
 extern void probe_roms(void);
 #ifdef __i386__
@@ -133,12 +130,19 @@ asmlinkage void __init x86_64_start_reservations(char *real_mode_data);
 
 #endif /* __i386__ */
 #endif /* _SETUP */
-#else
-#define RESERVE_BRK(name,sz)                           \
-       .pushsection .brk_reservation,"aw",@nobits;     \
-.brk.name:                                             \
-1:     .skip sz;                                       \
-       .size .brk.name,.-1b;                           \
+
+#else  /* __ASSEMBLY */
+
+.macro __RESERVE_BRK name, size
+       .pushsection .bss..brk, "aw"
+SYM_DATA_START(__brk_\name)
+       .skip \size
+SYM_DATA_END(__brk_\name)
        .popsection
+.endm
+
+#define RESERVE_BRK(name, size) __RESERVE_BRK name, size
+
 #endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_X86_SETUP_H */
index 03364dc..4c8b6ae 100644 (file)
@@ -36,10 +36,6 @@ KCSAN_SANITIZE := n
 
 OBJECT_FILES_NON_STANDARD_test_nx.o                    := y
 
-ifdef CONFIG_FRAME_POINTER
-OBJECT_FILES_NON_STANDARD_ftrace_$(BITS).o             := y
-endif
-
 # If instrumentation of this dir is enabled, boot hangs during first second.
 # Probably could be more selective here, but note that files related to irqs,
 # boot, dumpstack/stacktrace, etc are either non-interesting or can lead to
index d879a6c..74c62cc 100644 (file)
@@ -41,8 +41,10 @@ static void __init spectre_v2_select_mitigation(void);
 static void __init ssb_select_mitigation(void);
 static void __init l1tf_select_mitigation(void);
 static void __init mds_select_mitigation(void);
-static void __init mds_print_mitigation(void);
+static void __init md_clear_update_mitigation(void);
+static void __init md_clear_select_mitigation(void);
 static void __init taa_select_mitigation(void);
+static void __init mmio_select_mitigation(void);
 static void __init srbds_select_mitigation(void);
 static void __init l1d_flush_select_mitigation(void);
 
@@ -85,6 +87,10 @@ EXPORT_SYMBOL_GPL(mds_idle_clear);
  */
 DEFINE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush);
 
+/* Controls CPU Fill buffer clear before KVM guest MMIO accesses */
+DEFINE_STATIC_KEY_FALSE(mmio_stale_data_clear);
+EXPORT_SYMBOL_GPL(mmio_stale_data_clear);
+
 void __init check_bugs(void)
 {
        identify_boot_cpu();
@@ -117,17 +123,10 @@ void __init check_bugs(void)
        spectre_v2_select_mitigation();
        ssb_select_mitigation();
        l1tf_select_mitigation();
-       mds_select_mitigation();
-       taa_select_mitigation();
+       md_clear_select_mitigation();
        srbds_select_mitigation();
        l1d_flush_select_mitigation();
 
-       /*
-        * As MDS and TAA mitigations are inter-related, print MDS
-        * mitigation until after TAA mitigation selection is done.
-        */
-       mds_print_mitigation();
-
        arch_smt_update();
 
 #ifdef CONFIG_X86_32
@@ -267,14 +266,6 @@ static void __init mds_select_mitigation(void)
        }
 }
 
-static void __init mds_print_mitigation(void)
-{
-       if (!boot_cpu_has_bug(X86_BUG_MDS) || cpu_mitigations_off())
-               return;
-
-       pr_info("%s\n", mds_strings[mds_mitigation]);
-}
-
 static int __init mds_cmdline(char *str)
 {
        if (!boot_cpu_has_bug(X86_BUG_MDS))
@@ -329,7 +320,7 @@ static void __init taa_select_mitigation(void)
        /* TSX previously disabled by tsx=off */
        if (!boot_cpu_has(X86_FEATURE_RTM)) {
                taa_mitigation = TAA_MITIGATION_TSX_DISABLED;
-               goto out;
+               return;
        }
 
        if (cpu_mitigations_off()) {
@@ -343,7 +334,7 @@ static void __init taa_select_mitigation(void)
         */
        if (taa_mitigation == TAA_MITIGATION_OFF &&
            mds_mitigation == MDS_MITIGATION_OFF)
-               goto out;
+               return;
 
        if (boot_cpu_has(X86_FEATURE_MD_CLEAR))
                taa_mitigation = TAA_MITIGATION_VERW;
@@ -375,18 +366,6 @@ static void __init taa_select_mitigation(void)
 
        if (taa_nosmt || cpu_mitigations_auto_nosmt())
                cpu_smt_disable(false);
-
-       /*
-        * Update MDS mitigation, if necessary, as the mds_user_clear is
-        * now enabled for TAA mitigation.
-        */
-       if (mds_mitigation == MDS_MITIGATION_OFF &&
-           boot_cpu_has_bug(X86_BUG_MDS)) {
-               mds_mitigation = MDS_MITIGATION_FULL;
-               mds_select_mitigation();
-       }
-out:
-       pr_info("%s\n", taa_strings[taa_mitigation]);
 }
 
 static int __init tsx_async_abort_parse_cmdline(char *str)
@@ -410,6 +389,151 @@ static int __init tsx_async_abort_parse_cmdline(char *str)
 }
 early_param("tsx_async_abort", tsx_async_abort_parse_cmdline);
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "MMIO Stale Data: " fmt
+
+enum mmio_mitigations {
+       MMIO_MITIGATION_OFF,
+       MMIO_MITIGATION_UCODE_NEEDED,
+       MMIO_MITIGATION_VERW,
+};
+
+/* Default mitigation for Processor MMIO Stale Data vulnerabilities */
+static enum mmio_mitigations mmio_mitigation __ro_after_init = MMIO_MITIGATION_VERW;
+static bool mmio_nosmt __ro_after_init = false;
+
+static const char * const mmio_strings[] = {
+       [MMIO_MITIGATION_OFF]           = "Vulnerable",
+       [MMIO_MITIGATION_UCODE_NEEDED]  = "Vulnerable: Clear CPU buffers attempted, no microcode",
+       [MMIO_MITIGATION_VERW]          = "Mitigation: Clear CPU buffers",
+};
+
+static void __init mmio_select_mitigation(void)
+{
+       u64 ia32_cap;
+
+       if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
+           cpu_mitigations_off()) {
+               mmio_mitigation = MMIO_MITIGATION_OFF;
+               return;
+       }
+
+       if (mmio_mitigation == MMIO_MITIGATION_OFF)
+               return;
+
+       ia32_cap = x86_read_arch_cap_msr();
+
+       /*
+        * Enable CPU buffer clear mitigation for host and VMM, if also affected
+        * by MDS or TAA. Otherwise, enable mitigation for VMM only.
+        */
+       if (boot_cpu_has_bug(X86_BUG_MDS) || (boot_cpu_has_bug(X86_BUG_TAA) &&
+                                             boot_cpu_has(X86_FEATURE_RTM)))
+               static_branch_enable(&mds_user_clear);
+       else
+               static_branch_enable(&mmio_stale_data_clear);
+
+       /*
+        * If Processor-MMIO-Stale-Data bug is present and Fill Buffer data can
+        * be propagated to uncore buffers, clearing the Fill buffers on idle
+        * is required irrespective of SMT state.
+        */
+       if (!(ia32_cap & ARCH_CAP_FBSDP_NO))
+               static_branch_enable(&mds_idle_clear);
+
+       /*
+        * Check if the system has the right microcode.
+        *
+        * CPU Fill buffer clear mitigation is enumerated by either an explicit
+        * FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS
+        * affected systems.
+        */
+       if ((ia32_cap & ARCH_CAP_FB_CLEAR) ||
+           (boot_cpu_has(X86_FEATURE_MD_CLEAR) &&
+            boot_cpu_has(X86_FEATURE_FLUSH_L1D) &&
+            !(ia32_cap & ARCH_CAP_MDS_NO)))
+               mmio_mitigation = MMIO_MITIGATION_VERW;
+       else
+               mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED;
+
+       if (mmio_nosmt || cpu_mitigations_auto_nosmt())
+               cpu_smt_disable(false);
+}
+
+static int __init mmio_stale_data_parse_cmdline(char *str)
+{
+       if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+               return 0;
+
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "off")) {
+               mmio_mitigation = MMIO_MITIGATION_OFF;
+       } else if (!strcmp(str, "full")) {
+               mmio_mitigation = MMIO_MITIGATION_VERW;
+       } else if (!strcmp(str, "full,nosmt")) {
+               mmio_mitigation = MMIO_MITIGATION_VERW;
+               mmio_nosmt = true;
+       }
+
+       return 0;
+}
+early_param("mmio_stale_data", mmio_stale_data_parse_cmdline);
+
+#undef pr_fmt
+#define pr_fmt(fmt)     "" fmt
+
+static void __init md_clear_update_mitigation(void)
+{
+       if (cpu_mitigations_off())
+               return;
+
+       if (!static_key_enabled(&mds_user_clear))
+               goto out;
+
+       /*
+        * mds_user_clear is now enabled. Update MDS, TAA and MMIO Stale Data
+        * mitigation, if necessary.
+        */
+       if (mds_mitigation == MDS_MITIGATION_OFF &&
+           boot_cpu_has_bug(X86_BUG_MDS)) {
+               mds_mitigation = MDS_MITIGATION_FULL;
+               mds_select_mitigation();
+       }
+       if (taa_mitigation == TAA_MITIGATION_OFF &&
+           boot_cpu_has_bug(X86_BUG_TAA)) {
+               taa_mitigation = TAA_MITIGATION_VERW;
+               taa_select_mitigation();
+       }
+       if (mmio_mitigation == MMIO_MITIGATION_OFF &&
+           boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) {
+               mmio_mitigation = MMIO_MITIGATION_VERW;
+               mmio_select_mitigation();
+       }
+out:
+       if (boot_cpu_has_bug(X86_BUG_MDS))
+               pr_info("MDS: %s\n", mds_strings[mds_mitigation]);
+       if (boot_cpu_has_bug(X86_BUG_TAA))
+               pr_info("TAA: %s\n", taa_strings[taa_mitigation]);
+       if (boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+               pr_info("MMIO Stale Data: %s\n", mmio_strings[mmio_mitigation]);
+}
+
+static void __init md_clear_select_mitigation(void)
+{
+       mds_select_mitigation();
+       taa_select_mitigation();
+       mmio_select_mitigation();
+
+       /*
+        * As MDS, TAA and MMIO Stale Data mitigations are inter-related, update
+        * and print their mitigation after MDS, TAA and MMIO Stale Data
+        * mitigation selection is done.
+        */
+       md_clear_update_mitigation();
+}
+
 #undef pr_fmt
 #define pr_fmt(fmt)    "SRBDS: " fmt
 
@@ -478,11 +602,13 @@ static void __init srbds_select_mitigation(void)
                return;
 
        /*
-        * Check to see if this is one of the MDS_NO systems supporting
-        * TSX that are only exposed to SRBDS when TSX is enabled.
+        * Check to see if this is one of the MDS_NO systems supporting TSX that
+        * are only exposed to SRBDS when TSX is enabled or when CPU is affected
+        * by Processor MMIO Stale Data vulnerability.
         */
        ia32_cap = x86_read_arch_cap_msr();
-       if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM))
+       if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
+           !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
                srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
        else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
                srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR;
@@ -1116,6 +1242,8 @@ static void update_indir_branch_cond(void)
 /* Update the static key controlling the MDS CPU buffer clear in idle */
 static void update_mds_branch_idle(void)
 {
+       u64 ia32_cap = x86_read_arch_cap_msr();
+
        /*
         * Enable the idle clearing if SMT is active on CPUs which are
         * affected only by MSBDS and not any other MDS variant.
@@ -1127,14 +1255,17 @@ static void update_mds_branch_idle(void)
        if (!boot_cpu_has_bug(X86_BUG_MSBDS_ONLY))
                return;
 
-       if (sched_smt_active())
+       if (sched_smt_active()) {
                static_branch_enable(&mds_idle_clear);
-       else
+       } else if (mmio_mitigation == MMIO_MITIGATION_OFF ||
+                  (ia32_cap & ARCH_CAP_FBSDP_NO)) {
                static_branch_disable(&mds_idle_clear);
+       }
 }
 
 #define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
 #define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n"
+#define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n"
 
 void cpu_bugs_smt_update(void)
 {
@@ -1179,6 +1310,16 @@ void cpu_bugs_smt_update(void)
                break;
        }
 
+       switch (mmio_mitigation) {
+       case MMIO_MITIGATION_VERW:
+       case MMIO_MITIGATION_UCODE_NEEDED:
+               if (sched_smt_active())
+                       pr_warn_once(MMIO_MSG_SMT);
+               break;
+       case MMIO_MITIGATION_OFF:
+               break;
+       }
+
        mutex_unlock(&spec_ctrl_mutex);
 }
 
@@ -1781,6 +1922,20 @@ static ssize_t tsx_async_abort_show_state(char *buf)
                       sched_smt_active() ? "vulnerable" : "disabled");
 }
 
+static ssize_t mmio_stale_data_show_state(char *buf)
+{
+       if (mmio_mitigation == MMIO_MITIGATION_OFF)
+               return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
+
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
+               return sysfs_emit(buf, "%s; SMT Host state unknown\n",
+                                 mmio_strings[mmio_mitigation]);
+       }
+
+       return sysfs_emit(buf, "%s; SMT %s\n", mmio_strings[mmio_mitigation],
+                         sched_smt_active() ? "vulnerable" : "disabled");
+}
+
 static char *stibp_state(void)
 {
        if (spectre_v2_in_eibrs_mode(spectre_v2_enabled))
@@ -1881,6 +2036,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
        case X86_BUG_SRBDS:
                return srbds_show_state(buf);
 
+       case X86_BUG_MMIO_STALE_DATA:
+               return mmio_stale_data_show_state(buf);
+
        default:
                break;
        }
@@ -1932,4 +2090,9 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *
 {
        return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS);
 }
+
+ssize_t cpu_show_mmio_stale_data(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
+}
 #endif
index c296cb1..4730b0a 100644 (file)
@@ -1211,18 +1211,42 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
                                            X86_FEATURE_ANY, issues)
 
 #define SRBDS          BIT(0)
+/* CPU is affected by X86_BUG_MMIO_STALE_DATA */
+#define MMIO           BIT(1)
+/* CPU is affected by Shared Buffers Data Sampling (SBDS), a variant of X86_BUG_MMIO_STALE_DATA */
+#define MMIO_SBDS      BIT(2)
 
 static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
        VULNBL_INTEL_STEPPINGS(IVYBRIDGE,       X86_STEPPING_ANY,               SRBDS),
        VULNBL_INTEL_STEPPINGS(HASWELL,         X86_STEPPING_ANY,               SRBDS),
        VULNBL_INTEL_STEPPINGS(HASWELL_L,       X86_STEPPING_ANY,               SRBDS),
        VULNBL_INTEL_STEPPINGS(HASWELL_G,       X86_STEPPING_ANY,               SRBDS),
+       VULNBL_INTEL_STEPPINGS(HASWELL_X,       BIT(2) | BIT(4),                MMIO),
+       VULNBL_INTEL_STEPPINGS(BROADWELL_D,     X86_STEPPINGS(0x3, 0x5),        MMIO),
        VULNBL_INTEL_STEPPINGS(BROADWELL_G,     X86_STEPPING_ANY,               SRBDS),
+       VULNBL_INTEL_STEPPINGS(BROADWELL_X,     X86_STEPPING_ANY,               MMIO),
        VULNBL_INTEL_STEPPINGS(BROADWELL,       X86_STEPPING_ANY,               SRBDS),
+       VULNBL_INTEL_STEPPINGS(SKYLAKE_L,       X86_STEPPINGS(0x3, 0x3),        SRBDS | MMIO),
        VULNBL_INTEL_STEPPINGS(SKYLAKE_L,       X86_STEPPING_ANY,               SRBDS),
+       VULNBL_INTEL_STEPPINGS(SKYLAKE_X,       BIT(3) | BIT(4) | BIT(6) |
+                                               BIT(7) | BIT(0xB),              MMIO),
+       VULNBL_INTEL_STEPPINGS(SKYLAKE,         X86_STEPPINGS(0x3, 0x3),        SRBDS | MMIO),
        VULNBL_INTEL_STEPPINGS(SKYLAKE,         X86_STEPPING_ANY,               SRBDS),
-       VULNBL_INTEL_STEPPINGS(KABYLAKE_L,      X86_STEPPINGS(0x0, 0xC),        SRBDS),
-       VULNBL_INTEL_STEPPINGS(KABYLAKE,        X86_STEPPINGS(0x0, 0xD),        SRBDS),
+       VULNBL_INTEL_STEPPINGS(KABYLAKE_L,      X86_STEPPINGS(0x9, 0xC),        SRBDS | MMIO),
+       VULNBL_INTEL_STEPPINGS(KABYLAKE_L,      X86_STEPPINGS(0x0, 0x8),        SRBDS),
+       VULNBL_INTEL_STEPPINGS(KABYLAKE,        X86_STEPPINGS(0x9, 0xD),        SRBDS | MMIO),
+       VULNBL_INTEL_STEPPINGS(KABYLAKE,        X86_STEPPINGS(0x0, 0x8),        SRBDS),
+       VULNBL_INTEL_STEPPINGS(ICELAKE_L,       X86_STEPPINGS(0x5, 0x5),        MMIO | MMIO_SBDS),
+       VULNBL_INTEL_STEPPINGS(ICELAKE_D,       X86_STEPPINGS(0x1, 0x1),        MMIO),
+       VULNBL_INTEL_STEPPINGS(ICELAKE_X,       X86_STEPPINGS(0x4, 0x6),        MMIO),
+       VULNBL_INTEL_STEPPINGS(COMETLAKE,       BIT(2) | BIT(3) | BIT(5),       MMIO | MMIO_SBDS),
+       VULNBL_INTEL_STEPPINGS(COMETLAKE_L,     X86_STEPPINGS(0x1, 0x1),        MMIO | MMIO_SBDS),
+       VULNBL_INTEL_STEPPINGS(COMETLAKE_L,     X86_STEPPINGS(0x0, 0x0),        MMIO),
+       VULNBL_INTEL_STEPPINGS(LAKEFIELD,       X86_STEPPINGS(0x1, 0x1),        MMIO | MMIO_SBDS),
+       VULNBL_INTEL_STEPPINGS(ROCKETLAKE,      X86_STEPPINGS(0x1, 0x1),        MMIO),
+       VULNBL_INTEL_STEPPINGS(ATOM_TREMONT,    X86_STEPPINGS(0x1, 0x1),        MMIO | MMIO_SBDS),
+       VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D,  X86_STEPPING_ANY,               MMIO),
+       VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L,  X86_STEPPINGS(0x0, 0x0),        MMIO | MMIO_SBDS),
        {}
 };
 
@@ -1243,6 +1267,13 @@ u64 x86_read_arch_cap_msr(void)
        return ia32_cap;
 }
 
+static bool arch_cap_mmio_immune(u64 ia32_cap)
+{
+       return (ia32_cap & ARCH_CAP_FBSDP_NO &&
+               ia32_cap & ARCH_CAP_PSDP_NO &&
+               ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
+}
+
 static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 {
        u64 ia32_cap = x86_read_arch_cap_msr();
@@ -1296,12 +1327,27 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
        /*
         * SRBDS affects CPUs which support RDRAND or RDSEED and are listed
         * in the vulnerability blacklist.
+        *
+        * Some of the implications and mitigation of Shared Buffers Data
+        * Sampling (SBDS) are similar to SRBDS. Give SBDS same treatment as
+        * SRBDS.
         */
        if ((cpu_has(c, X86_FEATURE_RDRAND) ||
             cpu_has(c, X86_FEATURE_RDSEED)) &&
-           cpu_matches(cpu_vuln_blacklist, SRBDS))
+           cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
                    setup_force_cpu_bug(X86_BUG_SRBDS);
 
+       /*
+        * Processor MMIO Stale Data bug enumeration
+        *
+        * Affected CPU list is generally enough to enumerate the vulnerability,
+        * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
+        * not want the guest to enumerate the bug.
+        */
+       if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
+           !arch_cap_mmio_immune(ia32_cap))
+               setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+
        if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
                return;
 
index 4ec1360..dfeb227 100644 (file)
@@ -175,6 +175,7 @@ SYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL)
 
        jmp ftrace_epilogue
 SYM_FUNC_END(ftrace_caller);
+STACK_FRAME_NON_STANDARD_FP(ftrace_caller)
 
 SYM_FUNC_START(ftrace_epilogue)
 /*
@@ -282,6 +283,7 @@ SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL)
        jmp     ftrace_epilogue
 
 SYM_FUNC_END(ftrace_regs_caller)
+STACK_FRAME_NON_STANDARD_FP(ftrace_regs_caller)
 
 
 #else /* ! CONFIG_DYNAMIC_FTRACE */
@@ -311,10 +313,14 @@ trace:
        jmp ftrace_stub
 SYM_FUNC_END(__fentry__)
 EXPORT_SYMBOL(__fentry__)
+STACK_FRAME_NON_STANDARD_FP(__fentry__)
+
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-SYM_FUNC_START(return_to_handler)
+SYM_CODE_START(return_to_handler)
+       UNWIND_HINT_EMPTY
+       ANNOTATE_NOENDBR
        subq  $16, %rsp
 
        /* Save the return values */
@@ -339,7 +345,6 @@ SYM_FUNC_START(return_to_handler)
        int3
 .Ldo_rop:
        mov %rdi, (%rsp)
-       UNWIND_HINT_FUNC
        RET
-SYM_FUNC_END(return_to_handler)
+SYM_CODE_END(return_to_handler)
 #endif
index db2b350..bba1abd 100644 (file)
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/dev_printk.h>
 #include <linux/ioport.h>
+#include <linux/printk.h>
 #include <asm/e820/api.h>
+#include <asm/pci_x86.h>
 
 static void resource_clip(struct resource *res, resource_size_t start,
                          resource_size_t end)
@@ -24,14 +25,14 @@ static void resource_clip(struct resource *res, resource_size_t start,
                res->start = end + 1;
 }
 
-void remove_e820_regions(struct device *dev, struct resource *avail)
+static void remove_e820_regions(struct resource *avail)
 {
        int i;
        struct e820_entry *entry;
        u64 e820_start, e820_end;
        struct resource orig = *avail;
 
-       if (!(avail->flags & IORESOURCE_MEM))
+       if (!pci_use_e820)
                return;
 
        for (i = 0; i < e820_table->nr_entries; i++) {
@@ -41,7 +42,7 @@ void remove_e820_regions(struct device *dev, struct resource *avail)
 
                resource_clip(avail, e820_start, e820_end);
                if (orig.start != avail->start || orig.end != avail->end) {
-                       dev_info(dev, "clipped %pR to %pR for e820 entry [mem %#010Lx-%#010Lx]\n",
+                       pr_info("clipped %pR to %pR for e820 entry [mem %#010Lx-%#010Lx]\n",
                                 &orig, avail, e820_start, e820_end);
                        orig = *avail;
                }
@@ -55,6 +56,9 @@ void arch_remove_reservations(struct resource *avail)
         * the low 1MB unconditionally, as this area is needed for some ISA
         * cards requiring a memory range, e.g. the i82365 PCMCIA controller.
         */
-       if (avail->flags & IORESOURCE_MEM)
+       if (avail->flags & IORESOURCE_MEM) {
                resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
+
+               remove_e820_regions(avail);
+       }
 }
index 3ebb853..bd6c6fd 100644 (file)
@@ -67,11 +67,6 @@ RESERVE_BRK(dmi_alloc, 65536);
 #endif
 
 
-/*
- * Range of the BSS area. The size of the BSS area is determined
- * at link time, with RESERVE_BRK() facility reserving additional
- * chunks.
- */
 unsigned long _brk_start = (unsigned long)__brk_base;
 unsigned long _brk_end   = (unsigned long)__brk_base;
 
index f5f6dc2..81aba71 100644 (file)
@@ -385,10 +385,10 @@ SECTIONS
        __end_of_kernel_reserve = .;
 
        . = ALIGN(PAGE_SIZE);
-       .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
+       .brk (NOLOAD) : AT(ADDR(.brk) - LOAD_OFFSET) {
                __brk_base = .;
                . += 64 * 1024;         /* 64k alignment slop space */
-               *(.brk_reservation)     /* areas brk users have reserved */
+               *(.bss..brk)            /* areas brk users have reserved */
                __brk_limit = .;
        }
 
index f1bdac3..0e68b4c 100644 (file)
@@ -2039,6 +2039,19 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
        }
 }
 
+static void kvm_lapic_xapic_id_updated(struct kvm_lapic *apic)
+{
+       struct kvm *kvm = apic->vcpu->kvm;
+
+       if (KVM_BUG_ON(apic_x2apic_mode(apic), kvm))
+               return;
+
+       if (kvm_xapic_id(apic) == apic->vcpu->vcpu_id)
+               return;
+
+       kvm_set_apicv_inhibit(apic->vcpu->kvm, APICV_INHIBIT_REASON_APIC_ID_MODIFIED);
+}
+
 static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 {
        int ret = 0;
@@ -2047,10 +2060,12 @@ static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
        switch (reg) {
        case APIC_ID:           /* Local APIC ID */
-               if (!apic_x2apic_mode(apic))
+               if (!apic_x2apic_mode(apic)) {
                        kvm_apic_set_xapic_id(apic, val >> 24);
-               else
+                       kvm_lapic_xapic_id_updated(apic);
+               } else {
                        ret = 1;
+               }
                break;
 
        case APIC_TASKPRI:
@@ -2336,8 +2351,10 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                             MSR_IA32_APICBASE_BASE;
 
        if ((value & MSR_IA32_APICBASE_ENABLE) &&
-            apic->base_address != APIC_DEFAULT_PHYS_BASE)
-               pr_warn_once("APIC base relocation is unsupported by KVM");
+            apic->base_address != APIC_DEFAULT_PHYS_BASE) {
+               kvm_set_apicv_inhibit(apic->vcpu->kvm,
+                                     APICV_INHIBIT_REASON_APIC_BASE_MODIFIED);
+       }
 }
 
 void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
@@ -2648,6 +2665,8 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
                        icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
                        __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
                }
+       } else {
+               kvm_lapic_xapic_id_updated(vcpu->arch.apic);
        }
 
        return 0;
index e826ee9..17252f3 100644 (file)
@@ -3411,7 +3411,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
                        root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT),
                                              i << 30, PT32_ROOT_LEVEL, true);
                        mmu->pae_root[i] = root | PT_PRESENT_MASK |
-                                          shadow_me_mask;
+                                          shadow_me_value;
                }
                mmu->root.hpa = __pa(mmu->pae_root);
        } else {
index 54fe037..d1bc582 100644 (file)
@@ -291,58 +291,91 @@ void avic_ring_doorbell(struct kvm_vcpu *vcpu)
 static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source,
                                       u32 icrl, u32 icrh, u32 index)
 {
-       u32 dest, apic_id;
-       struct kvm_vcpu *vcpu;
+       u32 l1_physical_id, dest;
+       struct kvm_vcpu *target_vcpu;
        int dest_mode = icrl & APIC_DEST_MASK;
        int shorthand = icrl & APIC_SHORT_MASK;
        struct kvm_svm *kvm_svm = to_kvm_svm(kvm);
-       u32 *avic_logical_id_table = page_address(kvm_svm->avic_logical_id_table_page);
 
        if (shorthand != APIC_DEST_NOSHORT)
                return -EINVAL;
 
-       /*
-        * The AVIC incomplete IPI #vmexit info provides index into
-        * the physical APIC ID table, which can be used to derive
-        * guest physical APIC ID.
-        */
+       if (apic_x2apic_mode(source))
+               dest = icrh;
+       else
+               dest = GET_APIC_DEST_FIELD(icrh);
+
        if (dest_mode == APIC_DEST_PHYSICAL) {
-               apic_id = index;
+               /* broadcast destination, use slow path */
+               if (apic_x2apic_mode(source) && dest == X2APIC_BROADCAST)
+                       return -EINVAL;
+               if (!apic_x2apic_mode(source) && dest == APIC_BROADCAST)
+                       return -EINVAL;
+
+               l1_physical_id = dest;
+
+               if (WARN_ON_ONCE(l1_physical_id != index))
+                       return -EINVAL;
+
        } else {
-               if (!apic_x2apic_mode(source)) {
-                       /* For xAPIC logical mode, the index is for logical APIC table. */
-                       apic_id = avic_logical_id_table[index] & 0x1ff;
+               u32 bitmap, cluster;
+               int logid_index;
+
+               if (apic_x2apic_mode(source)) {
+                       /* 16 bit dest mask, 16 bit cluster id */
+                       bitmap = dest & 0xFFFF0000;
+                       cluster = (dest >> 16) << 4;
+               } else if (kvm_lapic_get_reg(source, APIC_DFR) == APIC_DFR_FLAT) {
+                       /* 8 bit dest mask*/
+                       bitmap = dest;
+                       cluster = 0;
                } else {
-                       return -EINVAL;
+                       /* 4 bit desk mask, 4 bit cluster id */
+                       bitmap = dest & 0xF;
+                       cluster = (dest >> 4) << 2;
                }
-       }
 
-       /*
-        * Assuming vcpu ID is the same as physical apic ID,
-        * and use it to retrieve the target vCPU.
-        */
-       vcpu = kvm_get_vcpu_by_id(kvm, apic_id);
-       if (!vcpu)
-               return -EINVAL;
+               if (unlikely(!bitmap))
+                       /* guest bug: nobody to send the logical interrupt to */
+                       return 0;
 
-       if (apic_x2apic_mode(vcpu->arch.apic))
-               dest = icrh;
-       else
-               dest = GET_APIC_DEST_FIELD(icrh);
+               if (!is_power_of_2(bitmap))
+                       /* multiple logical destinations, use slow path */
+                       return -EINVAL;
 
-       /*
-        * Try matching the destination APIC ID with the vCPU.
-        */
-       if (kvm_apic_match_dest(vcpu, source, shorthand, dest, dest_mode)) {
-               vcpu->arch.apic->irr_pending = true;
-               svm_complete_interrupt_delivery(vcpu,
-                                               icrl & APIC_MODE_MASK,
-                                               icrl & APIC_INT_LEVELTRIG,
-                                               icrl & APIC_VECTOR_MASK);
-               return 0;
+               logid_index = cluster + __ffs(bitmap);
+
+               if (apic_x2apic_mode(source)) {
+                       l1_physical_id = logid_index;
+               } else {
+                       u32 *avic_logical_id_table =
+                               page_address(kvm_svm->avic_logical_id_table_page);
+
+                       u32 logid_entry = avic_logical_id_table[logid_index];
+
+                       if (WARN_ON_ONCE(index != logid_index))
+                               return -EINVAL;
+
+                       /* guest bug: non existing/reserved logical destination */
+                       if (unlikely(!(logid_entry & AVIC_LOGICAL_ID_ENTRY_VALID_MASK)))
+                               return 0;
+
+                       l1_physical_id = logid_entry &
+                                        AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK;
+               }
        }
 
-       return -EINVAL;
+       target_vcpu = kvm_get_vcpu_by_id(kvm, l1_physical_id);
+       if (unlikely(!target_vcpu))
+               /* guest bug: non existing vCPU is a target of this IPI*/
+               return 0;
+
+       target_vcpu->arch.apic->irr_pending = true;
+       svm_complete_interrupt_delivery(target_vcpu,
+                                       icrl & APIC_MODE_MASK,
+                                       icrl & APIC_INT_LEVELTRIG,
+                                       icrl & APIC_VECTOR_MASK);
+       return 0;
 }
 
 static void avic_kick_target_vcpus(struct kvm *kvm, struct kvm_lapic *source,
@@ -508,35 +541,6 @@ static int avic_handle_ldr_update(struct kvm_vcpu *vcpu)
        return ret;
 }
 
-static int avic_handle_apic_id_update(struct kvm_vcpu *vcpu)
-{
-       u64 *old, *new;
-       struct vcpu_svm *svm = to_svm(vcpu);
-       u32 id = kvm_xapic_id(vcpu->arch.apic);
-
-       if (vcpu->vcpu_id == id)
-               return 0;
-
-       old = avic_get_physical_id_entry(vcpu, vcpu->vcpu_id);
-       new = avic_get_physical_id_entry(vcpu, id);
-       if (!new || !old)
-               return 1;
-
-       /* We need to move physical_id_entry to new offset */
-       *new = *old;
-       *old = 0ULL;
-       to_svm(vcpu)->avic_physical_id_cache = new;
-
-       /*
-        * Also update the guest physical APIC ID in the logical
-        * APIC ID table entry if already setup the LDR.
-        */
-       if (svm->ldr_reg)
-               avic_handle_ldr_update(vcpu);
-
-       return 0;
-}
-
 static void avic_handle_dfr_update(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -555,10 +559,6 @@ static int avic_unaccel_trap_write(struct kvm_vcpu *vcpu)
                                AVIC_UNACCEL_ACCESS_OFFSET_MASK;
 
        switch (offset) {
-       case APIC_ID:
-               if (avic_handle_apic_id_update(vcpu))
-                       return 0;
-               break;
        case APIC_LDR:
                if (avic_handle_ldr_update(vcpu))
                        return 0;
@@ -650,8 +650,6 @@ int avic_init_vcpu(struct vcpu_svm *svm)
 
 void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu)
 {
-       if (avic_handle_apic_id_update(vcpu) != 0)
-               return;
        avic_handle_dfr_update(vcpu);
        avic_handle_ldr_update(vcpu);
 }
@@ -910,7 +908,9 @@ bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
                          BIT(APICV_INHIBIT_REASON_PIT_REINJ) |
                          BIT(APICV_INHIBIT_REASON_X2APIC) |
                          BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
-                         BIT(APICV_INHIBIT_REASON_SEV);
+                         BIT(APICV_INHIBIT_REASON_SEV)      |
+                         BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
+                         BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED);
 
        return supported & BIT(reason);
 }
@@ -946,7 +946,7 @@ out:
        return ret;
 }
 
-void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        u64 entry;
        int h_physical_id = kvm_cpu_get_apicid(cpu);
@@ -978,7 +978,7 @@ void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        avic_update_iommu_vcpu_affinity(vcpu, h_physical_id, true);
 }
 
-void __avic_vcpu_put(struct kvm_vcpu *vcpu)
+void avic_vcpu_put(struct kvm_vcpu *vcpu)
 {
        u64 entry;
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -997,25 +997,6 @@ void __avic_vcpu_put(struct kvm_vcpu *vcpu)
        WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
 }
 
-static void avic_vcpu_load(struct kvm_vcpu *vcpu)
-{
-       int cpu = get_cpu();
-
-       WARN_ON(cpu != vcpu->cpu);
-
-       __avic_vcpu_load(vcpu, cpu);
-
-       put_cpu();
-}
-
-static void avic_vcpu_put(struct kvm_vcpu *vcpu)
-{
-       preempt_disable();
-
-       __avic_vcpu_put(vcpu);
-
-       preempt_enable();
-}
 
 void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
 {
@@ -1042,7 +1023,7 @@ void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
        vmcb_mark_dirty(vmcb, VMCB_AVIC);
 
        if (activated)
-               avic_vcpu_load(vcpu);
+               avic_vcpu_load(vcpu, vcpu->cpu);
        else
                avic_vcpu_put(vcpu);
 
@@ -1075,5 +1056,5 @@ void avic_vcpu_unblocking(struct kvm_vcpu *vcpu)
        if (!kvm_vcpu_apicv_active(vcpu))
                return;
 
-       avic_vcpu_load(vcpu);
+       avic_vcpu_load(vcpu, vcpu->cpu);
 }
index 3361258..ba7cd26 100644 (file)
@@ -616,6 +616,8 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
        struct kvm_vcpu *vcpu = &svm->vcpu;
        struct vmcb *vmcb01 = svm->vmcb01.ptr;
        struct vmcb *vmcb02 = svm->nested.vmcb02.ptr;
+       u32 pause_count12;
+       u32 pause_thresh12;
 
        /*
         * Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2,
@@ -671,27 +673,25 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
        if (!nested_vmcb_needs_vls_intercept(svm))
                vmcb02->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
 
+       pause_count12 = svm->pause_filter_enabled ? svm->nested.ctl.pause_filter_count : 0;
+       pause_thresh12 = svm->pause_threshold_enabled ? svm->nested.ctl.pause_filter_thresh : 0;
        if (kvm_pause_in_guest(svm->vcpu.kvm)) {
-               /* use guest values since host doesn't use them */
-               vmcb02->control.pause_filter_count =
-                               svm->pause_filter_enabled ?
-                               svm->nested.ctl.pause_filter_count : 0;
+               /* use guest values since host doesn't intercept PAUSE */
+               vmcb02->control.pause_filter_count = pause_count12;
+               vmcb02->control.pause_filter_thresh = pause_thresh12;
 
-               vmcb02->control.pause_filter_thresh =
-                               svm->pause_threshold_enabled ?
-                               svm->nested.ctl.pause_filter_thresh : 0;
-
-       } else if (!vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_PAUSE)) {
-               /* use host values when guest doesn't use them */
+       } else {
+               /* start from host values otherwise */
                vmcb02->control.pause_filter_count = vmcb01->control.pause_filter_count;
                vmcb02->control.pause_filter_thresh = vmcb01->control.pause_filter_thresh;
-       } else {
-               /*
-                * Intercept every PAUSE otherwise and
-                * ignore both host and guest values
-                */
-               vmcb02->control.pause_filter_count = 0;
-               vmcb02->control.pause_filter_thresh = 0;
+
+               /* ... but ensure filtering is disabled if so requested.  */
+               if (vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_PAUSE)) {
+                       if (!pause_count12)
+                               vmcb02->control.pause_filter_count = 0;
+                       if (!pause_thresh12)
+                               vmcb02->control.pause_filter_thresh = 0;
+               }
        }
 
        nested_svm_transition_tlb_flush(vcpu);
@@ -951,8 +951,11 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
        vmcb12->control.event_inj         = svm->nested.ctl.event_inj;
        vmcb12->control.event_inj_err     = svm->nested.ctl.event_inj_err;
 
-       if (!kvm_pause_in_guest(vcpu->kvm) && vmcb02->control.pause_filter_count)
+       if (!kvm_pause_in_guest(vcpu->kvm)) {
                vmcb01->control.pause_filter_count = vmcb02->control.pause_filter_count;
+               vmcb_mark_dirty(vmcb01, VMCB_INTERCEPTS);
+
+       }
 
        nested_svm_copy_common_state(svm->nested.vmcb02.ptr, svm->vmcb01.ptr);
 
index 1dc02cd..87da903 100644 (file)
@@ -921,7 +921,7 @@ static void grow_ple_window(struct kvm_vcpu *vcpu)
        struct vmcb_control_area *control = &svm->vmcb->control;
        int old = control->pause_filter_count;
 
-       if (kvm_pause_in_guest(vcpu->kvm) || !old)
+       if (kvm_pause_in_guest(vcpu->kvm))
                return;
 
        control->pause_filter_count = __grow_ple_window(old,
@@ -942,7 +942,7 @@ static void shrink_ple_window(struct kvm_vcpu *vcpu)
        struct vmcb_control_area *control = &svm->vmcb->control;
        int old = control->pause_filter_count;
 
-       if (kvm_pause_in_guest(vcpu->kvm) || !old)
+       if (kvm_pause_in_guest(vcpu->kvm))
                return;
 
        control->pause_filter_count =
@@ -1400,13 +1400,13 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                indirect_branch_prediction_barrier();
        }
        if (kvm_vcpu_apicv_active(vcpu))
-               __avic_vcpu_load(vcpu, cpu);
+               avic_vcpu_load(vcpu, cpu);
 }
 
 static void svm_vcpu_put(struct kvm_vcpu *vcpu)
 {
        if (kvm_vcpu_apicv_active(vcpu))
-               __avic_vcpu_put(vcpu);
+               avic_vcpu_put(vcpu);
 
        svm_prepare_host_switch(vcpu);
 
index 500348c..1bddd33 100644 (file)
@@ -610,8 +610,8 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb);
 int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu);
 int avic_unaccelerated_access_interception(struct kvm_vcpu *vcpu);
 int avic_init_vcpu(struct vcpu_svm *svm);
-void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
-void __avic_vcpu_put(struct kvm_vcpu *vcpu);
+void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
+void avic_vcpu_put(struct kvm_vcpu *vcpu);
 void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);
 void avic_set_virtual_apic_mode(struct kvm_vcpu *vcpu);
 void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu);
index 9bd86ec..3a919e4 100644 (file)
@@ -229,6 +229,9 @@ static const struct {
 #define L1D_CACHE_ORDER 4
 static void *vmx_l1d_flush_pages;
 
+/* Control for disabling CPU Fill buffer clear */
+static bool __read_mostly vmx_fb_clear_ctrl_available;
+
 static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
 {
        struct page *page;
@@ -360,6 +363,60 @@ static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
        return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option);
 }
 
+static void vmx_setup_fb_clear_ctrl(void)
+{
+       u64 msr;
+
+       if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES) &&
+           !boot_cpu_has_bug(X86_BUG_MDS) &&
+           !boot_cpu_has_bug(X86_BUG_TAA)) {
+               rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
+               if (msr & ARCH_CAP_FB_CLEAR_CTRL)
+                       vmx_fb_clear_ctrl_available = true;
+       }
+}
+
+static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx)
+{
+       u64 msr;
+
+       if (!vmx->disable_fb_clear)
+               return;
+
+       rdmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
+       msr |= FB_CLEAR_DIS;
+       wrmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
+       /* Cache the MSR value to avoid reading it later */
+       vmx->msr_ia32_mcu_opt_ctrl = msr;
+}
+
+static __always_inline void vmx_enable_fb_clear(struct vcpu_vmx *vmx)
+{
+       if (!vmx->disable_fb_clear)
+               return;
+
+       vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS;
+       wrmsrl(MSR_IA32_MCU_OPT_CTRL, vmx->msr_ia32_mcu_opt_ctrl);
+}
+
+static void vmx_update_fb_clear_dis(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
+{
+       vmx->disable_fb_clear = vmx_fb_clear_ctrl_available;
+
+       /*
+        * If guest will not execute VERW, there is no need to set FB_CLEAR_DIS
+        * at VMEntry. Skip the MSR read/write when a guest has no use case to
+        * execute VERW.
+        */
+       if ((vcpu->arch.arch_capabilities & ARCH_CAP_FB_CLEAR) ||
+          ((vcpu->arch.arch_capabilities & ARCH_CAP_MDS_NO) &&
+           (vcpu->arch.arch_capabilities & ARCH_CAP_TAA_NO) &&
+           (vcpu->arch.arch_capabilities & ARCH_CAP_PSDP_NO) &&
+           (vcpu->arch.arch_capabilities & ARCH_CAP_FBSDP_NO) &&
+           (vcpu->arch.arch_capabilities & ARCH_CAP_SBDR_SSDP_NO)))
+               vmx->disable_fb_clear = false;
+}
+
 static const struct kernel_param_ops vmentry_l1d_flush_ops = {
        .set = vmentry_l1d_flush_set,
        .get = vmentry_l1d_flush_get,
@@ -2252,6 +2309,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        ret = kvm_set_msr_common(vcpu, msr_info);
        }
 
+       /* FB_CLEAR may have changed, also update the FB_CLEAR_DIS behavior */
+       if (msr_index == MSR_IA32_ARCH_CAPABILITIES)
+               vmx_update_fb_clear_dis(vcpu, vmx);
+
        return ret;
 }
 
@@ -4553,6 +4614,8 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
 
        vpid_sync_context(vmx->vpid);
+
+       vmx_update_fb_clear_dis(vcpu, vmx);
 }
 
 static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)
@@ -6772,6 +6835,11 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
                vmx_l1d_flush(vcpu);
        else if (static_branch_unlikely(&mds_user_clear))
                mds_clear_cpu_buffers();
+       else if (static_branch_unlikely(&mmio_stale_data_clear) &&
+                kvm_arch_has_assigned_device(vcpu->kvm))
+               mds_clear_cpu_buffers();
+
+       vmx_disable_fb_clear(vmx);
 
        if (vcpu->arch.cr2 != native_read_cr2())
                native_write_cr2(vcpu->arch.cr2);
@@ -6781,6 +6849,8 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
 
        vcpu->arch.cr2 = native_read_cr2();
 
+       vmx_enable_fb_clear(vmx);
+
        guest_state_exit_irqoff();
 }
 
@@ -7709,7 +7779,9 @@ static bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
        ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
                          BIT(APICV_INHIBIT_REASON_ABSENT) |
                          BIT(APICV_INHIBIT_REASON_HYPERV) |
-                         BIT(APICV_INHIBIT_REASON_BLOCKIRQ);
+                         BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
+                         BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
+                         BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED);
 
        return supported & BIT(reason);
 }
@@ -8212,6 +8284,8 @@ static int __init vmx_init(void)
                return r;
        }
 
+       vmx_setup_fb_clear_ctrl();
+
        for_each_possible_cpu(cpu) {
                INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
 
index b98c7e9..8d2342e 100644 (file)
@@ -348,6 +348,8 @@ struct vcpu_vmx {
        u64 msr_ia32_feature_control_valid_bits;
        /* SGX Launch Control public key hash */
        u64 msr_ia32_sgxlepubkeyhash[4];
+       u64 msr_ia32_mcu_opt_ctrl;
+       bool disable_fb_clear;
 
        struct pt_desc pt_desc;
        struct lbr_desc lbr_desc;
index 03fbfbb..1910e1e 100644 (file)
@@ -1617,6 +1617,9 @@ static u64 kvm_get_arch_capabilities(void)
                 */
        }
 
+       /* Guests don't need to know "Fill buffer clear control" exists */
+       data &= ~ARCH_CAP_FB_CLEAR_CTRL;
+
        return data;
 }
 
@@ -9850,6 +9853,7 @@ void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
                return;
 
        down_read(&vcpu->kvm->arch.apicv_update_lock);
+       preempt_disable();
 
        activate = kvm_vcpu_apicv_activated(vcpu);
 
@@ -9870,6 +9874,7 @@ void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
                kvm_make_request(KVM_REQ_EVENT, vcpu);
 
 out:
+       preempt_enable();
        up_read(&vcpu->kvm->arch.apicv_update_lock);
 }
 EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
index f298b18..c98b8c0 100644 (file)
@@ -1420,8 +1420,9 @@ st:                       if (is_imm8(insn->off))
                case BPF_JMP | BPF_CALL:
                        func = (u8 *) __bpf_call_base + imm32;
                        if (tail_call_reachable) {
+                               /* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */
                                EMIT3_off32(0x48, 0x8B, 0x85,
-                                           -(bpf_prog->aux->stack_depth + 8));
+                                           -round_up(bpf_prog->aux->stack_depth, 8) - 8);
                                if (!imm32 || emit_call(&prog, func, image + addrs[i - 1] + 7))
                                        return -EINVAL;
                        } else {
index a4f4305..2f82480 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/pci-acpi.h>
 #include <asm/numa.h>
 #include <asm/pci_x86.h>
-#include <asm/e820/api.h>
 
 struct pci_root_info {
        struct acpi_pci_root_info common;
@@ -20,7 +19,7 @@ struct pci_root_info {
 #endif
 };
 
-static bool pci_use_e820 = true;
+bool pci_use_e820 = true;
 static bool pci_use_crs = true;
 static bool pci_ignore_seg;
 
@@ -387,11 +386,6 @@ static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
 
        status = acpi_pci_probe_root_resources(ci);
 
-       if (pci_use_e820) {
-               resource_list_for_each_entry(entry, &ci->resources)
-                       remove_e820_regions(&device->dev, entry->res);
-       }
-
        if (pci_use_crs) {
                resource_list_for_each_entry_safe(entry, tmp, &ci->resources)
                        if (resource_is_pcicfg_ioport(entry->res))
index 0d46cb7..e6d7e6b 100644 (file)
@@ -7046,6 +7046,7 @@ static void bfq_exit_queue(struct elevator_queue *e)
        spin_unlock_irq(&bfqd->lock);
 #endif
 
+       blk_stat_disable_accounting(bfqd->queue);
        wbt_enable_default(bfqd->queue);
 
        kfree(bfqd);
@@ -7188,7 +7189,12 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
        bfq_init_root_group(bfqd->root_group, bfqd);
        bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group);
 
+       /* We dispatch from request queue wide instead of hw queue */
+       blk_queue_flag_set(QUEUE_FLAG_SQ_SCHED, q);
+
        wbt_disable_default(q);
+       blk_stat_enable_accounting(q);
+
        return 0;
 
 out_free:
index 9e56a69..eb3c65a 100644 (file)
@@ -564,6 +564,7 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
        int ret;
 
        if (!e) {
+               blk_queue_flag_clear(QUEUE_FLAG_SQ_SCHED, q);
                q->elevator = NULL;
                q->nr_requests = q->tag_set->queue_depth;
                return 0;
index e9bf950..33145ba 100644 (file)
@@ -579,6 +579,8 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
        if (!blk_mq_hw_queue_mapped(data.hctx))
                goto out_queue_exit;
        cpu = cpumask_first_and(data.hctx->cpumask, cpu_online_mask);
+       if (cpu >= nr_cpu_ids)
+               goto out_queue_exit;
        data.ctx = __blk_mq_get_ctx(q, cpu);
 
        if (!q->elevator)
@@ -2140,20 +2142,6 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
 }
 EXPORT_SYMBOL(blk_mq_run_hw_queue);
 
-/*
- * Is the request queue handled by an IO scheduler that does not respect
- * hardware queues when dispatching?
- */
-static bool blk_mq_has_sqsched(struct request_queue *q)
-{
-       struct elevator_queue *e = q->elevator;
-
-       if (e && e->type->ops.dispatch_request &&
-           !(e->type->elevator_features & ELEVATOR_F_MQ_AWARE))
-               return true;
-       return false;
-}
-
 /*
  * Return prefered queue to dispatch from (if any) for non-mq aware IO
  * scheduler.
@@ -2186,7 +2174,7 @@ void blk_mq_run_hw_queues(struct request_queue *q, bool async)
        unsigned long i;
 
        sq_hctx = NULL;
-       if (blk_mq_has_sqsched(q))
+       if (blk_queue_sq_sched(q))
                sq_hctx = blk_mq_get_sq_hctx(q);
        queue_for_each_hw_ctx(q, hctx, i) {
                if (blk_mq_hctx_stopped(hctx))
@@ -2214,7 +2202,7 @@ void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs)
        unsigned long i;
 
        sq_hctx = NULL;
-       if (blk_mq_has_sqsched(q))
+       if (blk_queue_sq_sched(q))
                sq_hctx = blk_mq_get_sq_hctx(q);
        queue_for_each_hw_ctx(q, hctx, i) {
                if (blk_mq_hctx_stopped(hctx))
@@ -3443,8 +3431,9 @@ static void blk_mq_exit_hctx(struct request_queue *q,
        if (blk_mq_hw_queue_mapped(hctx))
                blk_mq_tag_idle(hctx);
 
-       blk_mq_clear_flush_rq_mapping(set->tags[hctx_idx],
-                       set->queue_depth, flush_rq);
+       if (blk_queue_init_done(q))
+               blk_mq_clear_flush_rq_mapping(set->tags[hctx_idx],
+                               set->queue_depth, flush_rq);
        if (set->ops->exit_request)
                set->ops->exit_request(set, flush_rq, hctx_idx);
 
@@ -4438,12 +4427,14 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
        if (!qe)
                return false;
 
+       /* q->elevator needs protection from ->sysfs_lock */
+       mutex_lock(&q->sysfs_lock);
+
        INIT_LIST_HEAD(&qe->node);
        qe->q = q;
        qe->type = q->elevator->type;
        list_add(&qe->node, head);
 
-       mutex_lock(&q->sysfs_lock);
        /*
         * After elevator_switch_mq, the previous elevator_queue will be
         * released by elevator_release. The reference of the io scheduler
index 70ff2a5..8f7c745 100644 (file)
@@ -421,6 +421,8 @@ static int kyber_init_sched(struct request_queue *q, struct elevator_type *e)
 
        blk_stat_enable_accounting(q);
 
+       blk_queue_flag_clear(QUEUE_FLAG_SQ_SCHED, q);
+
        eq->elevator_data = kqd;
        q->elevator = eq;
 
@@ -1033,7 +1035,6 @@ static struct elevator_type kyber_sched = {
 #endif
        .elevator_attrs = kyber_sched_attrs,
        .elevator_name = "kyber",
-       .elevator_features = ELEVATOR_F_MQ_AWARE,
        .elevator_owner = THIS_MODULE,
 };
 
index 6ed602b..1a9e835 100644 (file)
@@ -642,6 +642,9 @@ static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
        spin_lock_init(&dd->lock);
        spin_lock_init(&dd->zone_lock);
 
+       /* We dispatch from request queue wide instead of hw queue */
+       blk_queue_flag_set(QUEUE_FLAG_SQ_SCHED, q);
+
        q->elevator = eq;
        return 0;
 
index 56637ac..cec5465 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-/blacklist_hashes_checked
+/blacklist_hash_list
 /extract-cert
 /x509_certificate_list
 /x509_revocation_list
index cb1a9da..88a73b2 100644 (file)
@@ -3,26 +3,26 @@
 # Makefile for the linux kernel signature checking certificates.
 #
 
-obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o common.o
-obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o common.o
+obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
+obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
 obj-$(CONFIG_SYSTEM_REVOCATION_LIST) += revocation_certificates.o
 ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),)
-quiet_cmd_check_blacklist_hashes = CHECK   $(patsubst "%",%,$(2))
-      cmd_check_blacklist_hashes = $(AWK) -f $(srctree)/scripts/check-blacklist-hashes.awk $(2); touch $@
 
-$(eval $(call config_filename,SYSTEM_BLACKLIST_HASH_LIST))
+$(obj)/blacklist_hashes.o: $(obj)/blacklist_hash_list
+CFLAGS_blacklist_hashes.o := -I $(obj)
 
-$(obj)/blacklist_hashes.o: $(obj)/blacklist_hashes_checked
+quiet_cmd_check_and_copy_blacklist_hash_list = GEN     $@
+      cmd_check_and_copy_blacklist_hash_list = \
+       $(AWK) -f $(srctree)/scripts/check-blacklist-hashes.awk $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) >&2; \
+       cat $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) > $@
 
-CFLAGS_blacklist_hashes.o += -I$(srctree)
-
-targets += blacklist_hashes_checked
-$(obj)/blacklist_hashes_checked: $(SYSTEM_BLACKLIST_HASH_LIST_SRCPREFIX)$(SYSTEM_BLACKLIST_HASH_LIST_FILENAME) scripts/check-blacklist-hashes.awk FORCE
-       $(call if_changed,check_blacklist_hashes,$(SYSTEM_BLACKLIST_HASH_LIST_SRCPREFIX)$(CONFIG_SYSTEM_BLACKLIST_HASH_LIST))
+$(obj)/blacklist_hash_list: $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) FORCE
+       $(call if_changed,check_and_copy_blacklist_hash_list)
 obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
 else
 obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o
 endif
+targets += blacklist_hash_list
 
 quiet_cmd_extract_certs  = CERT    $@
       cmd_extract_certs  = $(obj)/extract-cert $(extract-cert-in) $@
@@ -33,7 +33,7 @@ $(obj)/system_certificates.o: $(obj)/x509_certificate_list
 $(obj)/x509_certificate_list: $(CONFIG_SYSTEM_TRUSTED_KEYS) $(obj)/extract-cert FORCE
        $(call if_changed,extract_certs)
 
-targets += x509_certificate_list blacklist_hashes_checked
+targets += x509_certificate_list
 
 # If module signing is requested, say by allyesconfig, but a key has not been
 # supplied, then one will need to be generated to make sure the build does not
index 25094ea..41f1060 100644 (file)
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/uidgid.h>
-#include <linux/verification.h>
+#include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
 #include "blacklist.h"
-#include "common.h"
 
 /*
  * According to crypto/asymmetric_keys/x509_cert_parser.c:x509_note_pkey_algo(),
@@ -365,8 +364,9 @@ static __init int load_revocation_certificate_list(void)
        if (revocation_certificate_list_size)
                pr_notice("Loading compiled-in revocation X.509 certificates\n");
 
-       return load_certificate_list(revocation_certificate_list, revocation_certificate_list_size,
-                                    blacklist_keyring);
+       return x509_load_certificate_list(revocation_certificate_list,
+                                         revocation_certificate_list_size,
+                                         blacklist_keyring);
 }
 late_initcall(load_revocation_certificate_list);
 #endif
index 3448923..86d66fe 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "blacklist.h"
 
-const char __initdata *const blacklist_hashes[] = {
-#include CONFIG_SYSTEM_BLACKLIST_HASH_LIST
+const char __initconst *const blacklist_hashes[] = {
+#include "blacklist_hash_list"
        , NULL
 };
diff --git a/certs/common.c b/certs/common.c
deleted file mode 100644 (file)
index 16a2208..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <linux/kernel.h>
-#include <linux/key.h>
-#include "common.h"
-
-int load_certificate_list(const u8 cert_list[],
-                         const unsigned long list_size,
-                         const struct key *keyring)
-{
-       key_ref_t key;
-       const u8 *p, *end;
-       size_t plen;
-
-       p = cert_list;
-       end = p + list_size;
-       while (p < end) {
-               /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
-                * than 256 bytes in size.
-                */
-               if (end - p < 4)
-                       goto dodgy_cert;
-               if (p[0] != 0x30 &&
-                   p[1] != 0x82)
-                       goto dodgy_cert;
-               plen = (p[2] << 8) | p[3];
-               plen += 4;
-               if (plen > end - p)
-                       goto dodgy_cert;
-
-               key = key_create_or_update(make_key_ref(keyring, 1),
-                                          "asymmetric",
-                                          NULL,
-                                          p,
-                                          plen,
-                                          ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                                          KEY_USR_VIEW | KEY_USR_READ),
-                                          KEY_ALLOC_NOT_IN_QUOTA |
-                                          KEY_ALLOC_BUILT_IN |
-                                          KEY_ALLOC_BYPASS_RESTRICTION);
-               if (IS_ERR(key)) {
-                       pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
-                              PTR_ERR(key));
-               } else {
-                       pr_notice("Loaded X.509 cert '%s'\n",
-                                 key_ref_to_ptr(key)->description);
-                       key_ref_put(key);
-               }
-               p += plen;
-       }
-
-       return 0;
-
-dodgy_cert:
-       pr_err("Problem parsing in-kernel X.509 certificate list\n");
-       return 0;
-}
diff --git a/certs/common.h b/certs/common.h
deleted file mode 100644 (file)
index abdb579..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-#ifndef _CERT_COMMON_H
-#define _CERT_COMMON_H
-
-int load_certificate_list(const u8 cert_list[], const unsigned long list_size,
-                         const struct key *keyring);
-
-#endif
index 05b66ce..5042cc5 100644 (file)
@@ -16,7 +16,6 @@
 #include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
 #include <crypto/pkcs7.h>
-#include "common.h"
 
 static struct key *builtin_trusted_keys;
 #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
@@ -183,7 +182,8 @@ __init int load_module_cert(struct key *keyring)
 
        pr_notice("Loading compiled-in module X.509 certificates\n");
 
-       return load_certificate_list(system_certificate_list, module_cert_size, keyring);
+       return x509_load_certificate_list(system_certificate_list,
+                                         module_cert_size, keyring);
 }
 
 /*
@@ -204,7 +204,7 @@ static __init int load_system_certificate_list(void)
        size = system_certificate_list_size - module_cert_size;
 #endif
 
-       return load_certificate_list(p, size, builtin_trusted_keys);
+       return x509_load_certificate_list(p, size, builtin_trusted_keys);
 }
 late_initcall(load_system_certificate_list);
 
index 1919746..1d44893 100644 (file)
@@ -15,6 +15,7 @@ source "crypto/async_tx/Kconfig"
 #
 menuconfig CRYPTO
        tristate "Cryptographic API"
+       select LIB_MEMNEQ
        help
          This option provides the core Cryptographic API.
 
index 43bc33e..ceaaa9f 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 obj-$(CONFIG_CRYPTO) += crypto.o
-crypto-y := api.o cipher.o compress.o memneq.o
+crypto-y := api.o cipher.o compress.o
 
 obj-$(CONFIG_CRYPTO_ENGINE) += crypto_engine.o
 obj-$(CONFIG_CRYPTO_FIPS) += fips.o
index 460bc5d..3df3fe4 100644 (file)
@@ -75,4 +75,14 @@ config SIGNED_PE_FILE_VERIFICATION
          This option provides support for verifying the signature(s) on a
          signed PE binary.
 
+config FIPS_SIGNATURE_SELFTEST
+       bool "Run FIPS selftests on the X.509+PKCS7 signature verification"
+       help
+         This option causes some selftests to be run on the signature
+         verification code, using some built in data.  This is required
+         for FIPS.
+       depends on KEYS
+       depends on ASYMMETRIC_KEY_TYPE
+       depends on PKCS7_MESSAGE_PARSER
+
 endif # ASYMMETRIC_KEY_TYPE
index c38424f..0d1fa1b 100644 (file)
@@ -20,7 +20,9 @@ x509_key_parser-y := \
        x509.asn1.o \
        x509_akid.asn1.o \
        x509_cert_parser.o \
+       x509_loader.o \
        x509_public_key.o
+x509_key_parser-$(CONFIG_FIPS_SIGNATURE_SELFTEST) += selftest.o
 
 $(obj)/x509_cert_parser.o: \
        $(obj)/x509.asn1.h \
diff --git a/crypto/asymmetric_keys/selftest.c b/crypto/asymmetric_keys/selftest.c
new file mode 100644 (file)
index 0000000..fa0bf7f
--- /dev/null
@@ -0,0 +1,224 @@
+/* Self-testing for signature checking.
+ *
+ * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/cred.h>
+#include <linux/key.h>
+#include <crypto/pkcs7.h>
+#include "x509_parser.h"
+
+struct certs_test {
+       const u8        *data;
+       size_t          data_len;
+       const u8        *pkcs7;
+       size_t          pkcs7_len;
+};
+
+/*
+ * Set of X.509 certificates to provide public keys for the tests.  These will
+ * be loaded into a temporary keyring for the duration of the testing.
+ */
+static const __initconst u8 certs_selftest_keys[] = {
+       "\x30\x82\x05\x55\x30\x82\x03\x3d\xa0\x03\x02\x01\x02\x02\x14\x73"
+       "\x98\xea\x98\x2d\xd0\x2e\xa8\xb1\xcf\x57\xc7\xf2\x97\xb3\xe6\x1a"
+       "\xfc\x8c\x0a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b"
+       "\x05\x00\x30\x34\x31\x32\x30\x30\x06\x03\x55\x04\x03\x0c\x29\x43"
+       "\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x76\x65\x72\x69\x66"
+       "\x69\x63\x61\x74\x69\x6f\x6e\x20\x73\x65\x6c\x66\x2d\x74\x65\x73"
+       "\x74\x69\x6e\x67\x20\x6b\x65\x79\x30\x20\x17\x0d\x32\x32\x30\x35"
+       "\x31\x38\x32\x32\x33\x32\x34\x31\x5a\x18\x0f\x32\x31\x32\x32\x30"
+       "\x34\x32\x34\x32\x32\x33\x32\x34\x31\x5a\x30\x34\x31\x32\x30\x30"
+       "\x06\x03\x55\x04\x03\x0c\x29\x43\x65\x72\x74\x69\x66\x69\x63\x61"
+       "\x74\x65\x20\x76\x65\x72\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20"
+       "\x73\x65\x6c\x66\x2d\x74\x65\x73\x74\x69\x6e\x67\x20\x6b\x65\x79"
+       "\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01"
+       "\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01"
+       "\x00\xcc\xac\x49\xdd\x3b\xca\xb0\x15\x7e\x84\x6a\xb2\x0a\x69\x5f"
+       "\x1c\x0a\x61\x82\x3b\x4f\x2c\xa3\x95\x2c\x08\x58\x4b\xb1\x5d\x99"
+       "\xe0\xc3\xc1\x79\xc2\xb3\xeb\xc0\x1e\x6d\x3e\x54\x1d\xbd\xb7\x92"
+       "\x7b\x4d\xb5\x95\x58\xb2\x52\x2e\xc6\x24\x4b\x71\x63\x80\x32\x77"
+       "\xa7\x38\x5e\xdb\x72\xae\x6e\x0d\xec\xfb\xb6\x6d\x01\x7f\xe9\x55"
+       "\x66\xdf\xbf\x1d\x76\x78\x02\x31\xe8\xe5\x07\xf8\xb7\x82\x5c\x0d"
+       "\xd4\xbb\xfb\xa2\x59\x0d\x2e\x3a\x78\x95\x3a\x8b\x46\x06\x47\x44"
+       "\x46\xd7\xcd\x06\x6a\x41\x13\xe3\x19\xf6\xbb\x6e\x38\xf4\x83\x01"
+       "\xa3\xbf\x4a\x39\x4f\xd7\x0a\xe9\x38\xb3\xf5\x94\x14\x4e\xdd\xf7"
+       "\x43\xfd\x24\xb2\x49\x3c\xa5\xf7\x7a\x7c\xd4\x45\x3d\x97\x75\x68"
+       "\xf1\xed\x4c\x42\x0b\x70\xca\x85\xf3\xde\xe5\x88\x2c\xc5\xbe\xb6"
+       "\x97\x34\xba\x24\x02\xcd\x8b\x86\x9f\xa9\x73\xca\x73\xcf\x92\x81"
+       "\xee\x75\x55\xbb\x18\x67\x5c\xff\x3f\xb5\xdd\x33\x1b\x0c\xe9\x78"
+       "\xdb\x5c\xcf\xaa\x5c\x43\x42\xdf\x5e\xa9\x6d\xec\xd7\xd7\xff\xe6"
+       "\xa1\x3a\x92\x1a\xda\xae\xf6\x8c\x6f\x7b\xd5\xb4\x6e\x06\xe9\x8f"
+       "\xe8\xde\x09\x31\x89\xed\x0e\x11\xa1\xfa\x8a\xe9\xe9\x64\x59\x62"
+       "\x53\xda\xd1\x70\xbe\x11\xd4\x99\x97\x11\xcf\x99\xde\x0b\x9d\x94"
+       "\x7e\xaa\xb8\x52\xea\x37\xdb\x90\x7e\x35\xbd\xd9\xfe\x6d\x0a\x48"
+       "\x70\x28\xdd\xd5\x0d\x7f\x03\x80\x93\x14\x23\x8f\xb9\x22\xcd\x7c"
+       "\x29\xfe\xf1\x72\xb5\x5c\x0b\x12\xcf\x9c\x15\xf6\x11\x4c\x7a\x45"
+       "\x25\x8c\x45\x0a\x34\xac\x2d\x9a\x81\xca\x0b\x13\x22\xcd\xeb\x1a"
+       "\x38\x88\x18\x97\x96\x08\x81\xaa\xcc\x8f\x0f\x8a\x32\x7b\x76\x68"
+       "\x03\x68\x43\xbf\x11\xba\x55\x60\xfd\x80\x1c\x0d\x9b\x69\xb6\x09"
+       "\x72\xbc\x0f\x41\x2f\x07\x82\xc6\xe3\xb2\x13\x91\xc4\x6d\x14\x95"
+       "\x31\xbe\x19\xbd\xbc\xed\xe1\x4c\x74\xa2\xe0\x78\x0b\xbb\x94\xec"
+       "\x4c\x53\x3a\xa2\xb5\x84\x1d\x4b\x65\x7e\xdc\xf7\xdb\x36\x7d\xbe"
+       "\x9e\x3b\x36\x66\x42\x66\x76\x35\xbf\xbe\xf0\xc1\x3c\x7c\xe9\x42"
+       "\x5c\x24\x53\x03\x05\xa8\x67\x24\x50\x02\x75\xff\x24\x46\x3b\x35"
+       "\x89\x76\xe6\x70\xda\xc5\x51\x8c\x9a\xe5\x05\xb0\x0b\xd0\x2d\xd4"
+       "\x7d\x57\x75\x94\x6b\xf9\x0a\xad\x0e\x41\x00\x15\xd0\x4f\xc0\x7f"
+       "\x90\x2d\x18\x48\x8f\x28\xfe\x5d\xa7\xcd\x99\x9e\xbd\x02\x6c\x8a"
+       "\x31\xf3\x1c\xc7\x4b\xe6\x93\xcd\x42\xa2\xe4\x68\x10\x47\x9d\xfc"
+       "\x21\x02\x03\x01\x00\x01\xa3\x5d\x30\x5b\x30\x0c\x06\x03\x55\x1d"
+       "\x13\x01\x01\xff\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04"
+       "\x04\x03\x02\x07\x80\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14"
+       "\xf5\x87\x03\xbb\x33\xce\x1b\x73\xee\x02\xec\xcd\xee\x5b\x88\x17"
+       "\x51\x8f\xe3\xdb\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80"
+       "\x14\xf5\x87\x03\xbb\x33\xce\x1b\x73\xee\x02\xec\xcd\xee\x5b\x88"
+       "\x17\x51\x8f\xe3\xdb\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01"
+       "\x01\x0b\x05\x00\x03\x82\x02\x01\x00\xc0\x2e\x12\x41\x7b\x73\x85"
+       "\x16\xc8\xdb\x86\x79\xe8\xf5\xcd\x44\xf4\xc6\xe2\x81\x23\x5e\x47"
+       "\xcb\xab\x25\xf1\x1e\x58\x3e\x31\x7f\x78\xad\x85\xeb\xfe\x14\x88"
+       "\x60\xf7\x7f\xd2\x26\xa2\xf4\x98\x2a\xfd\xba\x05\x0c\x20\x33\x12"
+       "\xcc\x4d\x14\x61\x64\x81\x93\xd3\x33\xed\xc8\xff\xf1\x78\xcc\x5f"
+       "\x51\x9f\x09\xd7\xbe\x0d\x5c\x74\xfd\x9b\xdf\x52\x4a\xc9\xa8\x71"
+       "\x25\x33\x04\x10\x67\x36\xd0\xb3\x0b\xc9\xa1\x40\x72\xae\x41\x7b"
+       "\x68\xe6\xe4\x7b\xd0\x28\xf7\x6d\xe7\x3f\x50\xfc\x91\x7c\x91\x56"
+       "\xd4\xdf\xa6\xbb\xe8\x4d\x1b\x58\xaa\x28\xfa\xc1\x19\xeb\x11\x2f"
+       "\x24\x8b\x7c\xc5\xa9\x86\x26\xaa\x6e\xb7\x9b\xd5\xf8\x06\xfb\x02"
+       "\x52\x7b\x9c\x9e\xa1\xe0\x07\x8b\x5e\xe4\xb8\x55\x29\xf6\x48\x52"
+       "\x1c\x1b\x54\x2d\x46\xd8\xe5\x71\xb9\x60\xd1\x45\xb5\x92\x89\x8a"
+       "\x63\x58\x2a\xb3\xc6\xb2\x76\xe2\x3c\x82\x59\x04\xae\x5a\xc4\x99"
+       "\x7b\x2e\x4b\x46\x57\xb8\x29\x24\xb2\xfd\xee\x2c\x0d\xa4\x83\xfa"
+       "\x65\x2a\x07\x35\x8b\x97\xcf\xbd\x96\x2e\xd1\x7e\x6c\xc2\x1e\x87"
+       "\xb6\x6c\x76\x65\xb5\xb2\x62\xda\x8b\xe9\x73\xe3\xdb\x33\xdd\x13"
+       "\x3a\x17\x63\x6a\x76\xde\x8d\x8f\xe0\x47\x61\x28\x3a\x83\xff\x8f"
+       "\xe7\xc7\xe0\x4a\xa3\xe5\x07\xcf\xe9\x8c\x35\x35\x2e\xe7\x80\x66"
+       "\x31\xbf\x91\x58\x0a\xe1\x25\x3d\x38\xd3\xa4\xf0\x59\x34\x47\x07"
+       "\x62\x0f\xbe\x30\xdd\x81\x88\x58\xf0\x28\xb0\x96\xe5\x82\xf8\x05"
+       "\xb7\x13\x01\xbc\xfa\xc6\x1f\x86\x72\xcc\xf9\xee\x8e\xd9\xd6\x04"
+       "\x8c\x24\x6c\xbf\x0f\x5d\x37\x39\xcf\x45\xc1\x93\x3a\xd2\xed\x5c"
+       "\x58\x79\x74\x86\x62\x30\x7e\x8e\xbb\xdd\x7a\xa9\xed\xca\x40\xcb"
+       "\x62\x47\xf4\xb4\x9f\x52\x7f\x72\x63\xa8\xf0\x2b\xaf\x45\x2a\x48"
+       "\x19\x6d\xe3\xfb\xf9\x19\x66\x69\xc8\xcc\x62\x87\x6c\x53\x2b\x2d"
+       "\x6e\x90\x6c\x54\x3a\x82\x25\x41\xcb\x18\x6a\xa4\x22\xa8\xa1\xc4"
+       "\x47\xd7\x81\x00\x1c\x15\x51\x0f\x1a\xaf\xef\x9f\xa6\x61\x8c\xbd"
+       "\x6b\x8b\xed\xe6\xac\x0e\xb6\x3a\x4c\x92\xe6\x0f\x91\x0a\x0f\x71"
+       "\xc7\xa0\xb9\x0d\x3a\x17\x5a\x6f\x35\xc8\xe7\x50\x4f\x46\xe8\x70"
+       "\x60\x48\x06\x82\x8b\x66\x58\xe6\x73\x91\x9c\x12\x3d\x35\x8e\x46"
+       "\xad\x5a\xf5\xb3\xdb\x69\x21\x04\xfd\xd3\x1c\xdf\x94\x9d\x56\xb0"
+       "\x0a\xd1\x95\x76\x8d\xec\x9e\xdd\x0b\x15\x97\x64\xad\xe5\xf2\x62"
+       "\x02\xfc\x9e\x5f\x56\x42\x39\x05\xb3"
+};
+
+/*
+ * Signed data and detached signature blobs that form the verification tests.
+ */
+static const __initconst u8 certs_selftest_1_data[] = {
+       "\x54\x68\x69\x73\x20\x69\x73\x20\x73\x6f\x6d\x65\x20\x74\x65\x73"
+       "\x74\x20\x64\x61\x74\x61\x20\x75\x73\x65\x64\x20\x66\x6f\x72\x20"
+       "\x73\x65\x6c\x66\x2d\x74\x65\x73\x74\x69\x6e\x67\x20\x63\x65\x72"
+       "\x74\x69\x66\x69\x63\x61\x74\x65\x20\x76\x65\x72\x69\x66\x69\x63"
+       "\x61\x74\x69\x6f\x6e\x2e\x0a"
+};
+
+static const __initconst u8 certs_selftest_1_pkcs7[] = {
+       "\x30\x82\x02\xab\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x07\x02\xa0"
+       "\x82\x02\x9c\x30\x82\x02\x98\x02\x01\x01\x31\x0d\x30\x0b\x06\x09"
+       "\x60\x86\x48\x01\x65\x03\x04\x02\x01\x30\x0b\x06\x09\x2a\x86\x48"
+       "\x86\xf7\x0d\x01\x07\x01\x31\x82\x02\x75\x30\x82\x02\x71\x02\x01"
+       "\x01\x30\x4c\x30\x34\x31\x32\x30\x30\x06\x03\x55\x04\x03\x0c\x29"
+       "\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x76\x65\x72\x69"
+       "\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x73\x65\x6c\x66\x2d\x74\x65"
+       "\x73\x74\x69\x6e\x67\x20\x6b\x65\x79\x02\x14\x73\x98\xea\x98\x2d"
+       "\xd0\x2e\xa8\xb1\xcf\x57\xc7\xf2\x97\xb3\xe6\x1a\xfc\x8c\x0a\x30"
+       "\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x30\x0d\x06\x09"
+       "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x04\x82\x02\x00\xac"
+       "\xb0\xf2\x07\xd6\x99\x6d\xc0\xc0\xd9\x8d\x31\x0d\x7e\x04\xeb\xc3"
+       "\x88\x90\xc4\x58\x46\xd4\xe2\xa0\xa3\x25\xe3\x04\x50\x37\x85\x8c"
+       "\x91\xc6\xfc\xc5\xd4\x92\xfd\x05\xd8\xb8\xa3\xb8\xba\x89\x13\x00"
+       "\x88\x79\x99\x51\x6b\x5b\x28\x31\xc0\xb3\x1b\x7a\x68\x2c\x00\xdb"
+       "\x4b\x46\x11\xf3\xfa\x50\x8e\x19\x89\xa2\x4c\xda\x4c\x89\x01\x11"
+       "\x89\xee\xd3\xc8\xc1\xe7\xa7\xf6\xb2\xa2\xf8\x65\xb8\x35\x20\x33"
+       "\xba\x12\x62\xd5\xbd\xaa\x71\xe5\x5b\xc0\x6a\x32\xff\x6a\x2e\x23"
+       "\xef\x2b\xb6\x58\xb1\xfb\x5f\x82\x34\x40\x6d\x9f\xbc\x27\xac\x37"
+       "\x23\x99\xcf\x7d\x20\xb2\x39\x01\xc0\x12\xce\xd7\x5d\x2f\xb6\xab"
+       "\xb5\x56\x4f\xef\xf4\x72\x07\x58\x65\xa9\xeb\x1f\x75\x1c\x5f\x0c"
+       "\x88\xe0\xa4\xe2\xcd\x73\x2b\x9e\xb2\x05\x7e\x12\xf8\xd0\x66\x41"
+       "\xcc\x12\x63\xd4\xd6\xac\x9b\x1d\x14\x77\x8d\x1c\x57\xd5\x27\xc6"
+       "\x49\xa2\x41\x43\xf3\x59\x29\xe5\xcb\xd1\x75\xbc\x3a\x97\x2a\x72"
+       "\x22\x66\xc5\x3b\xc1\xba\xfc\x53\x18\x98\xe2\x21\x64\xc6\x52\x87"
+       "\x13\xd5\x7c\x42\xe8\xfb\x9c\x9a\x45\x32\xd5\xa5\x22\x62\x9d\xd4"
+       "\xcb\xa4\xfa\x77\xbb\x50\x24\x0b\x8b\x88\x99\x15\x56\xa9\x1e\x92"
+       "\xbf\x5d\x94\x77\xb6\xf1\x67\x01\x60\x06\x58\x5c\xdf\x18\x52\x79"
+       "\x37\x30\x93\x7d\x87\x04\xf1\xe0\x55\x59\x52\xf3\xc2\xb1\x1c\x5b"
+       "\x12\x7c\x49\x87\xfb\xf7\xed\xdd\x95\x71\xec\x4b\x1a\x85\x08\xb0"
+       "\xa0\x36\xc4\x7b\xab\x40\xe0\xf1\x98\xcc\xaf\x19\x40\x8f\x47\x6f"
+       "\xf0\x6c\x84\x29\x7f\x7f\x04\x46\xcb\x08\x0f\xe0\xc1\xc9\x70\x6e"
+       "\x95\x3b\xa4\xbc\x29\x2b\x53\x67\x45\x1b\x0d\xbc\x13\xa5\x76\x31"
+       "\xaf\xb9\xd0\xe0\x60\x12\xd2\xf4\xb7\x7c\x58\x7e\xf6\x2d\xbb\x24"
+       "\x14\x5a\x20\x24\xa8\x12\xdf\x25\xbd\x42\xce\x96\x7c\x2e\xba\x14"
+       "\x1b\x81\x9f\x18\x45\xa4\xc6\x70\x3e\x0e\xf0\xd3\x7b\x9c\x10\xbe"
+       "\xb8\x7a\x89\xc5\x9e\xd9\x97\xdf\xd7\xe7\xc6\x1d\xc0\x20\x6c\xb8"
+       "\x1e\x3a\x63\xb8\x39\x8e\x8e\x62\xd5\xd2\xb4\xcd\xff\x46\xfc\x8e"
+       "\xec\x07\x35\x0c\xff\xb0\x05\xe6\xf4\xe5\xfe\xa2\xe3\x0a\xe6\x36"
+       "\xa7\x4a\x7e\x62\x1d\xc4\x50\x39\x35\x4e\x28\xcb\x4a\xfb\x9d\xdb"
+       "\xdd\x23\xd6\x53\xb1\x74\x77\x12\xf7\x9c\xf0\x9a\x6b\xf7\xa9\x64"
+       "\x2d\x86\x21\x2a\xcf\xc6\x54\xf5\xc9\xad\xfa\xb5\x12\xb4\xf3\x51"
+       "\x77\x55\x3c\x6f\x0c\x32\xd3\x8c\x44\x39\x71\x25\xfe\x96\xd2"
+};
+
+/*
+ * List of tests to be run.
+ */
+#define TEST(data, pkcs7) { data, sizeof(data) - 1, pkcs7, sizeof(pkcs7) - 1 }
+static const struct certs_test certs_tests[] __initconst = {
+       TEST(certs_selftest_1_data, certs_selftest_1_pkcs7),
+};
+
+int __init fips_signature_selftest(void)
+{
+       struct key *keyring;
+       int ret, i;
+
+       pr_notice("Running certificate verification selftests\n");
+
+       keyring = keyring_alloc(".certs_selftest",
+                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ |
+                               KEY_USR_SEARCH,
+                               KEY_ALLOC_NOT_IN_QUOTA,
+                               NULL, NULL);
+       if (IS_ERR(keyring))
+               panic("Can't allocate certs selftest keyring: %ld\n",
+                     PTR_ERR(keyring));
+
+       ret = x509_load_certificate_list(certs_selftest_keys,
+                                        sizeof(certs_selftest_keys) - 1, keyring);
+       if (ret < 0)
+               panic("Can't allocate certs selftest keyring: %d\n", ret);
+
+       for (i = 0; i < ARRAY_SIZE(certs_tests); i++) {
+               const struct certs_test *test = &certs_tests[i];
+               struct pkcs7_message *pkcs7;
+
+               pkcs7 = pkcs7_parse_message(test->pkcs7, test->pkcs7_len);
+               if (IS_ERR(pkcs7))
+                       panic("Certs selftest %d: pkcs7_parse_message() = %d\n", i, ret);
+
+               pkcs7_supply_detached_data(pkcs7, test->data, test->data_len);
+
+               ret = pkcs7_verify(pkcs7, VERIFYING_MODULE_SIGNATURE);
+               if (ret < 0)
+                       panic("Certs selftest %d: pkcs7_verify() = %d\n", i, ret);
+
+               ret = pkcs7_validate_trust(pkcs7, keyring);
+               if (ret < 0)
+                       panic("Certs selftest %d: pkcs7_validate_trust() = %d\n", i, ret);
+
+               pkcs7_free_message(pkcs7);
+       }
+
+       key_put(keyring);
+       return 0;
+}
diff --git a/crypto/asymmetric_keys/x509_loader.c b/crypto/asymmetric_keys/x509_loader.c
new file mode 100644 (file)
index 0000000..1bc169d
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/key.h>
+#include <keys/asymmetric-type.h>
+
+int x509_load_certificate_list(const u8 cert_list[],
+                              const unsigned long list_size,
+                              const struct key *keyring)
+{
+       key_ref_t key;
+       const u8 *p, *end;
+       size_t plen;
+
+       p = cert_list;
+       end = p + list_size;
+       while (p < end) {
+               /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+                * than 256 bytes in size.
+                */
+               if (end - p < 4)
+                       goto dodgy_cert;
+               if (p[0] != 0x30 &&
+                   p[1] != 0x82)
+                       goto dodgy_cert;
+               plen = (p[2] << 8) | p[3];
+               plen += 4;
+               if (plen > end - p)
+                       goto dodgy_cert;
+
+               key = key_create_or_update(make_key_ref(keyring, 1),
+                                          "asymmetric",
+                                          NULL,
+                                          p,
+                                          plen,
+                                          ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                                          KEY_USR_VIEW | KEY_USR_READ),
+                                          KEY_ALLOC_NOT_IN_QUOTA |
+                                          KEY_ALLOC_BUILT_IN |
+                                          KEY_ALLOC_BYPASS_RESTRICTION);
+               if (IS_ERR(key)) {
+                       pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+                              PTR_ERR(key));
+               } else {
+                       pr_notice("Loaded X.509 cert '%s'\n",
+                                 key_ref_to_ptr(key)->description);
+                       key_ref_put(key);
+               }
+               p += plen;
+       }
+
+       return 0;
+
+dodgy_cert:
+       pr_err("Problem parsing in-kernel X.509 certificate list\n");
+       return 0;
+}
index 97a886c..a299c9c 100644 (file)
@@ -40,6 +40,15 @@ struct x509_certificate {
        bool            blacklisted;
 };
 
+/*
+ * selftest.c
+ */
+#ifdef CONFIG_FIPS_SIGNATURE_SELFTEST
+extern int __init fips_signature_selftest(void);
+#else
+static inline int fips_signature_selftest(void) { return 0; }
+#endif
+
 /*
  * x509_cert_parser.c
  */
index 77ed4e9..0b4943a 100644 (file)
@@ -244,9 +244,15 @@ static struct asymmetric_key_parser x509_key_parser = {
 /*
  * Module stuff
  */
+extern int __init certs_selftest(void);
 static int __init x509_key_init(void)
 {
-       return register_asymmetric_key_parser(&x509_key_parser);
+       int ret;
+
+       ret = register_asymmetric_key_parser(&x509_key_parser);
+       if (ret < 0)
+               return ret;
+       return fips_signature_selftest();
 }
 
 static void __exit x509_key_exit(void)
diff --git a/crypto/memneq.c b/crypto/memneq.c
deleted file mode 100644 (file)
index fb11608..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Constant-time equality testing of memory regions.
- *
- * Authors:
- *
- *   James Yonan <james@openvpn.net>
- *   Daniel Borkmann <dborkman@redhat.com>
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * BSD LICENSE
- *
- * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * 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.
- *   * Neither the name of OpenVPN Technologies nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
- * OWNER 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.
- */
-
-#include <crypto/algapi.h>
-#include <asm/unaligned.h>
-
-#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ
-
-/* Generic path for arbitrary size */
-static inline unsigned long
-__crypto_memneq_generic(const void *a, const void *b, size_t size)
-{
-       unsigned long neq = 0;
-
-#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-       while (size >= sizeof(unsigned long)) {
-               neq |= get_unaligned((unsigned long *)a) ^
-                      get_unaligned((unsigned long *)b);
-               OPTIMIZER_HIDE_VAR(neq);
-               a += sizeof(unsigned long);
-               b += sizeof(unsigned long);
-               size -= sizeof(unsigned long);
-       }
-#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
-       while (size > 0) {
-               neq |= *(unsigned char *)a ^ *(unsigned char *)b;
-               OPTIMIZER_HIDE_VAR(neq);
-               a += 1;
-               b += 1;
-               size -= 1;
-       }
-       return neq;
-}
-
-/* Loop-free fast-path for frequently used 16-byte size */
-static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
-{
-       unsigned long neq = 0;
-
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-       if (sizeof(unsigned long) == 8) {
-               neq |= get_unaligned((unsigned long *)a) ^
-                      get_unaligned((unsigned long *)b);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= get_unaligned((unsigned long *)(a + 8)) ^
-                      get_unaligned((unsigned long *)(b + 8));
-               OPTIMIZER_HIDE_VAR(neq);
-       } else if (sizeof(unsigned int) == 4) {
-               neq |= get_unaligned((unsigned int *)a) ^
-                      get_unaligned((unsigned int *)b);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= get_unaligned((unsigned int *)(a + 4)) ^
-                      get_unaligned((unsigned int *)(b + 4));
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= get_unaligned((unsigned int *)(a + 8)) ^
-                      get_unaligned((unsigned int *)(b + 8));
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= get_unaligned((unsigned int *)(a + 12)) ^
-                      get_unaligned((unsigned int *)(b + 12));
-               OPTIMIZER_HIDE_VAR(neq);
-       } else
-#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
-       {
-               neq |= *(unsigned char *)(a)    ^ *(unsigned char *)(b);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+1)  ^ *(unsigned char *)(b+1);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+2)  ^ *(unsigned char *)(b+2);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+3)  ^ *(unsigned char *)(b+3);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+4)  ^ *(unsigned char *)(b+4);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+5)  ^ *(unsigned char *)(b+5);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+6)  ^ *(unsigned char *)(b+6);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+7)  ^ *(unsigned char *)(b+7);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+8)  ^ *(unsigned char *)(b+8);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+9)  ^ *(unsigned char *)(b+9);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14);
-               OPTIMIZER_HIDE_VAR(neq);
-               neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15);
-               OPTIMIZER_HIDE_VAR(neq);
-       }
-
-       return neq;
-}
-
-/* Compare two areas of memory without leaking timing information,
- * and with special optimizations for common sizes.  Users should
- * not call this function directly, but should instead use
- * crypto_memneq defined in crypto/algapi.h.
- */
-noinline unsigned long __crypto_memneq(const void *a, const void *b,
-                                      size_t size)
-{
-       switch (size) {
-       case 16:
-               return __crypto_memneq_16(a, b);
-       default:
-               return __crypto_memneq_generic(a, b, size);
-       }
-}
-EXPORT_SYMBOL(__crypto_memneq);
-
-#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */
index 2ef23fc..a97776e 100644 (file)
@@ -564,6 +564,12 @@ ssize_t __weak cpu_show_srbds(struct device *dev,
        return sysfs_emit(buf, "Not affected\n");
 }
 
+ssize_t __weak cpu_show_mmio_stale_data(struct device *dev,
+                                       struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "Not affected\n");
+}
+
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
 static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
@@ -573,6 +579,7 @@ static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
 static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
 static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
 static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
+static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_meltdown.attr,
@@ -584,6 +591,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_tsx_async_abort.attr,
        &dev_attr_itlb_multihit.attr,
        &dev_attr_srbds.attr,
+       &dev_attr_mmio_stale_data.attr,
        NULL
 };
 
index d8d0fe6..397eb98 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/memory.h>
 #include <linux/of.h>
+#include <linux/backing-dev.h>
 
 #include "base.h"
 
@@ -20,6 +21,7 @@
 void __init driver_init(void)
 {
        /* These are the core pieces */
+       bdi_init(&noop_backing_dev_info);
        devtmpfs_init();
        devices_init();
        buses_init();
index e81a970..6143dbf 100644 (file)
@@ -1239,14 +1239,14 @@ error_cleanup_mc_io:
 static int fsl_mc_bus_remove(struct platform_device *pdev)
 {
        struct fsl_mc *mc = platform_get_drvdata(pdev);
+       struct fsl_mc_io *mc_io;
 
        if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
                return -EINVAL;
 
+       mc_io = mc->root_mc_bus_dev->mc_io;
        fsl_mc_device_remove(mc->root_mc_bus_dev);
-
-       fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
-       mc->root_mc_bus_dev->mc_io = NULL;
+       fsl_destroy_mc_io(mc_io);
 
        bus_unregister_notifier(&fsl_mc_bus_type, &fsl_mc_nb);
 
index 0e22e3b..38aad99 100644 (file)
@@ -1019,7 +1019,7 @@ static struct parport_driver lp_driver = {
 
 static int __init lp_init(void)
 {
-       int i, err = 0;
+       int i, err;
 
        if (parport_nr[0] == LP_PARPORT_OFF)
                return 0;
index 655e327..e3dd1dd 100644 (file)
@@ -87,7 +87,7 @@ static struct fasync_struct *fasync;
 
 /* Control how we warn userspace. */
 static struct ratelimit_state urandom_warning =
-       RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
+       RATELIMIT_STATE_INIT_FLAGS("urandom_warning", HZ, 3, RATELIMIT_MSG_ON_RELEASE);
 static int ratelimit_disable __read_mostly =
        IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
 module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
@@ -408,7 +408,7 @@ static ssize_t get_random_bytes_user(struct iov_iter *iter)
 
        /*
         * Immediately overwrite the ChaCha key at index 4 with random
-        * bytes, in case userspace causes copy_to_user() below to sleep
+        * bytes, in case userspace causes copy_to_iter() below to sleep
         * forever, so that we still retain forward secrecy in that case.
         */
        crng_make_state(chacha_state, (u8 *)&chacha_state[4], CHACHA_KEY_SIZE);
@@ -1009,7 +1009,7 @@ void add_interrupt_randomness(int irq)
        if (new_count & MIX_INFLIGHT)
                return;
 
-       if (new_count < 64 && !time_is_before_jiffies(fast_pool->last + HZ))
+       if (new_count < 1024 && !time_is_before_jiffies(fast_pool->last + HZ))
                return;
 
        if (unlikely(!fast_pool->mix.func))
index ff188ab..bb47610 100644 (file)
@@ -565,4 +565,3 @@ void __init hv_init_clocksource(void)
        hv_sched_clock_offset = hv_read_reference_counter();
        hv_setup_sched_clock(read_hv_sched_clock_msr);
 }
-EXPORT_SYMBOL_GPL(hv_init_clocksource);
index 46023ad..4536ed4 100644 (file)
@@ -684,7 +684,7 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev)
        if (!devpriv->usb_rx_buf)
                return -ENOMEM;
 
-       size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE);
+       size = max(usb_endpoint_maxp(devpriv->ep_tx), MIN_BUF_SIZE);
        devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL);
        if (!devpriv->usb_tx_buf)
                return -ENOMEM;
index e733068..9631f2f 100644 (file)
@@ -32,8 +32,11 @@ static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct udmabuf *ubuf = vma->vm_private_data;
+       pgoff_t pgoff = vmf->pgoff;
 
-       vmf->page = ubuf->pages[vmf->pgoff];
+       if (pgoff >= ubuf->pagecount)
+               return VM_FAULT_SIGBUS;
+       vmf->page = ubuf->pages[pgoff];
        get_page(vmf->page);
        return 0;
 }
index c9fe590..9c89f7d 100644 (file)
@@ -1211,7 +1211,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
        struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2;
        struct fw_card *card = client->device->card;
        struct timespec64 ts = {0, 0};
-       u32 cycle_time;
+       u32 cycle_time = 0;
        int ret = 0;
 
        local_irq_disable();
index 90ed8fd..adddd8c 100644 (file)
@@ -372,8 +372,7 @@ static ssize_t rom_index_show(struct device *dev,
        struct fw_device *device = fw_device(dev->parent);
        struct fw_unit *unit = fw_unit(dev);
 
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       (int)(unit->directory - device->config_rom));
+       return sysfs_emit(buf, "%td\n", unit->directory - device->config_rom);
 }
 
 static struct device_attribute fw_unit_attributes[] = {
@@ -403,8 +402,7 @@ static ssize_t guid_show(struct device *dev,
        int ret;
 
        down_read(&fw_device_rwsem);
-       ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
-                      device->config_rom[3], device->config_rom[4]);
+       ret = sysfs_emit(buf, "0x%08x%08x\n", device->config_rom[3], device->config_rom[4]);
        up_read(&fw_device_rwsem);
 
        return ret;
index 4c7c9dd..7882d4b 100644 (file)
@@ -26,8 +26,6 @@
 #include <linux/sysfb.h>
 #include <video/vga.h>
 
-#include <asm/efi.h>
-
 enum {
        OVERRIDE_NONE = 0x0,
        OVERRIDE_BASE = 0x1,
index 98cd715..8d09b61 100644 (file)
@@ -217,8 +217,6 @@ static int giu_get_irq(unsigned int irq)
        printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
               maskl, pendl, maskh, pendh);
 
-       atomic_inc(&irq_err_count);
-
        return -EINVAL;
 }
 
index 801f6fa..6de63ea 100644 (file)
@@ -642,7 +642,6 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                            atomic64_read(&adev->visible_pin_size),
                            vram_gtt.vram_size);
                vram_gtt.gtt_size = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT)->size;
-               vram_gtt.gtt_size *= PAGE_SIZE;
                vram_gtt.gtt_size -= atomic64_read(&adev->gart_pin_size);
                return copy_to_user(out, &vram_gtt,
                                    min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0;
@@ -675,7 +674,6 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        mem.cpu_accessible_vram.usable_heap_size * 3 / 4;
 
                mem.gtt.total_heap_size = gtt_man->size;
-               mem.gtt.total_heap_size *= PAGE_SIZE;
                mem.gtt.usable_heap_size = mem.gtt.total_heap_size -
                        atomic64_read(&adev->gart_pin_size);
                mem.gtt.heap_usage = ttm_resource_manager_usage(gtt_man);
index 70be67a..39b425d 100644 (file)
@@ -2812,7 +2812,7 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
 
 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 {
-       u32 max_cll, min_cll, max, min, q, r;
+       u32 max_avg, min_cll, max, min, q, r;
        struct amdgpu_dm_backlight_caps *caps;
        struct amdgpu_display_manager *dm;
        struct drm_connector *conn_base;
@@ -2842,7 +2842,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        caps = &dm->backlight_caps[i];
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
-       max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
+       max_avg = conn_base->hdr_sink_metadata.hdmi_type1.max_fall;
        min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll;
 
        if (caps->ext_caps->bits.oled == 1 /*||
@@ -2870,8 +2870,8 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
         * The results of the above expressions can be verified at
         * pre_computed_values.
         */
-       q = max_cll >> 5;
-       r = max_cll % 32;
+       q = max_avg >> 5;
+       r = max_avg % 32;
        max = (1 << q) * pre_computed_values[r];
 
        // min luminance: maxLum * (CV/255)^2 / 100
index 424ea23..16c5396 100644 (file)
@@ -176,15 +176,15 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = {
        }, {
                DRV_PTR(mixer_driver, CONFIG_DRM_EXYNOS_MIXER),
                DRM_COMPONENT_DRIVER
-       }, {
-               DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
-               DRM_COMPONENT_DRIVER
        }, {
                DRV_PTR(dp_driver, CONFIG_DRM_EXYNOS_DP),
                DRM_COMPONENT_DRIVER
        }, {
                DRV_PTR(dsi_driver, CONFIG_DRM_EXYNOS_DSI),
                DRM_COMPONENT_DRIVER
+       }, {
+               DRV_PTR(mic_driver, CONFIG_DRM_EXYNOS_MIC),
+               DRM_COMPONENT_DRIVER
        }, {
                DRV_PTR(hdmi_driver, CONFIG_DRM_EXYNOS_HDMI),
                DRM_COMPONENT_DRIVER
index 9e06f8e..09ce28e 100644 (file)
@@ -26,6 +26,7 @@
 #include <drm/drm_print.h>
 
 #include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
 
 /* Sysreg registers for MIC */
 #define DSD_CFG_MUX    0x1004
@@ -100,9 +101,7 @@ struct exynos_mic {
 
        bool i80_mode;
        struct videomode vm;
-       struct drm_encoder *encoder;
        struct drm_bridge bridge;
-       struct drm_bridge *next_bridge;
 
        bool enabled;
 };
@@ -229,8 +228,6 @@ static void mic_set_reg_on(struct exynos_mic *mic, bool enable)
        writel(reg, mic->reg + MIC_OP);
 }
 
-static void mic_disable(struct drm_bridge *bridge) { }
-
 static void mic_post_disable(struct drm_bridge *bridge)
 {
        struct exynos_mic *mic = bridge->driver_private;
@@ -297,34 +294,30 @@ unlock:
        mutex_unlock(&mic_mutex);
 }
 
-static void mic_enable(struct drm_bridge *bridge) { }
-
-static int mic_attach(struct drm_bridge *bridge,
-                     enum drm_bridge_attach_flags flags)
-{
-       struct exynos_mic *mic = bridge->driver_private;
-
-       return drm_bridge_attach(bridge->encoder, mic->next_bridge,
-                                &mic->bridge, flags);
-}
-
 static const struct drm_bridge_funcs mic_bridge_funcs = {
-       .disable = mic_disable,
        .post_disable = mic_post_disable,
        .mode_set = mic_mode_set,
        .pre_enable = mic_pre_enable,
-       .enable = mic_enable,
-       .attach = mic_attach,
 };
 
 static int exynos_mic_bind(struct device *dev, struct device *master,
                           void *data)
 {
        struct exynos_mic *mic = dev_get_drvdata(dev);
+       struct drm_device *drm_dev = data;
+       struct exynos_drm_crtc *crtc = exynos_drm_crtc_get_by_type(drm_dev,
+                                                      EXYNOS_DISPLAY_TYPE_LCD);
+       struct drm_encoder *e, *encoder = NULL;
+
+       drm_for_each_encoder(e, drm_dev)
+               if (e->possible_crtcs == drm_crtc_mask(&crtc->base))
+                       encoder = e;
+       if (!encoder)
+               return -ENODEV;
 
        mic->bridge.driver_private = mic;
 
-       return 0;
+       return drm_bridge_attach(encoder, &mic->bridge, NULL, 0);
 }
 
 static void exynos_mic_unbind(struct device *dev, struct device *master,
@@ -388,7 +381,6 @@ static int exynos_mic_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos_mic *mic;
-       struct device_node *remote;
        struct resource res;
        int ret, i;
 
@@ -432,16 +424,6 @@ static int exynos_mic_probe(struct platform_device *pdev)
                }
        }
 
-       remote = of_graph_get_remote_node(dev->of_node, 1, 0);
-       mic->next_bridge = of_drm_find_bridge(remote);
-       if (IS_ERR(mic->next_bridge)) {
-               DRM_DEV_ERROR(dev, "mic: Failed to find next bridge\n");
-               ret = PTR_ERR(mic->next_bridge);
-               goto err;
-       }
-
-       of_node_put(remote);
-
        platform_set_drvdata(pdev, mic);
 
        mic->bridge.funcs = &mic_bridge_funcs;
index c326bd2..30fe847 100644 (file)
@@ -999,7 +999,8 @@ static int eb_validate_vmas(struct i915_execbuffer *eb)
                        }
                }
 
-               err = dma_resv_reserve_fences(vma->obj->base.resv, 1);
+               /* Reserve enough slots to accommodate composite fences */
+               err = dma_resv_reserve_fences(vma->obj->base.resv, eb->num_batches);
                if (err)
                        return err;
 
index 53307ca..51a0fe6 100644 (file)
@@ -785,6 +785,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt)
 {
        intel_wakeref_t wakeref;
 
+       intel_gt_sysfs_unregister(gt);
        intel_rps_driver_unregister(&gt->rps);
        intel_gsc_fini(&gt->gsc);
 
index 8ec8bc6..9e4ebf5 100644 (file)
@@ -24,7 +24,7 @@ bool is_object_gt(struct kobject *kobj)
 
 static struct intel_gt *kobj_to_gt(struct kobject *kobj)
 {
-       return container_of(kobj, struct kobj_gt, base)->gt;
+       return container_of(kobj, struct intel_gt, sysfs_gt);
 }
 
 struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
@@ -72,9 +72,9 @@ static struct attribute *id_attrs[] = {
 };
 ATTRIBUTE_GROUPS(id);
 
+/* A kobject needs a release() method even if it does nothing */
 static void kobj_gt_release(struct kobject *kobj)
 {
-       kfree(kobj);
 }
 
 static struct kobj_type kobj_gt_type = {
@@ -85,8 +85,6 @@ static struct kobj_type kobj_gt_type = {
 
 void intel_gt_sysfs_register(struct intel_gt *gt)
 {
-       struct kobj_gt *kg;
-
        /*
         * We need to make things right with the
         * ABI compatibility. The files were originally
@@ -98,25 +96,22 @@ void intel_gt_sysfs_register(struct intel_gt *gt)
        if (gt_is_root(gt))
                intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
 
-       kg = kzalloc(sizeof(*kg), GFP_KERNEL);
-       if (!kg)
+       /* init and xfer ownership to sysfs tree */
+       if (kobject_init_and_add(&gt->sysfs_gt, &kobj_gt_type,
+                                gt->i915->sysfs_gt, "gt%d", gt->info.id))
                goto exit_fail;
 
-       kobject_init(&kg->base, &kobj_gt_type);
-       kg->gt = gt;
-
-       /* xfer ownership to sysfs tree */
-       if (kobject_add(&kg->base, gt->i915->sysfs_gt, "gt%d", gt->info.id))
-               goto exit_kobj_put;
-
-       intel_gt_sysfs_pm_init(gt, &kg->base);
+       intel_gt_sysfs_pm_init(gt, &gt->sysfs_gt);
 
        return;
 
-exit_kobj_put:
-       kobject_put(&kg->base);
-
 exit_fail:
+       kobject_put(&gt->sysfs_gt);
        drm_warn(&gt->i915->drm,
                 "failed to initialize gt%d sysfs root\n", gt->info.id);
 }
+
+void intel_gt_sysfs_unregister(struct intel_gt *gt)
+{
+       kobject_put(&gt->sysfs_gt);
+}
index 9471b26..a99aa7e 100644 (file)
 
 struct intel_gt;
 
-struct kobj_gt {
-       struct kobject base;
-       struct intel_gt *gt;
-};
-
 bool is_object_gt(struct kobject *kobj);
 
 struct drm_i915_private *kobj_to_i915(struct kobject *kobj);
@@ -28,6 +23,7 @@ intel_gt_create_kobj(struct intel_gt *gt,
                     const char *name);
 
 void intel_gt_sysfs_register(struct intel_gt *gt);
+void intel_gt_sysfs_unregister(struct intel_gt *gt);
 struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
                                            const char *name);
 
index b06611c..edd7a3c 100644 (file)
@@ -224,6 +224,9 @@ struct intel_gt {
        } mocs;
 
        struct intel_pxp pxp;
+
+       /* gt/gtN sysfs */
+       struct kobject sysfs_gt;
 };
 
 enum intel_gt_scratch_field {
index d078f88..f0d7b57 100644 (file)
@@ -156,7 +156,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
                [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) },
                [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) },
        };
-       static const struct uc_fw_platform_requirement *fw_blobs;
+       const struct uc_fw_platform_requirement *fw_blobs;
        enum intel_platform p = INTEL_INFO(i915)->platform;
        u32 fw_count;
        u8 rev = INTEL_REVID(i915);
index 8521dab..1e27502 100644 (file)
@@ -166,7 +166,14 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
        struct device *kdev = kobj_to_dev(kobj);
        struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
        struct i915_gpu_coredump *gpu;
-       ssize_t ret;
+       ssize_t ret = 0;
+
+       /*
+        * FIXME: Concurrent clients triggering resets and reading + clearing
+        * dumps can cause inconsistent sysfs reads when a user calls in with a
+        * non-zero offset to complete a prior partial read but the
+        * gpu_coredump has been cleared or replaced.
+        */
 
        gpu = i915_first_error_state(i915);
        if (IS_ERR(gpu)) {
@@ -178,8 +185,10 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
                const char *str = "No error state collected\n";
                size_t len = strlen(str);
 
-               ret = min_t(size_t, count, len - off);
-               memcpy(buf, str + off, ret);
+               if (off < len) {
+                       ret = min_t(size_t, count, len - off);
+                       memcpy(buf, str + off, ret);
+               }
        }
 
        return ret;
@@ -259,4 +268,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
 
        device_remove_bin_file(kdev,  &dpf_attrs_1);
        device_remove_bin_file(kdev,  &dpf_attrs);
+
+       kobject_put(dev_priv->sysfs_gt);
 }
index 4f6db53..0bffb70 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/sched/mm.h>
+#include <linux/dma-fence-array.h>
 #include <drm/drm_gem.h>
 
 #include "display/intel_frontbuffer.h"
@@ -1823,6 +1824,21 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
        if (unlikely(err))
                return err;
 
+       /*
+        * Reserve fences slot early to prevent an allocation after preparing
+        * the workload and associating fences with dma_resv.
+        */
+       if (fence && !(flags & __EXEC_OBJECT_NO_RESERVE)) {
+               struct dma_fence *curr;
+               int idx;
+
+               dma_fence_array_for_each(curr, idx, fence)
+                       ;
+               err = dma_resv_reserve_fences(vma->obj->base.resv, idx);
+               if (unlikely(err))
+                       return err;
+       }
+
        if (flags & EXEC_OBJECT_WRITE) {
                struct intel_frontbuffer *front;
 
@@ -1832,31 +1848,23 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
                                i915_active_add_request(&front->write, rq);
                        intel_frontbuffer_put(front);
                }
+       }
 
-               if (!(flags & __EXEC_OBJECT_NO_RESERVE)) {
-                       err = dma_resv_reserve_fences(vma->obj->base.resv, 1);
-                       if (unlikely(err))
-                               return err;
-               }
+       if (fence) {
+               struct dma_fence *curr;
+               enum dma_resv_usage usage;
+               int idx;
 
-               if (fence) {
-                       dma_resv_add_fence(vma->obj->base.resv, fence,
-                                          DMA_RESV_USAGE_WRITE);
+               obj->read_domains = 0;
+               if (flags & EXEC_OBJECT_WRITE) {
+                       usage = DMA_RESV_USAGE_WRITE;
                        obj->write_domain = I915_GEM_DOMAIN_RENDER;
-                       obj->read_domains = 0;
-               }
-       } else {
-               if (!(flags & __EXEC_OBJECT_NO_RESERVE)) {
-                       err = dma_resv_reserve_fences(vma->obj->base.resv, 1);
-                       if (unlikely(err))
-                               return err;
+               } else {
+                       usage = DMA_RESV_USAGE_READ;
                }
 
-               if (fence) {
-                       dma_resv_add_fence(vma->obj->base.resv, fence,
-                                          DMA_RESV_USAGE_READ);
-                       obj->write_domain = 0;
-               }
+               dma_fence_array_for_each(curr, idx, fence)
+                       dma_resv_add_fence(vma->obj->base.resv, curr, usage);
        }
 
        if (flags & EXEC_OBJECT_NEEDS_FENCE && vma->fence)
index 75d308e..406e9c3 100644 (file)
@@ -109,11 +109,11 @@ void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo,
                return;
 
        spin_lock(&bo->bdev->lru_lock);
-       if (bo->bulk_move && bo->resource)
-               ttm_lru_bulk_move_del(bo->bulk_move, bo->resource);
+       if (bo->resource)
+               ttm_resource_del_bulk_move(bo->resource, bo);
        bo->bulk_move = bulk;
-       if (bo->bulk_move && bo->resource)
-               ttm_lru_bulk_move_add(bo->bulk_move, bo->resource);
+       if (bo->resource)
+               ttm_resource_add_bulk_move(bo->resource, bo);
        spin_unlock(&bo->bdev->lru_lock);
 }
 EXPORT_SYMBOL(ttm_bo_set_bulk_move);
@@ -689,8 +689,11 @@ void ttm_bo_pin(struct ttm_buffer_object *bo)
 {
        dma_resv_assert_held(bo->base.resv);
        WARN_ON_ONCE(!kref_read(&bo->kref));
-       if (!(bo->pin_count++) && bo->bulk_move && bo->resource)
-               ttm_lru_bulk_move_del(bo->bulk_move, bo->resource);
+       spin_lock(&bo->bdev->lru_lock);
+       if (bo->resource)
+               ttm_resource_del_bulk_move(bo->resource, bo);
+       ++bo->pin_count;
+       spin_unlock(&bo->bdev->lru_lock);
 }
 EXPORT_SYMBOL(ttm_bo_pin);
 
@@ -707,8 +710,11 @@ void ttm_bo_unpin(struct ttm_buffer_object *bo)
        if (WARN_ON_ONCE(!bo->pin_count))
                return;
 
-       if (!(--bo->pin_count) && bo->bulk_move && bo->resource)
-               ttm_lru_bulk_move_add(bo->bulk_move, bo->resource);
+       spin_lock(&bo->bdev->lru_lock);
+       --bo->pin_count;
+       if (bo->resource)
+               ttm_resource_add_bulk_move(bo->resource, bo);
+       spin_unlock(&bo->bdev->lru_lock);
 }
 EXPORT_SYMBOL(ttm_bo_unpin);
 
index a0562ab..e7147e3 100644 (file)
@@ -156,8 +156,12 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,
 
                ttm_resource_manager_for_each_res(man, &cursor, res) {
                        struct ttm_buffer_object *bo = res->bo;
-                       uint32_t num_pages = PFN_UP(bo->base.size);
+                       uint32_t num_pages;
 
+                       if (!bo)
+                               continue;
+
+                       num_pages = PFN_UP(bo->base.size);
                        ret = ttm_bo_swapout(bo, ctx, gfp_flags);
                        /* ttm_bo_swapout has dropped the lru_lock */
                        if (!ret)
index 65889b3..20f9adc 100644 (file)
@@ -91,8 +91,8 @@ static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos,
 }
 
 /* Add the resource to a bulk_move cursor */
-void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk,
-                          struct ttm_resource *res)
+static void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk,
+                                 struct ttm_resource *res)
 {
        struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
 
@@ -105,8 +105,8 @@ void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk,
 }
 
 /* Remove the resource from a bulk_move range */
-void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
-                          struct ttm_resource *res)
+static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
+                                 struct ttm_resource *res)
 {
        struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
 
@@ -122,6 +122,22 @@ void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
        }
 }
 
+/* Add the resource to a bulk move if the BO is configured for it */
+void ttm_resource_add_bulk_move(struct ttm_resource *res,
+                               struct ttm_buffer_object *bo)
+{
+       if (bo->bulk_move && !bo->pin_count)
+               ttm_lru_bulk_move_add(bo->bulk_move, res);
+}
+
+/* Remove the resource from a bulk move if the BO is configured for it */
+void ttm_resource_del_bulk_move(struct ttm_resource *res,
+                               struct ttm_buffer_object *bo)
+{
+       if (bo->bulk_move && !bo->pin_count)
+               ttm_lru_bulk_move_del(bo->bulk_move, res);
+}
+
 /* Move a resource to the LRU or bulk tail */
 void ttm_resource_move_to_lru_tail(struct ttm_resource *res)
 {
@@ -169,15 +185,14 @@ void ttm_resource_init(struct ttm_buffer_object *bo,
        res->bus.is_iomem = false;
        res->bus.caching = ttm_cached;
        res->bo = bo;
-       INIT_LIST_HEAD(&res->lru);
 
        man = ttm_manager_type(bo->bdev, place->mem_type);
        spin_lock(&bo->bdev->lru_lock);
-       man->usage += res->num_pages << PAGE_SHIFT;
-       if (bo->bulk_move)
-               ttm_lru_bulk_move_add(bo->bulk_move, res);
+       if (bo->pin_count)
+               list_add_tail(&res->lru, &bo->bdev->pinned);
        else
-               ttm_resource_move_to_lru_tail(res);
+               list_add_tail(&res->lru, &man->lru[bo->priority]);
+       man->usage += res->num_pages << PAGE_SHIFT;
        spin_unlock(&bo->bdev->lru_lock);
 }
 EXPORT_SYMBOL(ttm_resource_init);
@@ -210,8 +225,16 @@ int ttm_resource_alloc(struct ttm_buffer_object *bo,
 {
        struct ttm_resource_manager *man =
                ttm_manager_type(bo->bdev, place->mem_type);
+       int ret;
+
+       ret = man->func->alloc(man, bo, place, res_ptr);
+       if (ret)
+               return ret;
 
-       return man->func->alloc(man, bo, place, res_ptr);
+       spin_lock(&bo->bdev->lru_lock);
+       ttm_resource_add_bulk_move(*res_ptr, bo);
+       spin_unlock(&bo->bdev->lru_lock);
+       return 0;
 }
 
 void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res)
@@ -221,12 +244,9 @@ void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res)
        if (!*res)
                return;
 
-       if (bo->bulk_move) {
-               spin_lock(&bo->bdev->lru_lock);
-               ttm_lru_bulk_move_del(bo->bulk_move, *res);
-               spin_unlock(&bo->bdev->lru_lock);
-       }
-
+       spin_lock(&bo->bdev->lru_lock);
+       ttm_resource_del_bulk_move(*res, bo);
+       spin_unlock(&bo->bdev->lru_lock);
        man = ttm_manager_type(bo->bdev, (*res)->mem_type);
        man->func->free(man, *res);
        *res = NULL;
index 978ee2a..e0bc731 100644 (file)
@@ -199,7 +199,8 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
        if (!input_device->hid_desc)
                goto cleanup;
 
-       input_device->report_desc_size = desc->desc[0].wDescriptorLength;
+       input_device->report_desc_size = le16_to_cpu(
+                                       desc->desc[0].wDescriptorLength);
        if (input_device->report_desc_size == 0) {
                input_device->dev_info_status = -EINVAL;
                goto cleanup;
@@ -217,7 +218,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
 
        memcpy(input_device->report_desc,
               ((unsigned char *)desc) + desc->bLength,
-              desc->desc[0].wDescriptorLength);
+              le16_to_cpu(desc->desc[0].wDescriptorLength));
 
        /* Send the ack */
        memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
index b60f134..5b12040 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/cpu.h>
 #include <linux/hyperv.h>
 #include <asm/mshyperv.h>
+#include <linux/sched/isolation.h>
 
 #include "hyperv_vmbus.h"
 
@@ -638,6 +639,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
                 */
                if (newchannel->offermsg.offer.sub_channel_index == 0) {
                        mutex_unlock(&vmbus_connection.channel_mutex);
+                       cpus_read_unlock();
                        /*
                         * Don't call free_channel(), because newchannel->kobj
                         * is not initialized yet.
@@ -728,16 +730,20 @@ static void init_vp_index(struct vmbus_channel *channel)
        u32 i, ncpu = num_online_cpus();
        cpumask_var_t available_mask;
        struct cpumask *allocated_mask;
+       const struct cpumask *hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
        u32 target_cpu;
        int numa_node;
 
        if (!perf_chn ||
-           !alloc_cpumask_var(&available_mask, GFP_KERNEL)) {
+           !alloc_cpumask_var(&available_mask, GFP_KERNEL) ||
+           cpumask_empty(hk_mask)) {
                /*
                 * If the channel is not a performance critical
                 * channel, bind it to VMBUS_CONNECT_CPU.
                 * In case alloc_cpumask_var() fails, bind it to
                 * VMBUS_CONNECT_CPU.
+                * If all the cpus are isolated, bind it to
+                * VMBUS_CONNECT_CPU.
                 */
                channel->target_cpu = VMBUS_CONNECT_CPU;
                if (perf_chn)
@@ -758,17 +764,19 @@ static void init_vp_index(struct vmbus_channel *channel)
                }
                allocated_mask = &hv_context.hv_numa_map[numa_node];
 
-               if (cpumask_equal(allocated_mask, cpumask_of_node(numa_node))) {
+retry:
+               cpumask_xor(available_mask, allocated_mask, cpumask_of_node(numa_node));
+               cpumask_and(available_mask, available_mask, hk_mask);
+
+               if (cpumask_empty(available_mask)) {
                        /*
                         * We have cycled through all the CPUs in the node;
                         * reset the allocated map.
                         */
                        cpumask_clear(allocated_mask);
+                       goto retry;
                }
 
-               cpumask_xor(available_mask, allocated_mask,
-                           cpumask_of_node(numa_node));
-
                target_cpu = cpumask_first(available_mask);
                cpumask_set_cpu(target_cpu, allocated_mask);
 
index c698592..d35b60c 100644 (file)
@@ -394,7 +394,7 @@ kvp_send_key(struct work_struct *dummy)
        in_msg = kvp_transaction.kvp_msg;
 
        /*
-        * The key/value strings sent from the host are encoded in
+        * The key/value strings sent from the host are encoded
         * in utf16; convert it to utf8 strings.
         * The host assures us that the utf16 strings will not exceed
         * the max lengths specified. We will however, reserve room
index 714d549..547ae33 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/clockchips.h>
 #include <linux/cpu.h>
+#include <linux/sched/isolation.h>
 #include <linux/sched/task_stack.h>
 
 #include <linux/delay.h>
@@ -1770,6 +1771,9 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
        if (target_cpu >= nr_cpumask_bits)
                return -EINVAL;
 
+       if (!cpumask_test_cpu(target_cpu, housekeeping_cpumask(HK_TYPE_MANAGED_IRQ)))
+               return -EINVAL;
+
        /* No CPUs should come up or down during this. */
        cpus_read_lock();
 
index 57e11b2..3633ab6 100644 (file)
@@ -259,7 +259,7 @@ static const struct ec_board_info board_info[] = {
        },
        {
                .board_names = {
-                       "ROG CROSSHAIR VIII FORMULA"
+                       "ROG CROSSHAIR VIII FORMULA",
                        "ROG CROSSHAIR VIII HERO",
                        "ROG CROSSHAIR VIII HERO (WI-FI)",
                },
index d78f4be..ea070b9 100644 (file)
@@ -1228,10 +1228,15 @@ EXPORT_SYMBOL_GPL(occ_setup);
 
 void occ_shutdown(struct occ *occ)
 {
+       mutex_lock(&occ->lock);
+
        occ_shutdown_sysfs(occ);
 
        if (occ->hwmon)
                hwmon_device_unregister(occ->hwmon);
+       occ->hwmon = NULL;
+
+       mutex_unlock(&occ->lock);
 }
 EXPORT_SYMBOL_GPL(occ_shutdown);
 
index e7d316b..c023b69 100644 (file)
@@ -477,9 +477,6 @@ int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare)
 {
        int ret;
 
-       if (IS_ERR(dev->clk))
-               return PTR_ERR(dev->clk);
-
        if (prepare) {
                /* Optional interface clock */
                ret = clk_prepare_enable(dev->pclk);
index 70ade53..ba043b5 100644 (file)
@@ -320,8 +320,17 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
                goto exit_reset;
        }
 
-       dev->clk = devm_clk_get(&pdev->dev, NULL);
-       if (!i2c_dw_prepare_clk(dev, true)) {
+       dev->clk = devm_clk_get_optional(&pdev->dev, NULL);
+       if (IS_ERR(dev->clk)) {
+               ret = PTR_ERR(dev->clk);
+               goto exit_reset;
+       }
+
+       ret = i2c_dw_prepare_clk(dev, true);
+       if (ret)
+               goto exit_reset;
+
+       if (dev->clk) {
                u64 clk_khz;
 
                dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
index bdecb78..8e69853 100644 (file)
@@ -1420,17 +1420,22 @@ static int mtk_i2c_probe(struct platform_device *pdev)
        if (ret < 0) {
                dev_err(&pdev->dev,
                        "Request I2C IRQ %d fail\n", irq);
-               return ret;
+               goto err_bulk_unprepare;
        }
 
        i2c_set_adapdata(&i2c->adap, i2c);
        ret = i2c_add_adapter(&i2c->adap);
        if (ret)
-               return ret;
+               goto err_bulk_unprepare;
 
        platform_set_drvdata(pdev, i2c);
 
        return 0;
+
+err_bulk_unprepare:
+       clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
+
+       return ret;
 }
 
 static int mtk_i2c_remove(struct platform_device *pdev)
index 5960ccd..aede9d5 100644 (file)
@@ -2372,8 +2372,7 @@ static struct platform_driver npcm_i2c_bus_driver = {
 static int __init npcm_i2c_init(void)
 {
        npcm_i2c_debugfs_dir = debugfs_create_dir("npcm_i2c", NULL);
-       platform_driver_register(&npcm_i2c_bus_driver);
-       return 0;
+       return platform_driver_register(&npcm_i2c_bus_driver);
 }
 module_init(npcm_i2c_init);
 
index 4ab1038..1f23a6b 100644 (file)
@@ -298,7 +298,7 @@ config XTENSA_MX
 
 config XILINX_INTC
        bool "Xilinx Interrupt Controller IP"
-       depends on MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP
+       depends on OF
        select IRQ_DOMAIN
        help
          Support for the Xilinx Interrupt Controller IP core.
index 12dd487..5ac8318 100644 (file)
@@ -1035,6 +1035,7 @@ static void build_fiq_affinity(struct aic_irq_chip *ic, struct device_node *aff)
                        continue;
 
                cpu = of_cpu_node_to_id(cpu_node);
+               of_node_put(cpu_node);
                if (WARN_ON(cpu < 0))
                        continue;
 
@@ -1143,6 +1144,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
                for_each_child_of_node(affs, chld)
                        build_fiq_affinity(irqc, chld);
        }
+       of_node_put(affs);
 
        set_handle_irq(aic_handle_irq);
        set_handle_fiq(aic_handle_fiq);
index b4c1924..38fab02 100644 (file)
@@ -57,6 +57,7 @@ realview_gic_of_init(struct device_node *node, struct device_node *parent)
 
        /* The PB11MPCore GIC needs to be configured in the syscon */
        map = syscon_node_to_regmap(np);
+       of_node_put(np);
        if (!IS_ERR(map)) {
                /* new irq mode with no DCC */
                regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
index 2be8dea..5c1cf90 100644 (file)
@@ -1932,7 +1932,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
 
        gic_data.ppi_descs = kcalloc(gic_data.ppi_nr, sizeof(*gic_data.ppi_descs), GFP_KERNEL);
        if (!gic_data.ppi_descs)
-               return;
+               goto out_put_node;
 
        nr_parts = of_get_child_count(parts_node);
 
@@ -1973,12 +1973,15 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
                                continue;
 
                        cpu = of_cpu_node_to_id(cpu_node);
-                       if (WARN_ON(cpu < 0))
+                       if (WARN_ON(cpu < 0)) {
+                               of_node_put(cpu_node);
                                continue;
+                       }
 
                        pr_cont("%pOF[%d] ", cpu_node, cpu);
 
                        cpumask_set_cpu(cpu, &part->mask);
+                       of_node_put(cpu_node);
                }
 
                pr_cont("}\n");
index aed8885..8d05d8b 100644 (file)
 
 #define LIOINTC_ERRATA_IRQ     10
 
+#if defined(CONFIG_MIPS)
+#define liointc_core_id get_ebase_cpunum()
+#else
+#define liointc_core_id get_csr_cpuid()
+#endif
+
 struct liointc_handler_data {
        struct liointc_priv     *priv;
        u32                     parent_int_map;
@@ -57,7 +63,7 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)
        struct liointc_handler_data *handler = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irq_chip_generic *gc = handler->priv->gc;
-       int core = cpu_logical_map(smp_processor_id()) % LIOINTC_NUM_CORES;
+       int core = liointc_core_id % LIOINTC_NUM_CORES;
        u32 pending;
 
        chained_irq_enter(chip, desc);
index 50a5682..56bf502 100644 (file)
@@ -134,9 +134,9 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do
                if (!cpu_ictl)
                        return -EINVAL;
                ret = of_property_read_u32(cpu_ictl, "#interrupt-cells", &tmp);
+               of_node_put(cpu_ictl);
                if (ret || tmp != 1)
                        return -EINVAL;
-               of_node_put(cpu_ictl);
 
                cpu_int = be32_to_cpup(imap + 2);
                if (cpu_int > 7 || cpu_int < 2)
index 89121b3..716b1bb 100644 (file)
@@ -237,6 +237,7 @@ static const struct of_device_id uniphier_aidet_match[] = {
        { .compatible = "socionext,uniphier-ld11-aidet" },
        { .compatible = "socionext,uniphier-ld20-aidet" },
        { .compatible = "socionext,uniphier-pxs3-aidet" },
+       { .compatible = "socionext,uniphier-nx1-aidet" },
        { /* sentinel */ }
 };
 
index 06f3289..2dda05a 100644 (file)
@@ -415,8 +415,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
        /*
         * Work out how many "unsigned long"s we need to hold the bitset.
         */
-       bitset_size = dm_round_up(region_count,
-                                 sizeof(*lc->clean_bits) << BYTE_SHIFT);
+       bitset_size = dm_round_up(region_count, BITS_PER_LONG);
        bitset_size >>= BYTE_SHIFT;
 
        lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits);
index 5e41fba..9526ccb 100644 (file)
@@ -3725,7 +3725,7 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
        if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
                if (mddev->sync_thread) {
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-                       md_reap_sync_thread(mddev, false);
+                       md_reap_sync_thread(mddev);
                }
        } else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
                return -EBUSY;
index d8f1618..b6b25d3 100644 (file)
@@ -555,6 +555,10 @@ static void dm_start_io_acct(struct dm_io *io, struct bio *clone)
                unsigned long flags;
                /* Can afford locking given DM_TIO_IS_DUPLICATE_BIO */
                spin_lock_irqsave(&io->lock, flags);
+               if (dm_io_flagged(io, DM_IO_ACCOUNTED)) {
+                       spin_unlock_irqrestore(&io->lock, flags);
+                       return;
+               }
                dm_io_set_flag(io, DM_IO_ACCOUNTED);
                spin_unlock_irqrestore(&io->lock, flags);
        }
@@ -711,18 +715,18 @@ static void dm_put_live_table_fast(struct mapped_device *md) __releases(RCU)
 }
 
 static inline struct dm_table *dm_get_live_table_bio(struct mapped_device *md,
-                                                    int *srcu_idx, struct bio *bio)
+                                                    int *srcu_idx, unsigned bio_opf)
 {
-       if (bio->bi_opf & REQ_NOWAIT)
+       if (bio_opf & REQ_NOWAIT)
                return dm_get_live_table_fast(md);
        else
                return dm_get_live_table(md, srcu_idx);
 }
 
 static inline void dm_put_live_table_bio(struct mapped_device *md, int srcu_idx,
-                                        struct bio *bio)
+                                        unsigned bio_opf)
 {
-       if (bio->bi_opf & REQ_NOWAIT)
+       if (bio_opf & REQ_NOWAIT)
                dm_put_live_table_fast(md);
        else
                dm_put_live_table(md, srcu_idx);
@@ -1609,7 +1613,12 @@ static blk_status_t __split_and_process_bio(struct clone_info *ci)
        ti = dm_table_find_target(ci->map, ci->sector);
        if (unlikely(!ti))
                return BLK_STS_IOERR;
-       else if (unlikely(ci->is_abnormal_io))
+
+       if (unlikely((ci->bio->bi_opf & REQ_NOWAIT) != 0) &&
+           unlikely(!dm_target_supports_nowait(ti->type)))
+               return BLK_STS_NOTSUPP;
+
+       if (unlikely(ci->is_abnormal_io))
                return __process_abnormal_io(ci, ti);
 
        /*
@@ -1711,8 +1720,9 @@ static void dm_submit_bio(struct bio *bio)
        struct mapped_device *md = bio->bi_bdev->bd_disk->private_data;
        int srcu_idx;
        struct dm_table *map;
+       unsigned bio_opf = bio->bi_opf;
 
-       map = dm_get_live_table_bio(md, &srcu_idx, bio);
+       map = dm_get_live_table_bio(md, &srcu_idx, bio_opf);
 
        /* If suspended, or map not yet available, queue this IO for later */
        if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) ||
@@ -1728,7 +1738,7 @@ static void dm_submit_bio(struct bio *bio)
 
        dm_split_and_process_bio(md, map, bio);
 out:
-       dm_put_live_table_bio(md, srcu_idx, bio);
+       dm_put_live_table_bio(md, srcu_idx, bio_opf);
 }
 
 static bool dm_poll_dm_io(struct dm_io *io, struct io_comp_batch *iob,
index 8273ac5..c7ecb0b 100644 (file)
@@ -4831,7 +4831,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
                                flush_workqueue(md_misc_wq);
                        if (mddev->sync_thread) {
                                set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-                               md_reap_sync_thread(mddev, true);
+                               md_reap_sync_thread(mddev);
                        }
                        mddev_unlock(mddev);
                }
@@ -6197,7 +6197,7 @@ static void __md_stop_writes(struct mddev *mddev)
                flush_workqueue(md_misc_wq);
        if (mddev->sync_thread) {
                set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-               md_reap_sync_thread(mddev, true);
+               md_reap_sync_thread(mddev);
        }
 
        del_timer_sync(&mddev->safemode_timer);
@@ -9303,7 +9303,7 @@ void md_check_recovery(struct mddev *mddev)
                         * ->spare_active and clear saved_raid_disk
                         */
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-                       md_reap_sync_thread(mddev, true);
+                       md_reap_sync_thread(mddev);
                        clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
                        clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
@@ -9338,7 +9338,7 @@ void md_check_recovery(struct mddev *mddev)
                        goto unlock;
                }
                if (mddev->sync_thread) {
-                       md_reap_sync_thread(mddev, true);
+                       md_reap_sync_thread(mddev);
                        goto unlock;
                }
                /* Set RUNNING before clearing NEEDED to avoid
@@ -9411,18 +9411,14 @@ void md_check_recovery(struct mddev *mddev)
 }
 EXPORT_SYMBOL(md_check_recovery);
 
-void md_reap_sync_thread(struct mddev *mddev, bool reconfig_mutex_held)
+void md_reap_sync_thread(struct mddev *mddev)
 {
        struct md_rdev *rdev;
        sector_t old_dev_sectors = mddev->dev_sectors;
        bool is_reshaped = false;
 
-       if (reconfig_mutex_held)
-               mddev_unlock(mddev);
        /* resync has finished, collect result */
        md_unregister_thread(&mddev->sync_thread);
-       if (reconfig_mutex_held)
-               mddev_lock_nointr(mddev);
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
            !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
            mddev->degraded != mddev->raid_disks) {
index 5f62c46..cf2cbb1 100644 (file)
@@ -719,7 +719,7 @@ extern struct md_thread *md_register_thread(
 extern void md_unregister_thread(struct md_thread **threadp);
 extern void md_wakeup_thread(struct md_thread *thread);
 extern void md_check_recovery(struct mddev *mddev);
-extern void md_reap_sync_thread(struct mddev *mddev, bool reconfig_mutex_held);
+extern void md_reap_sync_thread(struct mddev *mddev);
 extern int mddev_init_writes_pending(struct mddev *mddev);
 extern bool md_write_start(struct mddev *mddev, struct bio *bi);
 extern void md_write_inc(struct mddev *mddev, struct bio *bi);
index 973e2e0..0a2e480 100644 (file)
@@ -629,9 +629,9 @@ static void ppl_do_flush(struct ppl_io_unit *io)
                if (bdev) {
                        struct bio *bio;
 
-                       bio = bio_alloc_bioset(bdev, 0, GFP_NOIO,
+                       bio = bio_alloc_bioset(bdev, 0,
                                               REQ_OP_WRITE | REQ_PREFLUSH,
-                                              &ppl_conf->flush_bs);
+                                              GFP_NOIO, &ppl_conf->flush_bs);
                        bio->bi_private = io;
                        bio->bi_end_io = ppl_flush_endio;
 
index d6cd553..69f9b03 100644 (file)
@@ -232,9 +232,9 @@ static int ssc_probe(struct platform_device *pdev)
        clk_disable_unprepare(ssc->clk);
 
        ssc->irq = platform_get_irq(pdev, 0);
-       if (!ssc->irq) {
+       if (ssc->irq < 0) {
                dev_dbg(&pdev->dev, "could not get irq\n");
-               return -ENXIO;
+               return ssc->irq;
        }
 
        mutex_lock(&user_lock);
index 749cc5a..b1e7603 100644 (file)
@@ -407,6 +407,8 @@ static void rts5261_init_from_hw(struct rtsx_pcr *pcr)
                // default
                setting_reg1 = PCR_SETTING_REG1;
                setting_reg2 = PCR_SETTING_REG2;
+       } else {
+               return;
        }
 
        pci_read_config_dword(pdev, setting_reg2, &lval2);
index 8d169a3..c9c56fd 100644 (file)
@@ -79,6 +79,11 @@ static int at25_ee_read(void *priv, unsigned int offset,
 {
        struct at25_data *at25 = priv;
        char *buf = val;
+       size_t max_chunk = spi_max_transfer_size(at25->spi);
+       size_t num_msgs = DIV_ROUND_UP(count, max_chunk);
+       size_t nr_bytes = 0;
+       unsigned int msg_offset;
+       size_t msg_count;
        u8                      *cp;
        ssize_t                 status;
        struct spi_transfer     t[2];
@@ -92,54 +97,59 @@ static int at25_ee_read(void *priv, unsigned int offset,
        if (unlikely(!count))
                return -EINVAL;
 
-       cp = at25->command;
+       msg_offset = (unsigned int)offset;
+       msg_count = min(count, max_chunk);
+       while (num_msgs) {
+               cp = at25->command;
 
-       instr = AT25_READ;
-       if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
-               if (offset >= BIT(at25->addrlen * 8))
-                       instr |= AT25_INSTR_BIT3;
+               instr = AT25_READ;
+               if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
+                       if (msg_offset >= BIT(at25->addrlen * 8))
+                               instr |= AT25_INSTR_BIT3;
 
-       mutex_lock(&at25->lock);
+               mutex_lock(&at25->lock);
 
-       *cp++ = instr;
-
-       /* 8/16/24-bit address is written MSB first */
-       switch (at25->addrlen) {
-       default:        /* case 3 */
-               *cp++ = offset >> 16;
-               fallthrough;
-       case 2:
-               *cp++ = offset >> 8;
-               fallthrough;
-       case 1:
-       case 0: /* can't happen: for better code generation */
-               *cp++ = offset >> 0;
-       }
+               *cp++ = instr;
 
-       spi_message_init(&m);
-       memset(t, 0, sizeof(t));
+               /* 8/16/24-bit address is written MSB first */
+               switch (at25->addrlen) {
+               default:        /* case 3 */
+                       *cp++ = msg_offset >> 16;
+                       fallthrough;
+               case 2:
+                       *cp++ = msg_offset >> 8;
+                       fallthrough;
+               case 1:
+               case 0: /* can't happen: for better code generation */
+                       *cp++ = msg_offset >> 0;
+               }
 
-       t[0].tx_buf = at25->command;
-       t[0].len = at25->addrlen + 1;
-       spi_message_add_tail(&t[0], &m);
+               spi_message_init(&m);
+               memset(t, 0, sizeof(t));
 
-       t[1].rx_buf = buf;
-       t[1].len = count;
-       spi_message_add_tail(&t[1], &m);
+               t[0].tx_buf = at25->command;
+               t[0].len = at25->addrlen + 1;
+               spi_message_add_tail(&t[0], &m);
 
-       /*
-        * Read it all at once.
-        *
-        * REVISIT that's potentially a problem with large chips, if
-        * other devices on the bus need to be accessed regularly or
-        * this chip is clocked very slowly.
-        */
-       status = spi_sync(at25->spi, &m);
-       dev_dbg(&at25->spi->dev, "read %zu bytes at %d --> %zd\n",
-               count, offset, status);
+               t[1].rx_buf = buf + nr_bytes;
+               t[1].len = msg_count;
+               spi_message_add_tail(&t[1], &m);
 
-       mutex_unlock(&at25->lock);
-       return status;
+               status = spi_sync(at25->spi, &m);
+
+               mutex_unlock(&at25->lock);
+
+               if (status)
+                       return status;
+
+               --num_msgs;
+               msg_offset += msg_count;
+               nr_bytes += msg_count;
+       }
+
+       dev_dbg(&at25->spi->dev, "read %zu bytes at %d\n",
+               count, offset);
+       return 0;
 }
 
 /* Read extra registers as ID or serial number */
@@ -190,6 +200,7 @@ ATTRIBUTE_GROUPS(sernum);
 static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
 {
        struct at25_data *at25 = priv;
+       size_t maxsz = spi_max_transfer_size(at25->spi);
        const char *buf = val;
        int                     status = 0;
        unsigned                buf_size;
@@ -253,6 +264,8 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
                segment = buf_size - (offset % buf_size);
                if (segment > count)
                        segment = count;
+               if (segment > maxsz)
+                       segment = maxsz;
                memcpy(cp, buf, segment);
                status = spi_write(at25->spi, bounce,
                                segment + at25->addrlen + 1);
index cebcca6..cf2b826 100644 (file)
@@ -1351,7 +1351,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 
                if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
                    dev->hbm_state != MEI_HBM_CAP_SETUP) {
-                       if (dev->dev_state == MEI_DEV_POWER_DOWN) {
+                       if (dev->dev_state == MEI_DEV_POWER_DOWN ||
+                           dev->dev_state == MEI_DEV_POWERING_DOWN) {
                                dev_dbg(dev->dev, "hbm: capabilities response: on shutdown, ignoring\n");
                                return 0;
                        }
index 64ce3f8..15e8e2b 100644 (file)
 #define MEI_DEV_ID_ADP_P      0x51E0  /* Alder Lake Point P */
 #define MEI_DEV_ID_ADP_N      0x54E0  /* Alder Lake Point N */
 
+#define MEI_DEV_ID_RPL_S      0x7A68  /* Raptor Lake Point S */
+
 /*
  * MEI HW Section
  */
index 9870bf7..befa491 100644 (file)
@@ -1154,6 +1154,8 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
                        ret = mei_me_d0i3_exit_sync(dev);
                        if (ret)
                                return ret;
+               } else {
+                       hw->pg_state = MEI_PG_OFF;
                }
        }
 
index 33e5882..5435604 100644 (file)
@@ -116,6 +116,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_N, MEI_ME_PCH15_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)},
+
        /* required last entry */
        {0, }
 };
index 195dc89..9da4489 100644 (file)
@@ -1356,7 +1356,7 @@ static void msdc_data_xfer_next(struct msdc_host *host, struct mmc_request *mrq)
                msdc_request_done(host, mrq);
 }
 
-static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
+static void msdc_data_xfer_done(struct msdc_host *host, u32 events,
                                struct mmc_request *mrq, struct mmc_data *data)
 {
        struct mmc_command *stop;
@@ -1376,7 +1376,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
        spin_unlock_irqrestore(&host->lock, flags);
 
        if (done)
-               return true;
+               return;
        stop = data->stop;
 
        if (check_data || (stop && stop->error)) {
@@ -1385,12 +1385,15 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
                sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
                                1);
 
+               ret = readl_poll_timeout_atomic(host->base + MSDC_DMA_CTRL, val,
+                                               !(val & MSDC_DMA_CTRL_STOP), 1, 20000);
+               if (ret)
+                       dev_dbg(host->dev, "DMA stop timed out\n");
+
                ret = readl_poll_timeout_atomic(host->base + MSDC_DMA_CFG, val,
                                                !(val & MSDC_DMA_CFG_STS), 1, 20000);
-               if (ret) {
-                       dev_dbg(host->dev, "DMA stop timed out\n");
-                       return false;
-               }
+               if (ret)
+                       dev_dbg(host->dev, "DMA inactive timed out\n");
 
                sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
                dev_dbg(host->dev, "DMA stop\n");
@@ -1415,9 +1418,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
                }
 
                msdc_data_xfer_next(host, mrq);
-               done = true;
        }
-       return done;
 }
 
 static void msdc_set_buswidth(struct msdc_host *host, u32 width)
@@ -2416,6 +2417,9 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
        if (recovery) {
                sdr_set_field(host->base + MSDC_DMA_CTRL,
                              MSDC_DMA_CTRL_STOP, 1);
+               if (WARN_ON(readl_poll_timeout(host->base + MSDC_DMA_CTRL, val,
+                       !(val & MSDC_DMA_CTRL_STOP), 1, 3000)))
+                       return;
                if (WARN_ON(readl_poll_timeout(host->base + MSDC_DMA_CFG, val,
                        !(val & MSDC_DMA_CFG_STS), 1, 3000)))
                        return;
index 92c20cb..0d4d343 100644 (file)
@@ -152,6 +152,8 @@ static int sdhci_o2_get_cd(struct mmc_host *mmc)
 
        if (!(sdhci_readw(host, O2_PLL_DLL_WDT_CONTROL1) & O2_PLL_LOCK_STATUS))
                sdhci_o2_enable_internal_clock(host);
+       else
+               sdhci_o2_wait_card_detect_stable(host);
 
        return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
 }
index f85372a..6ba4c83 100644 (file)
@@ -3684,9 +3684,11 @@ re_arm:
                if (!rtnl_trylock())
                        return;
 
-               if (should_notify_peers)
+               if (should_notify_peers) {
+                       bond->send_peer_notif--;
                        call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
                                                 bond->dev);
+               }
                if (should_notify_rtnl) {
                        bond_slave_state_notify(bond);
                        bond_slave_link_notify(bond);
index 2727d31..1cbb05b 100644 (file)
@@ -2334,6 +2334,7 @@ static int
 qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 {
        struct qca8k_priv *priv = ds->priv;
+       int ret;
 
        /* We have only have a general MTU setting.
         * DSA always set the CPU port's MTU to the largest MTU of the slave
@@ -2344,8 +2345,27 @@ qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
        if (!dsa_is_cpu_port(ds, port))
                return 0;
 
+       /* To change the MAX_FRAME_SIZE the cpu ports must be off or
+        * the switch panics.
+        * Turn off both cpu ports before applying the new value to prevent
+        * this.
+        */
+       if (priv->port_enabled_map & BIT(0))
+               qca8k_port_set_status(priv, 0, 0);
+
+       if (priv->port_enabled_map & BIT(6))
+               qca8k_port_set_status(priv, 6, 0);
+
        /* Include L2 header / FCS length */
-       return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, new_mtu + ETH_HLEN + ETH_FCS_LEN);
+       ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, new_mtu + ETH_HLEN + ETH_FCS_LEN);
+
+       if (priv->port_enabled_map & BIT(0))
+               qca8k_port_set_status(priv, 0, 1);
+
+       if (priv->port_enabled_map & BIT(6))
+               qca8k_port_set_status(priv, 6, 1);
+
+       return ret;
 }
 
 static int
index 04408e1..ec58d0e 100644 (file)
@@ -15,7 +15,7 @@
 
 #define QCA8K_ETHERNET_MDIO_PRIORITY                   7
 #define QCA8K_ETHERNET_PHY_PRIORITY                    6
-#define QCA8K_ETHERNET_TIMEOUT                         100
+#define QCA8K_ETHERNET_TIMEOUT                         5
 
 #define QCA8K_NUM_PORTS                                        7
 #define QCA8K_NUM_CPU_PORTS                            2
index 4ebd241..4d790a8 100644 (file)
@@ -338,7 +338,7 @@ static int xgbe_platform_probe(struct platform_device *pdev)
                 *   the PHY resources listed last
                 */
                phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
-               phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1;
+               phy_irqnum = platform_irq_count(pdev) - 1;
                dma_irqnum = 1;
                dma_irqend = phy_irqnum;
        } else {
@@ -348,7 +348,7 @@ static int xgbe_platform_probe(struct platform_device *pdev)
                phy_memnum = 0;
                phy_irqnum = 0;
                dma_irqnum = 1;
-               dma_irqend = xgbe_resource_count(pdev, IORESOURCE_IRQ);
+               dma_irqend = platform_irq_count(pdev);
        }
 
        /* Obtain the mmio areas for the device */
index e6f4878..02bd3cf 100644 (file)
@@ -332,7 +332,6 @@ static void bgmac_remove(struct bcma_device *core)
        bcma_mdio_mii_unregister(bgmac->mii_bus);
        bgmac_enet_remove(bgmac);
        bcma_set_drvdata(core, NULL);
-       kfree(bgmac);
 }
 
 static struct bcma_driver bgmac_bcma_driver = {
index 8a3a446..94f80e1 100644 (file)
@@ -769,6 +769,7 @@ struct hnae3_tc_info {
        u8 prio_tc[HNAE3_MAX_USER_PRIO]; /* TC indexed by prio */
        u16 tqp_count[HNAE3_MAX_TC];
        u16 tqp_offset[HNAE3_MAX_TC];
+       u8 max_tc; /* Total number of TCs */
        u8 num_tc; /* Total number of enabled TCs */
        bool mqprio_active;
 };
index 6d20974..4c7988e 100644 (file)
@@ -1129,7 +1129,7 @@ hns3_is_ringparam_changed(struct net_device *ndev,
        if (old_ringparam->tx_desc_num == new_ringparam->tx_desc_num &&
            old_ringparam->rx_desc_num == new_ringparam->rx_desc_num &&
            old_ringparam->rx_buf_len == new_ringparam->rx_buf_len) {
-               netdev_info(ndev, "ringparam not changed\n");
+               netdev_info(ndev, "descriptor number and rx buffer length not changed\n");
                return false;
        }
 
index 1ebad0e..fae7976 100644 (file)
@@ -3268,7 +3268,7 @@ static int hclge_tp_port_init(struct hclge_dev *hdev)
 static int hclge_update_port_info(struct hclge_dev *hdev)
 {
        struct hclge_mac *mac = &hdev->hw.mac;
-       int speed = HCLGE_MAC_SPEED_UNKNOWN;
+       int speed;
        int ret;
 
        /* get the port info from SFP cmd if not copper port */
@@ -3279,10 +3279,13 @@ static int hclge_update_port_info(struct hclge_dev *hdev)
        if (!hdev->support_sfp_query)
                return 0;
 
-       if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
+       if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
+               speed = mac->speed;
                ret = hclge_get_sfp_info(hdev, mac);
-       else
+       } else {
+               speed = HCLGE_MAC_SPEED_UNKNOWN;
                ret = hclge_get_sfp_speed(hdev, &speed);
+       }
 
        if (ret == -EOPNOTSUPP) {
                hdev->support_sfp_query = false;
@@ -3294,6 +3297,8 @@ static int hclge_update_port_info(struct hclge_dev *hdev)
        if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
                if (mac->speed_type == QUERY_ACTIVE_SPEED) {
                        hclge_update_port_capability(hdev, mac);
+                       if (mac->speed != speed)
+                               (void)hclge_tm_port_shaper_cfg(hdev);
                        return 0;
                }
                return hclge_cfg_mac_speed_dup(hdev, mac->speed,
@@ -3376,6 +3381,12 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
        link_state_old = vport->vf_info.link_state;
        vport->vf_info.link_state = link_state;
 
+       /* return success directly if the VF is unalive, VF will
+        * query link state itself when it starts work.
+        */
+       if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
+               return 0;
+
        ret = hclge_push_vf_link_status(vport);
        if (ret) {
                vport->vf_info.link_state = link_state_old;
@@ -10117,6 +10128,7 @@ static int hclge_modify_port_base_vlan_tag(struct hclge_vport *vport,
        if (ret)
                return ret;
 
+       vport->port_base_vlan_cfg.tbl_sta = false;
        /* remove old VLAN tag */
        if (old_info->vlan_tag == 0)
                ret = hclge_set_vf_vlan_common(hdev, vport->vport_id,
index 1f87a8a..2f33b03 100644 (file)
@@ -282,8 +282,8 @@ static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev,
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
 
-static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev,
-                                     u16 qs_id, u8 pri)
+static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev, u16 qs_id, u8 pri,
+                                     bool link_vld)
 {
        struct hclge_qs_to_pri_link_cmd *map;
        struct hclge_desc desc;
@@ -294,7 +294,7 @@ static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev,
 
        map->qs_id = cpu_to_le16(qs_id);
        map->priority = pri;
-       map->link_vld = HCLGE_TM_QS_PRI_LINK_VLD_MSK;
+       map->link_vld = link_vld ? HCLGE_TM_QS_PRI_LINK_VLD_MSK : 0;
 
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
@@ -420,7 +420,7 @@ static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
 
-static int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev)
+int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev)
 {
        struct hclge_port_shapping_cmd *shap_cfg_cmd;
        struct hclge_shaper_ir_para ir_para;
@@ -642,11 +642,13 @@ static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport)
         * one tc for VF for simplicity. VF's vport_id is non zero.
         */
        if (vport->vport_id) {
+               kinfo->tc_info.max_tc = 1;
                kinfo->tc_info.num_tc = 1;
                vport->qs_offset = HNAE3_MAX_TC +
                                   vport->vport_id - HCLGE_VF_VPORT_START_NUM;
                vport_max_rss_size = hdev->vf_rss_size_max;
        } else {
+               kinfo->tc_info.max_tc = hdev->tc_max;
                kinfo->tc_info.num_tc =
                        min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc);
                vport->qs_offset = 0;
@@ -679,7 +681,9 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
        kinfo->num_tqps = hclge_vport_get_tqp_num(vport);
        vport->dwrr = 100;  /* 100 percent as init */
        vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
-       hdev->rss_cfg.rss_size = kinfo->rss_size;
+
+       if (vport->vport_id == PF_VPORT_ID)
+               hdev->rss_cfg.rss_size = kinfo->rss_size;
 
        /* when enable mqprio, the tc_info has been updated. */
        if (kinfo->tc_info.mqprio_active)
@@ -714,14 +718,22 @@ static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
 
 static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
 {
-       u8 i;
+       u8 i, tc_sch_mode;
+       u32 bw_limit;
+
+       for (i = 0; i < hdev->tc_max; i++) {
+               if (i < hdev->tm_info.num_tc) {
+                       tc_sch_mode = HCLGE_SCH_MODE_DWRR;
+                       bw_limit = hdev->tm_info.pg_info[0].bw_limit;
+               } else {
+                       tc_sch_mode = HCLGE_SCH_MODE_SP;
+                       bw_limit = 0;
+               }
 
-       for (i = 0; i < hdev->tm_info.num_tc; i++) {
                hdev->tm_info.tc_info[i].tc_id = i;
-               hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR;
+               hdev->tm_info.tc_info[i].tc_sch_mode = tc_sch_mode;
                hdev->tm_info.tc_info[i].pgid = 0;
-               hdev->tm_info.tc_info[i].bw_limit =
-                       hdev->tm_info.pg_info[0].bw_limit;
+               hdev->tm_info.tc_info[i].bw_limit = bw_limit;
        }
 
        for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
@@ -926,10 +938,13 @@ static int hclge_tm_pri_q_qs_cfg_tc_base(struct hclge_dev *hdev)
        for (k = 0; k < hdev->num_alloc_vport; k++) {
                struct hnae3_knic_private_info *kinfo = &vport[k].nic.kinfo;
 
-               for (i = 0; i < kinfo->tc_info.num_tc; i++) {
+               for (i = 0; i < kinfo->tc_info.max_tc; i++) {
+                       u8 pri = i < kinfo->tc_info.num_tc ? i : 0;
+                       bool link_vld = i < kinfo->tc_info.num_tc;
+
                        ret = hclge_tm_qs_to_pri_map_cfg(hdev,
                                                         vport[k].qs_offset + i,
-                                                        i);
+                                                        pri, link_vld);
                        if (ret)
                                return ret;
                }
@@ -949,7 +964,7 @@ static int hclge_tm_pri_q_qs_cfg_vnet_base(struct hclge_dev *hdev)
                for (i = 0; i < HNAE3_MAX_TC; i++) {
                        ret = hclge_tm_qs_to_pri_map_cfg(hdev,
                                                         vport[k].qs_offset + i,
-                                                        k);
+                                                        k, true);
                        if (ret)
                                return ret;
                }
@@ -989,33 +1004,39 @@ static int hclge_tm_pri_tc_base_shaper_cfg(struct hclge_dev *hdev)
 {
        u32 max_tm_rate = hdev->ae_dev->dev_specs.max_tm_rate;
        struct hclge_shaper_ir_para ir_para;
-       u32 shaper_para;
+       u32 shaper_para_c, shaper_para_p;
        int ret;
        u32 i;
 
-       for (i = 0; i < hdev->tm_info.num_tc; i++) {
+       for (i = 0; i < hdev->tc_max; i++) {
                u32 rate = hdev->tm_info.tc_info[i].bw_limit;
 
-               ret = hclge_shaper_para_calc(rate, HCLGE_SHAPER_LVL_PRI,
-                                            &ir_para, max_tm_rate);
-               if (ret)
-                       return ret;
+               if (rate) {
+                       ret = hclge_shaper_para_calc(rate, HCLGE_SHAPER_LVL_PRI,
+                                                    &ir_para, max_tm_rate);
+                       if (ret)
+                               return ret;
+
+                       shaper_para_c = hclge_tm_get_shapping_para(0, 0, 0,
+                                                                  HCLGE_SHAPER_BS_U_DEF,
+                                                                  HCLGE_SHAPER_BS_S_DEF);
+                       shaper_para_p = hclge_tm_get_shapping_para(ir_para.ir_b,
+                                                                  ir_para.ir_u,
+                                                                  ir_para.ir_s,
+                                                                  HCLGE_SHAPER_BS_U_DEF,
+                                                                  HCLGE_SHAPER_BS_S_DEF);
+               } else {
+                       shaper_para_c = 0;
+                       shaper_para_p = 0;
+               }
 
-               shaper_para = hclge_tm_get_shapping_para(0, 0, 0,
-                                                        HCLGE_SHAPER_BS_U_DEF,
-                                                        HCLGE_SHAPER_BS_S_DEF);
                ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, i,
-                                               shaper_para, rate);
+                                               shaper_para_c, rate);
                if (ret)
                        return ret;
 
-               shaper_para = hclge_tm_get_shapping_para(ir_para.ir_b,
-                                                        ir_para.ir_u,
-                                                        ir_para.ir_s,
-                                                        HCLGE_SHAPER_BS_U_DEF,
-                                                        HCLGE_SHAPER_BS_S_DEF);
                ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, i,
-                                               shaper_para, rate);
+                                               shaper_para_p, rate);
                if (ret)
                        return ret;
        }
@@ -1125,7 +1146,7 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
        int ret;
        u32 i, k;
 
-       for (i = 0; i < hdev->tm_info.num_tc; i++) {
+       for (i = 0; i < hdev->tc_max; i++) {
                pg_info =
                        &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
                dwrr = pg_info->tc_dwrr[i];
@@ -1135,9 +1156,15 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
                        return ret;
 
                for (k = 0; k < hdev->num_alloc_vport; k++) {
+                       struct hnae3_knic_private_info *kinfo = &vport[k].nic.kinfo;
+
+                       if (i >= kinfo->tc_info.max_tc)
+                               continue;
+
+                       dwrr = i < kinfo->tc_info.num_tc ? vport[k].dwrr : 0;
                        ret = hclge_tm_qs_weight_cfg(
                                hdev, vport[k].qs_offset + i,
-                               vport[k].dwrr);
+                               dwrr);
                        if (ret)
                                return ret;
                }
@@ -1303,6 +1330,7 @@ static int hclge_tm_schd_mode_tc_base_cfg(struct hclge_dev *hdev, u8 pri_id)
 {
        struct hclge_vport *vport = hdev->vport;
        int ret;
+       u8 mode;
        u16 i;
 
        ret = hclge_tm_pri_schd_mode_cfg(hdev, pri_id);
@@ -1310,9 +1338,16 @@ static int hclge_tm_schd_mode_tc_base_cfg(struct hclge_dev *hdev, u8 pri_id)
                return ret;
 
        for (i = 0; i < hdev->num_alloc_vport; i++) {
+               struct hnae3_knic_private_info *kinfo = &vport[i].nic.kinfo;
+
+               if (pri_id >= kinfo->tc_info.max_tc)
+                       continue;
+
+               mode = pri_id < kinfo->tc_info.num_tc ? HCLGE_SCH_MODE_DWRR :
+                      HCLGE_SCH_MODE_SP;
                ret = hclge_tm_qs_schd_mode_cfg(hdev,
                                                vport[i].qs_offset + pri_id,
-                                               HCLGE_SCH_MODE_DWRR);
+                                               mode);
                if (ret)
                        return ret;
        }
@@ -1353,7 +1388,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
        u8 i;
 
        if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
-               for (i = 0; i < hdev->tm_info.num_tc; i++) {
+               for (i = 0; i < hdev->tc_max; i++) {
                        ret = hclge_tm_schd_mode_tc_base_cfg(hdev, i);
                        if (ret)
                                return ret;
index 619cc30..d943943 100644 (file)
@@ -237,6 +237,7 @@ int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
 void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
 void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
 int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate);
+int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev);
 int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num);
 int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num);
 int hclge_tm_get_qset_map_pri(struct hclge_dev *hdev, u16 qset_id, u8 *priority,
index 60ae8bf..1749d26 100644 (file)
@@ -43,9 +43,7 @@ static bool check_image_valid(struct hinic_devlink_priv *priv, const u8 *buf,
 
        for (i = 0; i < fw_image->fw_info.fw_section_cnt; i++) {
                len += fw_image->fw_section_info[i].fw_section_len;
-               memcpy(&host_image->image_section_info[i],
-                      &fw_image->fw_section_info[i],
-                      sizeof(struct fw_section_info_st));
+               host_image->image_section_info[i] = fw_image->fw_section_info[i];
        }
 
        if (len != fw_image->fw_len ||
index 610f00c..19704f5 100644 (file)
@@ -2586,15 +2586,16 @@ static void i40e_diag_test(struct net_device *netdev,
 
                set_bit(__I40E_TESTING, pf->state);
 
+               if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+                   test_bit(__I40E_RESET_INTR_RECEIVED, pf->state)) {
+                       dev_warn(&pf->pdev->dev,
+                                "Cannot start offline testing when PF is in reset state.\n");
+                       goto skip_ol_tests;
+               }
+
                if (i40e_active_vfs(pf) || i40e_active_vmdqs(pf)) {
                        dev_warn(&pf->pdev->dev,
                                 "Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n");
-                       data[I40E_ETH_TEST_REG]         = 1;
-                       data[I40E_ETH_TEST_EEPROM]      = 1;
-                       data[I40E_ETH_TEST_INTR]        = 1;
-                       data[I40E_ETH_TEST_LINK]        = 1;
-                       eth_test->flags |= ETH_TEST_FL_FAILED;
-                       clear_bit(__I40E_TESTING, pf->state);
                        goto skip_ol_tests;
                }
 
@@ -2641,9 +2642,17 @@ static void i40e_diag_test(struct net_device *netdev,
                data[I40E_ETH_TEST_INTR] = 0;
        }
 
-skip_ol_tests:
-
        netif_info(pf, drv, netdev, "testing finished\n");
+       return;
+
+skip_ol_tests:
+       data[I40E_ETH_TEST_REG]         = 1;
+       data[I40E_ETH_TEST_EEPROM]      = 1;
+       data[I40E_ETH_TEST_INTR]        = 1;
+       data[I40E_ETH_TEST_LINK]        = 1;
+       eth_test->flags |= ETH_TEST_FL_FAILED;
+       clear_bit(__I40E_TESTING, pf->state);
+       netif_info(pf, drv, netdev, "testing failed\n");
 }
 
 static void i40e_get_wol(struct net_device *netdev,
index 332a608..72576bb 100644 (file)
@@ -8542,6 +8542,11 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,
                return -EOPNOTSUPP;
        }
 
+       if (!tc) {
+               dev_err(&pf->pdev->dev, "Unable to add filter because of invalid destination");
+               return -EINVAL;
+       }
+
        if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
            test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
                return -EBUSY;
index 2606e8f..033ea71 100644 (file)
@@ -2282,7 +2282,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
        }
 
        if (vf->adq_enabled) {
-               for (i = 0; i < I40E_MAX_VF_VSI; i++)
+               for (i = 0; i < vf->num_tc; i++)
                        num_qps_all += vf->ch[i].num_qps;
                if (num_qps_all != qci->num_queue_pairs) {
                        aq_ret = I40E_ERR_PARAM;
index 7dfcf78..f3ecb3b 100644 (file)
@@ -984,7 +984,7 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
                list_add_tail(&f->list, &adapter->mac_filter_list);
                f->add = true;
                f->is_new_mac = true;
-               f->is_primary = false;
+               f->is_primary = ether_addr_equal(macaddr, adapter->hw.mac.addr);
                adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
        } else {
                f->remove = false;
index 1e71b70..70335f6 100644 (file)
@@ -2189,6 +2189,42 @@ ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks,
        return err;
 }
 
+/**
+ * ice_set_phy_type_from_speed - set phy_types based on speeds
+ * and advertised modes
+ * @ks: ethtool link ksettings struct
+ * @phy_type_low: pointer to the lower part of phy_type
+ * @phy_type_high: pointer to the higher part of phy_type
+ * @adv_link_speed: targeted link speeds bitmap
+ */
+static void
+ice_set_phy_type_from_speed(const struct ethtool_link_ksettings *ks,
+                           u64 *phy_type_low, u64 *phy_type_high,
+                           u16 adv_link_speed)
+{
+       /* Handle 1000M speed in a special way because ice_update_phy_type
+        * enables all link modes, but having mixed copper and optical
+        * standards is not supported.
+        */
+       adv_link_speed &= ~ICE_AQ_LINK_SPEED_1000MB;
+
+       if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 1000baseT_Full))
+               *phy_type_low |= ICE_PHY_TYPE_LOW_1000BASE_T |
+                                ICE_PHY_TYPE_LOW_1G_SGMII;
+
+       if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 1000baseKX_Full))
+               *phy_type_low |= ICE_PHY_TYPE_LOW_1000BASE_KX;
+
+       if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 1000baseX_Full))
+               *phy_type_low |= ICE_PHY_TYPE_LOW_1000BASE_SX |
+                                ICE_PHY_TYPE_LOW_1000BASE_LX;
+
+       ice_update_phy_type(phy_type_low, phy_type_high, adv_link_speed);
+}
+
 /**
  * ice_set_link_ksettings - Set Speed and Duplex
  * @netdev: network interface device structure
@@ -2320,7 +2356,8 @@ ice_set_link_ksettings(struct net_device *netdev,
                adv_link_speed = curr_link_speed;
 
        /* Convert the advertise link speeds to their corresponded PHY_TYPE */
-       ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed);
+       ice_set_phy_type_from_speed(ks, &phy_type_low, &phy_type_high,
+                                   adv_link_speed);
 
        if (!autoneg_changed && adv_link_speed == curr_link_speed) {
                netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
@@ -3470,6 +3507,16 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
        new_rx = ch->combined_count + ch->rx_count;
        new_tx = ch->combined_count + ch->tx_count;
 
+       if (new_rx < vsi->tc_cfg.numtc) {
+               netdev_err(dev, "Cannot set less Rx channels, than Traffic Classes you have (%u)\n",
+                          vsi->tc_cfg.numtc);
+               return -EINVAL;
+       }
+       if (new_tx < vsi->tc_cfg.numtc) {
+               netdev_err(dev, "Cannot set less Tx channels, than Traffic Classes you have (%u)\n",
+                          vsi->tc_cfg.numtc);
+               return -EINVAL;
+       }
        if (new_rx > ice_get_max_rxq(pf)) {
                netdev_err(dev, "Maximum allowed Rx channels is %d\n",
                           ice_get_max_rxq(pf));
index 454e01a..f7f9c97 100644 (file)
@@ -909,7 +909,7 @@ static void ice_set_dflt_vsi_ctx(struct ice_hw *hw, struct ice_vsi_ctx *ctxt)
  * @vsi: the VSI being configured
  * @ctxt: VSI context structure
  */
-static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
+static int ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
 {
        u16 offset = 0, qmap = 0, tx_count = 0, pow = 0;
        u16 num_txq_per_tc, num_rxq_per_tc;
@@ -982,7 +982,18 @@ static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
        else
                vsi->num_rxq = num_rxq_per_tc;
 
+       if (vsi->num_rxq > vsi->alloc_rxq) {
+               dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Rx queues (%u), than were allocated (%u)!\n",
+                       vsi->num_rxq, vsi->alloc_rxq);
+               return -EINVAL;
+       }
+
        vsi->num_txq = tx_count;
+       if (vsi->num_txq > vsi->alloc_txq) {
+               dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Tx queues (%u), than were allocated (%u)!\n",
+                       vsi->num_txq, vsi->alloc_txq);
+               return -EINVAL;
+       }
 
        if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
                dev_dbg(ice_pf_to_dev(vsi->back), "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n");
@@ -1000,6 +1011,8 @@ static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
         */
        ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
        ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
+
+       return 0;
 }
 
 /**
@@ -1187,7 +1200,10 @@ static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
        if (vsi->type == ICE_VSI_CHNL) {
                ice_chnl_vsi_setup_q_map(vsi, ctxt);
        } else {
-               ice_vsi_setup_q_map(vsi, ctxt);
+               ret = ice_vsi_setup_q_map(vsi, ctxt);
+               if (ret)
+                       goto out;
+
                if (!init_vsi) /* means VSI being updated */
                        /* must to indicate which section of VSI context are
                         * being modified
@@ -3464,7 +3480,7 @@ void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)
  *
  * Prepares VSI tc_config to have queue configurations based on MQPRIO options.
  */
-static void
+static int
 ice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt,
                           u8 ena_tc)
 {
@@ -3513,7 +3529,18 @@ ice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt,
 
        /* Set actual Tx/Rx queue pairs */
        vsi->num_txq = offset + qcount_tx;
+       if (vsi->num_txq > vsi->alloc_txq) {
+               dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Tx queues (%u), than were allocated (%u)!\n",
+                       vsi->num_txq, vsi->alloc_txq);
+               return -EINVAL;
+       }
+
        vsi->num_rxq = offset + qcount_rx;
+       if (vsi->num_rxq > vsi->alloc_rxq) {
+               dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Rx queues (%u), than were allocated (%u)!\n",
+                       vsi->num_rxq, vsi->alloc_rxq);
+               return -EINVAL;
+       }
 
        /* Setup queue TC[0].qmap for given VSI context */
        ctxt->info.tc_mapping[0] = cpu_to_le16(qmap);
@@ -3531,6 +3558,8 @@ ice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt,
        dev_dbg(ice_pf_to_dev(vsi->back), "vsi->num_rxq = %d\n",  vsi->num_rxq);
        dev_dbg(ice_pf_to_dev(vsi->back), "all_numtc %u, all_enatc: 0x%04x, tc_cfg.numtc %u\n",
                vsi->all_numtc, vsi->all_enatc, vsi->tc_cfg.numtc);
+
+       return 0;
 }
 
 /**
@@ -3580,9 +3609,12 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
 
        if (vsi->type == ICE_VSI_PF &&
            test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))
-               ice_vsi_setup_q_map_mqprio(vsi, ctx, ena_tc);
+               ret = ice_vsi_setup_q_map_mqprio(vsi, ctx, ena_tc);
        else
-               ice_vsi_setup_q_map(vsi, ctx);
+               ret = ice_vsi_setup_q_map(vsi, ctx);
+
+       if (ret)
+               goto out;
 
        /* must to indicate which section of VSI context are being modified */
        ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
index e1cae25..c1ac2f7 100644 (file)
@@ -5763,25 +5763,38 @@ static netdev_features_t
 ice_fix_features(struct net_device *netdev, netdev_features_t features)
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
-       netdev_features_t supported_vlan_filtering;
-       netdev_features_t requested_vlan_filtering;
-       struct ice_vsi *vsi = np->vsi;
-
-       requested_vlan_filtering = features & NETIF_VLAN_FILTERING_FEATURES;
-
-       /* make sure supported_vlan_filtering works for both SVM and DVM */
-       supported_vlan_filtering = NETIF_F_HW_VLAN_CTAG_FILTER;
-       if (ice_is_dvm_ena(&vsi->back->hw))
-               supported_vlan_filtering |= NETIF_F_HW_VLAN_STAG_FILTER;
-
-       if (requested_vlan_filtering &&
-           requested_vlan_filtering != supported_vlan_filtering) {
-               if (requested_vlan_filtering & NETIF_F_HW_VLAN_CTAG_FILTER) {
-                       netdev_warn(netdev, "cannot support requested VLAN filtering settings, enabling all supported VLAN filtering settings\n");
-                       features |= supported_vlan_filtering;
+       netdev_features_t req_vlan_fltr, cur_vlan_fltr;
+       bool cur_ctag, cur_stag, req_ctag, req_stag;
+
+       cur_vlan_fltr = netdev->features & NETIF_VLAN_FILTERING_FEATURES;
+       cur_ctag = cur_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER;
+       cur_stag = cur_vlan_fltr & NETIF_F_HW_VLAN_STAG_FILTER;
+
+       req_vlan_fltr = features & NETIF_VLAN_FILTERING_FEATURES;
+       req_ctag = req_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER;
+       req_stag = req_vlan_fltr & NETIF_F_HW_VLAN_STAG_FILTER;
+
+       if (req_vlan_fltr != cur_vlan_fltr) {
+               if (ice_is_dvm_ena(&np->vsi->back->hw)) {
+                       if (req_ctag && req_stag) {
+                               features |= NETIF_VLAN_FILTERING_FEATURES;
+                       } else if (!req_ctag && !req_stag) {
+                               features &= ~NETIF_VLAN_FILTERING_FEATURES;
+                       } else if ((!cur_ctag && req_ctag && !cur_stag) ||
+                                  (!cur_stag && req_stag && !cur_ctag)) {
+                               features |= NETIF_VLAN_FILTERING_FEATURES;
+                               netdev_warn(netdev,  "802.1Q and 802.1ad VLAN filtering must be either both on or both off. VLAN filtering has been enabled for both types.\n");
+                       } else if ((cur_ctag && !req_ctag && cur_stag) ||
+                                  (cur_stag && !req_stag && cur_ctag)) {
+                               features &= ~NETIF_VLAN_FILTERING_FEATURES;
+                               netdev_warn(netdev,  "802.1Q and 802.1ad VLAN filtering must be either both on or both off. VLAN filtering has been disabled for both types.\n");
+                       }
                } else {
-                       netdev_warn(netdev, "cannot support requested VLAN filtering settings, clearing all supported VLAN filtering settings\n");
-                       features &= ~supported_vlan_filtering;
+                       if (req_vlan_fltr & NETIF_F_HW_VLAN_STAG_FILTER)
+                               netdev_warn(netdev, "cannot support requested 802.1ad filtering setting in SVM mode\n");
+
+                       if (req_vlan_fltr & NETIF_F_HW_VLAN_CTAG_FILTER)
+                               features |= NETIF_F_HW_VLAN_CTAG_FILTER;
                }
        }
 
index 662947c..ef9344e 100644 (file)
@@ -2271,7 +2271,7 @@ static int
 ice_ptp_init_tx_e822(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
 {
        tx->quad = port / ICE_PORTS_PER_QUAD;
-       tx->quad_offset = tx->quad * INDEX_PER_PORT;
+       tx->quad_offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT;
        tx->len = INDEX_PER_PORT;
 
        return ice_ptp_alloc_tx_tracker(tx);
index afd048d..10e396a 100644 (file)
@@ -49,6 +49,37 @@ struct ice_perout_channel {
  * To allow multiple ports to access the shared register block independently,
  * the blocks are split up so that indexes are assigned to each port based on
  * hardware logical port number.
+ *
+ * The timestamp blocks are handled differently for E810- and E822-based
+ * devices. In E810 devices, each port has its own block of timestamps, while in
+ * E822 there is a need to logically break the block of registers into smaller
+ * chunks based on the port number to avoid collisions.
+ *
+ * Example for port 5 in E810:
+ *  +--------+--------+--------+--------+--------+--------+--------+--------+
+ *  |register|register|register|register|register|register|register|register|
+ *  | block  | block  | block  | block  | block  | block  | block  | block  |
+ *  |  for   |  for   |  for   |  for   |  for   |  for   |  for   |  for   |
+ *  | port 0 | port 1 | port 2 | port 3 | port 4 | port 5 | port 6 | port 7 |
+ *  +--------+--------+--------+--------+--------+--------+--------+--------+
+ *                                               ^^
+ *                                               ||
+ *                                               |---  quad offset is always 0
+ *                                               ---- quad number
+ *
+ * Example for port 5 in E822:
+ * +-----------------------------+-----------------------------+
+ * |  register block for quad 0  |  register block for quad 1  |
+ * |+------+------+------+------+|+------+------+------+------+|
+ * ||port 0|port 1|port 2|port 3|||port 0|port 1|port 2|port 3||
+ * |+------+------+------+------+|+------+------+------+------+|
+ * +-----------------------------+-------^---------------------+
+ *                                ^      |
+ *                                |      --- quad offset*
+ *                                ---- quad number
+ *
+ *   * PHY port 5 is port 1 in quad 1
+ *
  */
 
 /**
index 0a0c55f..b803f2a 100644 (file)
@@ -524,6 +524,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
         */
        fltr->rid = rule_added.rid;
        fltr->rule_id = rule_added.rule_id;
+       fltr->dest_id = rule_added.vsi_handle;
 
 exit:
        kfree(list);
@@ -993,7 +994,9 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
                n_proto_key = ntohs(match.key->n_proto);
                n_proto_mask = ntohs(match.mask->n_proto);
 
-               if (n_proto_key == ETH_P_ALL || n_proto_key == 0) {
+               if (n_proto_key == ETH_P_ALL || n_proto_key == 0 ||
+                   fltr->tunnel_type == TNL_GTPU ||
+                   fltr->tunnel_type == TNL_GTPC) {
                        n_proto_key = 0;
                        n_proto_mask = 0;
                } else {
index cd8e6b5..7adf9dd 100644 (file)
@@ -504,6 +504,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
        }
 
        if (ice_is_vf_disabled(vf)) {
+               vsi = ice_get_vf_vsi(vf);
+               if (WARN_ON(!vsi))
+                       return -EINVAL;
+               ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id);
+               ice_vsi_stop_all_rx_rings(vsi);
                dev_dbg(dev, "VF is already disabled, there is no need for resetting it, telling VM, all is fine %d\n",
                        vf->vf_id);
                return 0;
index 1d9b84c..4547bc1 100644 (file)
@@ -1569,35 +1569,27 @@ error_param:
  */
 static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
 {
-       enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
        struct virtchnl_vsi_queue_config_info *qci =
            (struct virtchnl_vsi_queue_config_info *)msg;
        struct virtchnl_queue_pair_info *qpi;
        struct ice_pf *pf = vf->pf;
        struct ice_vsi *vsi;
-       int i, q_idx;
+       int i = -1, q_idx;
 
-       if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
-               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+       if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
                goto error_param;
-       }
 
-       if (!ice_vc_isvalid_vsi_id(vf, qci->vsi_id)) {
-               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+       if (!ice_vc_isvalid_vsi_id(vf, qci->vsi_id))
                goto error_param;
-       }
 
        vsi = ice_get_vf_vsi(vf);
-       if (!vsi) {
-               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+       if (!vsi)
                goto error_param;
-       }
 
        if (qci->num_queue_pairs > ICE_MAX_RSS_QS_PER_VF ||
            qci->num_queue_pairs > min_t(u16, vsi->alloc_txq, vsi->alloc_rxq)) {
                dev_err(ice_pf_to_dev(pf), "VF-%d requesting more than supported number of queues: %d\n",
                        vf->vf_id, min_t(u16, vsi->alloc_txq, vsi->alloc_rxq));
-               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
                goto error_param;
        }
 
@@ -1610,7 +1602,6 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
                    !ice_vc_isvalid_ring_len(qpi->txq.ring_len) ||
                    !ice_vc_isvalid_ring_len(qpi->rxq.ring_len) ||
                    !ice_vc_isvalid_q_id(vf, qci->vsi_id, qpi->txq.queue_id)) {
-                       v_ret = VIRTCHNL_STATUS_ERR_PARAM;
                        goto error_param;
                }
 
@@ -1620,7 +1611,6 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
                 * for selected "vsi"
                 */
                if (q_idx >= vsi->alloc_txq || q_idx >= vsi->alloc_rxq) {
-                       v_ret = VIRTCHNL_STATUS_ERR_PARAM;
                        goto error_param;
                }
 
@@ -1630,14 +1620,13 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
                        vsi->tx_rings[i]->count = qpi->txq.ring_len;
 
                        /* Disable any existing queue first */
-                       if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx)) {
-                               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+                       if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx))
                                goto error_param;
-                       }
 
                        /* Configure a queue with the requested settings */
                        if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) {
-                               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+                               dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure TX queue %d\n",
+                                        vf->vf_id, i);
                                goto error_param;
                        }
                }
@@ -1651,17 +1640,13 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
 
                        if (qpi->rxq.databuffer_size != 0 &&
                            (qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
-                            qpi->rxq.databuffer_size < 1024)) {
-                               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+                            qpi->rxq.databuffer_size < 1024))
                                goto error_param;
-                       }
                        vsi->rx_buf_len = qpi->rxq.databuffer_size;
                        vsi->rx_rings[i]->rx_buf_len = vsi->rx_buf_len;
                        if (qpi->rxq.max_pkt_size > max_frame_size ||
-                           qpi->rxq.max_pkt_size < 64) {
-                               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+                           qpi->rxq.max_pkt_size < 64)
                                goto error_param;
-                       }
 
                        vsi->max_frame = qpi->rxq.max_pkt_size;
                        /* add space for the port VLAN since the VF driver is
@@ -1672,16 +1657,30 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
                                vsi->max_frame += VLAN_HLEN;
 
                        if (ice_vsi_cfg_single_rxq(vsi, q_idx)) {
-                               v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+                               dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure RX queue %d\n",
+                                        vf->vf_id, i);
                                goto error_param;
                        }
                }
        }
 
+       /* send the response to the VF */
+       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+                                    VIRTCHNL_STATUS_SUCCESS, NULL, 0);
 error_param:
+       /* disable whatever we can */
+       for (; i >= 0; i--) {
+               if (ice_vsi_ctrl_one_rx_ring(vsi, false, i, true))
+                       dev_err(ice_pf_to_dev(pf), "VF-%d could not disable RX queue %d\n",
+                               vf->vf_id, i);
+               if (ice_vf_vsi_dis_single_txq(vf, vsi, i))
+                       dev_err(ice_pf_to_dev(pf), "VF-%d could not disable TX queue %d\n",
+                               vf->vf_id, i);
+       }
+
        /* send the response to the VF */
-       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, v_ret,
-                                    NULL, 0);
+       return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+                                    VIRTCHNL_STATUS_ERR_PARAM, NULL, 0);
 }
 
 /**
index 68be297..c5f04c4 100644 (file)
@@ -4819,8 +4819,11 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
        while (i != tx_ring->next_to_use) {
                union e1000_adv_tx_desc *eop_desc, *tx_desc;
 
-               /* Free all the Tx ring sk_buffs */
-               dev_kfree_skb_any(tx_buffer->skb);
+               /* Free all the Tx ring sk_buffs or xdp frames */
+               if (tx_buffer->type == IGB_TYPE_SKB)
+                       dev_kfree_skb_any(tx_buffer->skb);
+               else
+                       xdp_return_frame(tx_buffer->xdpf);
 
                /* unmap skb header data */
                dma_unmap_single(tx_ring->dev,
@@ -9898,11 +9901,10 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
        struct e1000_hw *hw = &adapter->hw;
        u32 dmac_thr;
        u16 hwm;
+       u32 reg;
 
        if (hw->mac.type > e1000_82580) {
                if (adapter->flags & IGB_FLAG_DMAC) {
-                       u32 reg;
-
                        /* force threshold to 0. */
                        wr32(E1000_DMCTXTH, 0);
 
@@ -9935,7 +9937,6 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
                        /* Disable BMC-to-OS Watchdog Enable */
                        if (hw->mac.type != e1000_i354)
                                reg &= ~E1000_DMACR_DC_BMC2OSW_EN;
-
                        wr32(E1000_DMACR, reg);
 
                        /* no lower threshold to disable
@@ -9952,12 +9953,12 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
                         */
                        wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE -
                             (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6);
+               }
 
-                       /* make low power state decision controlled
-                        * by DMA coal
-                        */
+               if (hw->mac.type >= e1000_i210 ||
+                   (adapter->flags & IGB_FLAG_DMAC)) {
                        reg = rd32(E1000_PCIEMISC);
-                       reg &= ~E1000_PCIEMISC_LX_DECISION;
+                       reg |= E1000_PCIEMISC_LX_DECISION;
                        wr32(E1000_PCIEMISC, reg);
                } /* endif adapter->dmac is not disabled */
        } else if (hw->mac.type == e1000_82580) {
index bc614a4..3f60a80 100644 (file)
@@ -1390,7 +1390,8 @@ static int otx2vf_get_link_ksettings(struct net_device *netdev,
 
 static const struct ethtool_ops otx2vf_ethtool_ops = {
        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
-                                    ETHTOOL_COALESCE_MAX_FRAMES,
+                                    ETHTOOL_COALESCE_MAX_FRAMES |
+                                    ETHTOOL_COALESCE_USE_ADAPTIVE,
        .supported_ring_params  = ETHTOOL_RING_USE_RX_BUF_LEN |
                                  ETHTOOL_RING_USE_CQE_SIZE,
        .get_link               = otx2_get_link,
index a68d931..15c8d4d 100644 (file)
@@ -8,8 +8,8 @@
 #include "spectrum.h"
 
 enum mlxsw_sp_counter_sub_pool_id {
-       MLXSW_SP_COUNTER_SUB_POOL_FLOW,
        MLXSW_SP_COUNTER_SUB_POOL_RIF,
+       MLXSW_SP_COUNTER_SUB_POOL_FLOW,
 };
 
 int mlxsw_sp_counter_alloc(struct mlxsw_sp *mlxsw_sp,
index 4225efb..f2e2261 100644 (file)
@@ -547,6 +547,57 @@ static inline void axienet_iow(struct axienet_local *lp, off_t offset,
        iowrite32(value, lp->regs + offset);
 }
 
+/**
+ * axienet_dma_out32 - Memory mapped Axi DMA register write.
+ * @lp:                Pointer to axienet local structure
+ * @reg:       Address offset from the base address of the Axi DMA core
+ * @value:     Value to be written into the Axi DMA register
+ *
+ * This function writes the desired value into the corresponding Axi DMA
+ * register.
+ */
+
+static inline void axienet_dma_out32(struct axienet_local *lp,
+                                    off_t reg, u32 value)
+{
+       iowrite32(value, lp->dma_regs + reg);
+}
+
+#if defined(CONFIG_64BIT) && defined(iowrite64)
+/**
+ * axienet_dma_out64 - Memory mapped Axi DMA register write.
+ * @lp:                Pointer to axienet local structure
+ * @reg:       Address offset from the base address of the Axi DMA core
+ * @value:     Value to be written into the Axi DMA register
+ *
+ * This function writes the desired value into the corresponding Axi DMA
+ * register.
+ */
+static inline void axienet_dma_out64(struct axienet_local *lp,
+                                    off_t reg, u64 value)
+{
+       iowrite64(value, lp->dma_regs + reg);
+}
+
+static inline void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
+                                       dma_addr_t addr)
+{
+       if (lp->features & XAE_FEATURE_DMA_64BIT)
+               axienet_dma_out64(lp, reg, addr);
+       else
+               axienet_dma_out32(lp, reg, lower_32_bits(addr));
+}
+
+#else /* CONFIG_64BIT */
+
+static inline void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
+                                dma_addr_t addr)
+{
+       axienet_dma_out32(lp, reg, lower_32_bits(addr));
+}
+
+#endif /* CONFIG_64BIT */
+
 /* Function prototypes visible in xilinx_axienet_mdio.c for other files */
 int axienet_mdio_enable(struct axienet_local *lp);
 void axienet_mdio_disable(struct axienet_local *lp);
index 93c9f30..1760930 100644 (file)
@@ -133,30 +133,6 @@ static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg)
        return ioread32(lp->dma_regs + reg);
 }
 
-/**
- * axienet_dma_out32 - Memory mapped Axi DMA register write.
- * @lp:                Pointer to axienet local structure
- * @reg:       Address offset from the base address of the Axi DMA core
- * @value:     Value to be written into the Axi DMA register
- *
- * This function writes the desired value into the corresponding Axi DMA
- * register.
- */
-static inline void axienet_dma_out32(struct axienet_local *lp,
-                                    off_t reg, u32 value)
-{
-       iowrite32(value, lp->dma_regs + reg);
-}
-
-static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
-                                dma_addr_t addr)
-{
-       axienet_dma_out32(lp, reg, lower_32_bits(addr));
-
-       if (lp->features & XAE_FEATURE_DMA_64BIT)
-               axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
-}
-
 static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
                               struct axidma_bd *desc)
 {
@@ -2061,6 +2037,11 @@ static int axienet_probe(struct platform_device *pdev)
                        iowrite32(0x0, desc);
                }
        }
+       if (!IS_ENABLED(CONFIG_64BIT) && lp->features & XAE_FEATURE_DMA_64BIT) {
+               dev_err(&pdev->dev, "64-bit addressable DMA is not compatible with 32-bit archecture\n");
+               ret = -EINVAL;
+               goto cleanup_clk;
+       }
 
        ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width));
        if (ret) {
index 45c3c4a..9fb5675 100644 (file)
@@ -99,6 +99,7 @@ struct sixpack {
 
        unsigned int            rx_count;
        unsigned int            rx_count_cooked;
+       spinlock_t              rxlock;
 
        int                     mtu;            /* Our mtu (to spot changes!) */
        int                     buffsize;       /* Max buffers sizes */
@@ -565,6 +566,7 @@ static int sixpack_open(struct tty_struct *tty)
        sp->dev = dev;
 
        spin_lock_init(&sp->lock);
+       spin_lock_init(&sp->rxlock);
        refcount_set(&sp->refcnt, 1);
        init_completion(&sp->dead);
 
@@ -913,6 +915,7 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
                        sp->led_state = 0x60;
                        /* fill trailing bytes with zeroes */
                        sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+                       spin_lock_bh(&sp->rxlock);
                        rest = sp->rx_count;
                        if (rest != 0)
                                 for (i = rest; i <= 3; i++)
@@ -930,6 +933,7 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
                                sp_bump(sp, 0);
                        }
                        sp->rx_count_cooked = 0;
+                       spin_unlock_bh(&sp->rxlock);
                }
                break;
        case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
@@ -959,8 +963,11 @@ sixpack_decode(struct sixpack *sp, const unsigned char *pre_rbuff, int count)
                        decode_prio_command(sp, inbyte);
                else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
                        decode_std_command(sp, inbyte);
-               else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
+               else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) {
+                       spin_lock_bh(&sp->rxlock);
                        decode_data(sp, inbyte);
+                       spin_unlock_bh(&sp->rxlock);
+               }
        }
 }
 
index a8db1a1..c7047f5 100644 (file)
@@ -34,6 +34,8 @@
 #define MDIO_AN_VEND_PROV                      0xc400
 #define MDIO_AN_VEND_PROV_1000BASET_FULL       BIT(15)
 #define MDIO_AN_VEND_PROV_1000BASET_HALF       BIT(14)
+#define MDIO_AN_VEND_PROV_5000BASET_FULL       BIT(11)
+#define MDIO_AN_VEND_PROV_2500BASET_FULL       BIT(10)
 #define MDIO_AN_VEND_PROV_DOWNSHIFT_EN         BIT(4)
 #define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK       GENMASK(3, 0)
 #define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT       4
@@ -231,9 +233,20 @@ static int aqr_config_aneg(struct phy_device *phydev)
                              phydev->advertising))
                reg |= MDIO_AN_VEND_PROV_1000BASET_HALF;
 
+       /* Handle the case when the 2.5G and 5G speeds are not advertised */
+       if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+                             phydev->advertising))
+               reg |= MDIO_AN_VEND_PROV_2500BASET_FULL;
+
+       if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+                             phydev->advertising))
+               reg |= MDIO_AN_VEND_PROV_5000BASET_FULL;
+
        ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV,
                                     MDIO_AN_VEND_PROV_1000BASET_HALF |
-                                    MDIO_AN_VEND_PROV_1000BASET_FULL, reg);
+                                    MDIO_AN_VEND_PROV_1000BASET_FULL |
+                                    MDIO_AN_VEND_PROV_2500BASET_FULL |
+                                    MDIO_AN_VEND_PROV_5000BASET_FULL, reg);
        if (ret < 0)
                return ret;
        if (ret > 0)
index 6a467e7..59fe356 100644 (file)
@@ -2072,6 +2072,8 @@ static struct phy_driver at803x_driver[] = {
        /* ATHEROS AR9331 */
        PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
        .name                   = "Qualcomm Atheros AR9331 built-in PHY",
+       .probe                  = at803x_probe,
+       .remove                 = at803x_remove,
        .suspend                = at803x_suspend,
        .resume                 = at803x_resume,
        .flags                  = PHY_POLL_CABLE_TEST,
@@ -2087,6 +2089,8 @@ static struct phy_driver at803x_driver[] = {
        /* Qualcomm Atheros QCA9561 */
        PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
        .name                   = "Qualcomm Atheros QCA9561 built-in PHY",
+       .probe                  = at803x_probe,
+       .remove                 = at803x_remove,
        .suspend                = at803x_suspend,
        .resume                 = at803x_resume,
        .flags                  = PHY_POLL_CABLE_TEST,
@@ -2151,6 +2155,8 @@ static struct phy_driver at803x_driver[] = {
        PHY_ID_MATCH_EXACT(QCA8081_PHY_ID),
        .name                   = "Qualcomm QCA8081",
        .flags                  = PHY_POLL_CABLE_TEST,
+       .probe                  = at803x_probe,
+       .remove                 = at803x_remove,
        .config_intr            = at803x_config_intr,
        .handle_interrupt       = at803x_handle_interrupt,
        .get_tunable            = at803x_get_tunable,
index 1b54684..96d3c40 100644 (file)
@@ -110,7 +110,7 @@ static int smsc_phy_config_init(struct phy_device *phydev)
        struct smsc_phy_priv *priv = phydev->priv;
        int rc;
 
-       if (!priv->energy_enable)
+       if (!priv->energy_enable || phydev->irq != PHY_POLL)
                return 0;
 
        rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
@@ -210,6 +210,8 @@ static int lan95xx_config_aneg_ext(struct phy_device *phydev)
  * response on link pulses to detect presence of plugged Ethernet cable.
  * The Energy Detect Power-Down mode is enabled again in the end of procedure to
  * save approximately 220 mW of power if cable is unplugged.
+ * The workaround is only applicable to poll mode. Energy Detect Power-Down may
+ * not be used in interrupt mode lest link change detection becomes unreliable.
  */
 static int lan87xx_read_status(struct phy_device *phydev)
 {
@@ -217,7 +219,7 @@ static int lan87xx_read_status(struct phy_device *phydev)
 
        int err = genphy_read_status(phydev);
 
-       if (!phydev->link && priv->energy_enable) {
+       if (!phydev->link && priv->energy_enable && phydev->irq == PHY_POLL) {
                /* Disable EDPD to wake up PHY */
                int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
                if (rc < 0)
index 7a8c11a..4704ed6 100644 (file)
@@ -1750,7 +1750,7 @@ static const struct driver_info ax88179_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1763,7 +1763,7 @@ static const struct driver_info ax88178a_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1776,7 +1776,7 @@ static const struct driver_info cypress_GX3_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1789,7 +1789,7 @@ static const struct driver_info dlink_dub1312_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1802,7 +1802,7 @@ static const struct driver_info sitecom_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1815,7 +1815,7 @@ static const struct driver_info samsung_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1828,7 +1828,7 @@ static const struct driver_info lenovo_info = {
        .link_reset = ax88179_link_reset,
        .reset = ax88179_reset,
        .stop = ax88179_stop,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1841,7 +1841,7 @@ static const struct driver_info belkin_info = {
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
        .stop   = ax88179_stop,
-       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1854,7 +1854,7 @@ static const struct driver_info toshiba_info = {
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
        .stop = ax88179_stop,
-       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1867,7 +1867,7 @@ static const struct driver_info mct_info = {
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
        .stop   = ax88179_stop,
-       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1880,7 +1880,7 @@ static const struct driver_info at_umc2000_info = {
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
        .stop   = ax88179_stop,
-       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1893,7 +1893,7 @@ static const struct driver_info at_umc200_info = {
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
        .stop   = ax88179_stop,
-       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
@@ -1906,7 +1906,7 @@ static const struct driver_info at_umc2000sp_info = {
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
        .stop   = ax88179_stop,
-       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
 };
index 466da01..2cb833b 100644 (file)
@@ -312,6 +312,7 @@ static bool veth_skb_is_eligible_for_gro(const struct net_device *dev,
 static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
+       struct netdev_queue *queue = NULL;
        struct veth_rq *rq = NULL;
        struct net_device *rcv;
        int length = skb->len;
@@ -329,6 +330,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
        rxq = skb_get_queue_mapping(skb);
        if (rxq < rcv->real_num_rx_queues) {
                rq = &rcv_priv->rq[rxq];
+               queue = netdev_get_tx_queue(dev, rxq);
 
                /* The napi pointer is available when an XDP program is
                 * attached or when GRO is enabled
@@ -340,6 +342,8 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
 
        skb_tx_timestamp(skb);
        if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) {
+               if (queue)
+                       txq_trans_cond_update(queue);
                if (!use_napi)
                        dev_lstats_add(dev, length);
        } else {
index db05b5e..969a679 100644 (file)
@@ -2768,7 +2768,6 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
 static void virtnet_freeze_down(struct virtio_device *vdev)
 {
        struct virtnet_info *vi = vdev->priv;
-       int i;
 
        /* Make sure no work handler is accessing the device */
        flush_work(&vi->config_work);
@@ -2776,14 +2775,8 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
        netif_tx_lock_bh(vi->dev);
        netif_device_detach(vi->dev);
        netif_tx_unlock_bh(vi->dev);
-       cancel_delayed_work_sync(&vi->refill);
-
-       if (netif_running(vi->dev)) {
-               for (i = 0; i < vi->max_queue_pairs; i++) {
-                       napi_disable(&vi->rq[i].napi);
-                       virtnet_napi_tx_disable(&vi->sq[i].napi);
-               }
-       }
+       if (netif_running(vi->dev))
+               virtnet_close(vi->dev);
 }
 
 static int init_vqs(struct virtnet_info *vi);
@@ -2791,7 +2784,7 @@ static int init_vqs(struct virtnet_info *vi);
 static int virtnet_restore_up(struct virtio_device *vdev)
 {
        struct virtnet_info *vi = vdev->priv;
-       int err, i;
+       int err;
 
        err = init_vqs(vi);
        if (err)
@@ -2800,15 +2793,9 @@ static int virtnet_restore_up(struct virtio_device *vdev)
        virtio_device_ready(vdev);
 
        if (netif_running(vi->dev)) {
-               for (i = 0; i < vi->curr_queue_pairs; i++)
-                       if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
-                               schedule_delayed_work(&vi->refill, 0);
-
-               for (i = 0; i < vi->max_queue_pairs; i++) {
-                       virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
-                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
-                                              &vi->sq[i].napi);
-               }
+               err = virtnet_open(vi->dev);
+               if (err)
+                       return err;
        }
 
        netif_tx_lock_bh(vi->dev);
index 24165da..3ab2cfd 100644 (file)
@@ -3285,8 +3285,8 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
         * we have no UUID set
         */
        if (uuid_is_null(&ids->uuid)) {
-               printk_ratelimited(KERN_WARNING
-                                  "No UUID available providing old NGUID\n");
+               dev_warn_ratelimited(dev,
+                       "No UUID available providing old NGUID\n");
                return sysfs_emit(buf, "%pU\n", ids->nguid);
        }
        return sysfs_emit(buf, "%pU\n", &ids->uuid);
@@ -3863,6 +3863,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
        if (ret) {
                dev_err(ctrl->device,
                        "globally duplicate IDs for nsid %d\n", nsid);
+               nvme_print_device_info(ctrl);
                return ret;
        }
 
index 9b72b6e..0da94b2 100644 (file)
@@ -503,6 +503,7 @@ struct nvme_ctrl_ops {
        void (*submit_async_event)(struct nvme_ctrl *ctrl);
        void (*delete_ctrl)(struct nvme_ctrl *ctrl);
        int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
+       void (*print_device_info)(struct nvme_ctrl *ctrl);
 };
 
 /*
@@ -548,6 +549,33 @@ static inline struct request *nvme_cid_to_rq(struct blk_mq_tags *tags,
        return blk_mq_tag_to_rq(tags, nvme_tag_from_cid(command_id));
 }
 
+/*
+ * Return the length of the string without the space padding
+ */
+static inline int nvme_strlen(char *s, int len)
+{
+       while (s[len - 1] == ' ')
+               len--;
+       return len;
+}
+
+static inline void nvme_print_device_info(struct nvme_ctrl *ctrl)
+{
+       struct nvme_subsystem *subsys = ctrl->subsys;
+
+       if (ctrl->ops->print_device_info) {
+               ctrl->ops->print_device_info(ctrl);
+               return;
+       }
+
+       dev_err(ctrl->device,
+               "VID:%04x model:%.*s firmware:%.*s\n", subsys->vendor_id,
+               nvme_strlen(subsys->model, sizeof(subsys->model)),
+               subsys->model, nvme_strlen(subsys->firmware_rev,
+                                          sizeof(subsys->firmware_rev)),
+               subsys->firmware_rev);
+}
+
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
 void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
                            const char *dev_name);
index 48f4f6e..c7012e8 100644 (file)
@@ -1334,6 +1334,14 @@ static void nvme_warn_reset(struct nvme_dev *dev, u32 csts)
                dev_warn(dev->ctrl.device,
                         "controller is down; will reset: CSTS=0x%x, PCI_STATUS read failed (%d)\n",
                         csts, result);
+
+       if (csts != ~0)
+               return;
+
+       dev_warn(dev->ctrl.device,
+                "Does your device have a faulty power saving mode enabled?\n");
+       dev_warn(dev->ctrl.device,
+                "Try \"nvme_core.default_ps_max_latency_us=0 pcie_aspm=off\" and report a bug\n");
 }
 
 static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
@@ -2976,6 +2984,21 @@ static int nvme_pci_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
        return snprintf(buf, size, "%s\n", dev_name(&pdev->dev));
 }
 
+
+static void nvme_pci_print_device_info(struct nvme_ctrl *ctrl)
+{
+       struct pci_dev *pdev = to_pci_dev(to_nvme_dev(ctrl)->dev);
+       struct nvme_subsystem *subsys = ctrl->subsys;
+
+       dev_err(ctrl->device,
+               "VID:DID %04x:%04x model:%.*s firmware:%.*s\n",
+               pdev->vendor, pdev->device,
+               nvme_strlen(subsys->model, sizeof(subsys->model)),
+               subsys->model, nvme_strlen(subsys->firmware_rev,
+                                          sizeof(subsys->firmware_rev)),
+               subsys->firmware_rev);
+}
+
 static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
        .name                   = "pcie",
        .module                 = THIS_MODULE,
@@ -2987,6 +3010,7 @@ static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
        .free_ctrl              = nvme_pci_free_ctrl,
        .submit_async_event     = nvme_pci_submit_async_event,
        .get_address            = nvme_pci_get_address,
+       .print_device_info      = nvme_pci_print_device_info,
 };
 
 static int nvme_dev_map(struct nvme_dev *dev)
@@ -3421,7 +3445,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(REDHAT, 0x0010),  /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x126f, 0x2263),   /* Silicon Motion unidentified */
-               .driver_data = NVME_QUIRK_NO_NS_DESC_LIST, },
+               .driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
+                               NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1bb1, 0x0100),   /* Seagate Nytro Flash Storage */
                .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
                                NVME_QUIRK_NO_NS_DESC_LIST, },
@@ -3437,6 +3462,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
                                NVME_QUIRK_DISABLE_WRITE_ZEROES|
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+       { PCI_DEVICE(0x1987, 0x5012),   /* Phison E12 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1987, 0x5016),   /* Phison E16 */
                .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE(0x1b4b, 0x1092),   /* Lexar 256 GB SSD */
@@ -3449,10 +3476,20 @@ static const struct pci_device_id nvme_id_table[] = {
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE(0x1c5c, 0x1504),   /* SK Hynix PC400 */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x1c5c, 0x174a),   /* SK Hynix P31 SSD */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x15b7, 0x2001),   /*  Sandisk Skyhawk */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x1d97, 0x2263),   /* SPCC */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x144d, 0xa80b),   /* Samsung PM9B1 256G and 512G */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x144d, 0xa809),   /* Samsung MZALQ256HBJD 256G */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x1cc4, 0x6303),   /* UMIS RPJTJ512MGE1QDY 512G */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x1cc4, 0x6302),   /* UMIS RPJTJ256MGE1QDY 256G */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x2646, 0x2262),   /* KINGSTON SKC2000 NVMe SSD */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
        { PCI_DEVICE(0x2646, 0x2263),   /* KINGSTON A2000 NVMe SSD  */
@@ -3463,6 +3500,10 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1e4B, 0x1202),   /* MAXIO MAP1202 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1cc1, 0x5350),   /* ADATA XPG GAMMIX S50 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1e49, 0x0041),   /* ZHITAI TiPro7000 NVMe SSD */
+               .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061),
                .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065),
index d0eab57..00684e1 100644 (file)
@@ -160,8 +160,8 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *);
 static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *);
 static void ibmvfc_tgt_move_login(struct ibmvfc_target *);
 
-static void ibmvfc_release_sub_crqs(struct ibmvfc_host *);
-static void ibmvfc_init_sub_crqs(struct ibmvfc_host *);
+static void ibmvfc_dereg_sub_crqs(struct ibmvfc_host *);
+static void ibmvfc_reg_sub_crqs(struct ibmvfc_host *);
 
 static const char *unknown_error = "unknown error";
 
@@ -917,7 +917,7 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
        struct vio_dev *vdev = to_vio_dev(vhost->dev);
        unsigned long flags;
 
-       ibmvfc_release_sub_crqs(vhost);
+       ibmvfc_dereg_sub_crqs(vhost);
 
        /* Re-enable the CRQ */
        do {
@@ -936,7 +936,7 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
        spin_unlock(vhost->crq.q_lock);
        spin_unlock_irqrestore(vhost->host->host_lock, flags);
 
-       ibmvfc_init_sub_crqs(vhost);
+       ibmvfc_reg_sub_crqs(vhost);
 
        return rc;
 }
@@ -955,7 +955,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
        struct vio_dev *vdev = to_vio_dev(vhost->dev);
        struct ibmvfc_queue *crq = &vhost->crq;
 
-       ibmvfc_release_sub_crqs(vhost);
+       ibmvfc_dereg_sub_crqs(vhost);
 
        /* Close the CRQ */
        do {
@@ -988,7 +988,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
        spin_unlock(vhost->crq.q_lock);
        spin_unlock_irqrestore(vhost->host->host_lock, flags);
 
-       ibmvfc_init_sub_crqs(vhost);
+       ibmvfc_reg_sub_crqs(vhost);
 
        return rc;
 }
@@ -5682,6 +5682,8 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
        queue->cur = 0;
        queue->fmt = fmt;
        queue->size = PAGE_SIZE / fmt_size;
+
+       queue->vhost = vhost;
        return 0;
 }
 
@@ -5757,9 +5759,6 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
 
        ENTER;
 
-       if (ibmvfc_alloc_queue(vhost, scrq, IBMVFC_SUB_CRQ_FMT))
-               return -ENOMEM;
-
        rc = h_reg_sub_crq(vdev->unit_address, scrq->msg_token, PAGE_SIZE,
                           &scrq->cookie, &scrq->hw_irq);
 
@@ -5790,7 +5789,6 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
        }
 
        scrq->hwq_id = index;
-       scrq->vhost = vhost;
 
        LEAVE;
        return 0;
@@ -5800,7 +5798,6 @@ irq_failed:
                rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie);
        } while (rtas_busy_delay(rc));
 reg_failed:
-       ibmvfc_free_queue(vhost, scrq);
        LEAVE;
        return rc;
 }
@@ -5826,12 +5823,50 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
        if (rc)
                dev_err(dev, "Failed to free sub-crq[%d]: rc=%ld\n", index, rc);
 
-       ibmvfc_free_queue(vhost, scrq);
+       /* Clean out the queue */
+       memset(scrq->msgs.crq, 0, PAGE_SIZE);
+       scrq->cur = 0;
+
+       LEAVE;
+}
+
+static void ibmvfc_reg_sub_crqs(struct ibmvfc_host *vhost)
+{
+       int i, j;
+
+       ENTER;
+       if (!vhost->mq_enabled || !vhost->scsi_scrqs.scrqs)
+               return;
+
+       for (i = 0; i < nr_scsi_hw_queues; i++) {
+               if (ibmvfc_register_scsi_channel(vhost, i)) {
+                       for (j = i; j > 0; j--)
+                               ibmvfc_deregister_scsi_channel(vhost, j - 1);
+                       vhost->do_enquiry = 0;
+                       return;
+               }
+       }
+
+       LEAVE;
+}
+
+static void ibmvfc_dereg_sub_crqs(struct ibmvfc_host *vhost)
+{
+       int i;
+
+       ENTER;
+       if (!vhost->mq_enabled || !vhost->scsi_scrqs.scrqs)
+               return;
+
+       for (i = 0; i < nr_scsi_hw_queues; i++)
+               ibmvfc_deregister_scsi_channel(vhost, i);
+
        LEAVE;
 }
 
 static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
 {
+       struct ibmvfc_queue *scrq;
        int i, j;
 
        ENTER;
@@ -5847,30 +5882,41 @@ static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
        }
 
        for (i = 0; i < nr_scsi_hw_queues; i++) {
-               if (ibmvfc_register_scsi_channel(vhost, i)) {
-                       for (j = i; j > 0; j--)
-                               ibmvfc_deregister_scsi_channel(vhost, j - 1);
+               scrq = &vhost->scsi_scrqs.scrqs[i];
+               if (ibmvfc_alloc_queue(vhost, scrq, IBMVFC_SUB_CRQ_FMT)) {
+                       for (j = i; j > 0; j--) {
+                               scrq = &vhost->scsi_scrqs.scrqs[j - 1];
+                               ibmvfc_free_queue(vhost, scrq);
+                       }
                        kfree(vhost->scsi_scrqs.scrqs);
                        vhost->scsi_scrqs.scrqs = NULL;
                        vhost->scsi_scrqs.active_queues = 0;
                        vhost->do_enquiry = 0;
-                       break;
+                       vhost->mq_enabled = 0;
+                       return;
                }
        }
 
+       ibmvfc_reg_sub_crqs(vhost);
+
        LEAVE;
 }
 
 static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost)
 {
+       struct ibmvfc_queue *scrq;
        int i;
 
        ENTER;
        if (!vhost->scsi_scrqs.scrqs)
                return;
 
-       for (i = 0; i < nr_scsi_hw_queues; i++)
-               ibmvfc_deregister_scsi_channel(vhost, i);
+       ibmvfc_dereg_sub_crqs(vhost);
+
+       for (i = 0; i < nr_scsi_hw_queues; i++) {
+               scrq = &vhost->scsi_scrqs.scrqs[i];
+               ibmvfc_free_queue(vhost, scrq);
+       }
 
        kfree(vhost->scsi_scrqs.scrqs);
        vhost->scsi_scrqs.scrqs = NULL;
index 3718406..c39a245 100644 (file)
@@ -789,6 +789,7 @@ struct ibmvfc_queue {
        spinlock_t _lock;
        spinlock_t *q_lock;
 
+       struct ibmvfc_host *vhost;
        struct ibmvfc_event_pool evt_pool;
        struct list_head sent;
        struct list_head free;
@@ -797,7 +798,6 @@ struct ibmvfc_queue {
        union ibmvfc_iu cancel_rsp;
 
        /* Sub-CRQ fields */
-       struct ibmvfc_host *vhost;
        unsigned long cookie;
        unsigned long vios_cookie;
        unsigned long hw_irq;
index 1f423f7..b8a76b8 100644 (file)
@@ -2826,6 +2826,24 @@ static void zbc_open_zone(struct sdebug_dev_info *devip,
        }
 }
 
+static inline void zbc_set_zone_full(struct sdebug_dev_info *devip,
+                                    struct sdeb_zone_state *zsp)
+{
+       switch (zsp->z_cond) {
+       case ZC2_IMPLICIT_OPEN:
+               devip->nr_imp_open--;
+               break;
+       case ZC3_EXPLICIT_OPEN:
+               devip->nr_exp_open--;
+               break;
+       default:
+               WARN_ONCE(true, "Invalid zone %llu condition %x\n",
+                         zsp->z_start, zsp->z_cond);
+               break;
+       }
+       zsp->z_cond = ZC5_FULL;
+}
+
 static void zbc_inc_wp(struct sdebug_dev_info *devip,
                       unsigned long long lba, unsigned int num)
 {
@@ -2838,7 +2856,7 @@ static void zbc_inc_wp(struct sdebug_dev_info *devip,
        if (zsp->z_type == ZBC_ZTYPE_SWR) {
                zsp->z_wp += num;
                if (zsp->z_wp >= zend)
-                       zsp->z_cond = ZC5_FULL;
+                       zbc_set_zone_full(devip, zsp);
                return;
        }
 
@@ -2857,7 +2875,7 @@ static void zbc_inc_wp(struct sdebug_dev_info *devip,
                        n = num;
                }
                if (zsp->z_wp >= zend)
-                       zsp->z_cond = ZC5_FULL;
+                       zbc_set_zone_full(devip, zsp);
 
                num -= n;
                lba += n;
index 2c0dd64..5d21f07 100644 (file)
@@ -212,7 +212,12 @@ iscsi_create_endpoint(int dd_size)
                return NULL;
 
        mutex_lock(&iscsi_ep_idr_mutex);
-       id = idr_alloc(&iscsi_ep_idr, ep, 0, -1, GFP_NOIO);
+
+       /*
+        * First endpoint id should be 1 to comply with user space
+        * applications (iscsid).
+        */
+       id = idr_alloc(&iscsi_ep_idr, ep, 1, -1, GFP_NOIO);
        if (id < 0) {
                mutex_unlock(&iscsi_ep_idr_mutex);
                printk(KERN_ERR "Could not allocate endpoint ID. Error %d.\n",
index ca35309..fe000da 100644 (file)
@@ -1844,7 +1844,7 @@ static struct scsi_host_template scsi_driver = {
        .cmd_per_lun =          2048,
        .this_id =              -1,
        /* Ensure there are no gaps in presented sgls */
-       .virt_boundary_mask =   PAGE_SIZE-1,
+       .virt_boundary_mask =   HV_HYP_PAGE_SIZE - 1,
        .no_write_same =        1,
        .track_queue_depth =    1,
        .change_queue_depth =   storvsc_change_queue_depth,
@@ -1895,6 +1895,7 @@ static int storvsc_probe(struct hv_device *device,
        int target = 0;
        struct storvsc_device *stor_device;
        int max_sub_channels = 0;
+       u32 max_xfer_bytes;
 
        /*
         * We support sub-channels for storage on SCSI and FC controllers.
@@ -1968,12 +1969,28 @@ static int storvsc_probe(struct hv_device *device,
        }
        /* max cmd length */
        host->max_cmd_len = STORVSC_MAX_CMD_LEN;
-
        /*
-        * set the table size based on the info we got
-        * from the host.
+        * Any reasonable Hyper-V configuration should provide
+        * max_transfer_bytes value aligning to HV_HYP_PAGE_SIZE,
+        * protecting it from any weird value.
+        */
+       max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE);
+       /* max_hw_sectors_kb */
+       host->max_sectors = max_xfer_bytes >> 9;
+       /*
+        * There are 2 requirements for Hyper-V storvsc sgl segments,
+        * based on which the below calculation for max segments is
+        * done:
+        *
+        * 1. Except for the first and last sgl segment, all sgl segments
+        *    should be align to HV_HYP_PAGE_SIZE, that also means the
+        *    maximum number of segments in a sgl can be calculated by
+        *    dividing the total max transfer length by HV_HYP_PAGE_SIZE.
+        *
+        * 2. Except for the first and last, each entry in the SGL must
+        *    have an offset that is a multiple of HV_HYP_PAGE_SIZE.
         */
-       host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT);
+       host->sg_tablesize = (max_xfer_bytes >> HV_HYP_PAGE_SHIFT) + 1;
        /*
         * For non-IDE disks, the host supports multiple channels.
         * Set the number of HW queues we are supporting.
index d1a0dea..d0ba34c 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 config FB_OLPC_DCON
        tristate "One Laptop Per Child Display CONtroller support"
-       depends on OLPC && FB
+       depends on OLPC && FB && BROKEN
        depends on I2C
        depends on GPIO_CS5535 && ACPI
        select BACKLIGHT_CLASS_DEVICE
index 3d8e9de..7135d89 100644 (file)
@@ -178,8 +178,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
 
        pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
 
-       res = rtw_alloc_hwxmits(padapter);
-       if (res) {
+       if (rtw_alloc_hwxmits(padapter)) {
                res = _FAIL;
                goto exit;
        }
@@ -1483,19 +1482,10 @@ int rtw_alloc_hwxmits(struct adapter *padapter)
 
        hwxmits = pxmitpriv->hwxmits;
 
-       if (pxmitpriv->hwxmit_entry == 5) {
-               hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
-               hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
-               hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
-               hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
-               hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
-       } else if (pxmitpriv->hwxmit_entry == 4) {
-               hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
-               hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
-               hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
-               hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
-       } else {
-       }
+       hwxmits[0].sta_queue = &pxmitpriv->vo_pending;
+       hwxmits[1].sta_queue = &pxmitpriv->vi_pending;
+       hwxmits[2].sta_queue = &pxmitpriv->be_pending;
+       hwxmits[3].sta_queue = &pxmitpriv->bk_pending;
 
        return 0;
 }
index 1b09462..8dd280e 100644 (file)
@@ -403,7 +403,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
 
                if (wep_key_len > 0) {
                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
-                       wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial);
+                       wep_total_len = wep_key_len + sizeof(*pwep);
                        pwep = kzalloc(wep_total_len, GFP_KERNEL);
                        if (!pwep)
                                goto exit;
index ece97e3..30374a8 100644 (file)
@@ -90,7 +90,8 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
                if (wep_key_len > 0) {
                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
-                       pwep = kzalloc(wep_total_len, GFP_KERNEL);
+                       /* Allocate a full structure to avoid potentially running off the end. */
+                       pwep = kzalloc(sizeof(*pwep), GFP_KERNEL);
                        if (!pwep) {
                                ret = -ENOMEM;
                                goto exit;
@@ -582,7 +583,8 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
                if (wep_key_len > 0) {
                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
-                       pwep = kzalloc(wep_total_len, GFP_KERNEL);
+                       /* Allocate a full structure to avoid potentially running off the end. */
+                       pwep = kzalloc(sizeof(*pwep), GFP_KERNEL);
                        if (!pwep)
                                goto exit;
 
index c7968ae..d02de3f 100644 (file)
@@ -426,7 +426,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
        tty_unregister_device(goldfish_tty_driver, qtty->console.index);
        iounmap(qtty->base);
        qtty->base = NULL;
-       free_irq(qtty->irq, pdev);
+       free_irq(qtty->irq, qtty);
        tty_port_destroy(&qtty->port);
        goldfish_tty_current_line_count--;
        if (goldfish_tty_current_line_count == 0)
index 137eebd..fd4d24f 100644 (file)
@@ -455,7 +455,7 @@ static void gsm_hex_dump_bytes(const char *fname, const u8 *data,
                return;
        }
 
-       prefix = kasprintf(GFP_KERNEL, "%s: ", fname);
+       prefix = kasprintf(GFP_ATOMIC, "%s: ", fname);
        if (!prefix)
                return;
        print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 16, 1, data, len,
index 78b6ded..8f32fe9 100644 (file)
@@ -1517,6 +1517,8 @@ static inline void __stop_tx(struct uart_8250_port *p)
                unsigned char lsr = serial_in(p, UART_LSR);
                u64 stop_delay = 0;
 
+               p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+
                if (!(lsr & UART_LSR_THRE))
                        return;
                /*
index 4733a23..f8f9506 100644 (file)
@@ -1306,6 +1306,7 @@ static const struct uart_ops qcom_geni_console_pops = {
        .stop_tx = qcom_geni_serial_stop_tx,
        .start_tx = qcom_geni_serial_start_tx,
        .stop_rx = qcom_geni_serial_stop_rx,
+       .start_rx = qcom_geni_serial_start_rx,
        .set_termios = qcom_geni_serial_set_termios,
        .startup = qcom_geni_serial_startup,
        .request_port = qcom_geni_serial_request_port,
index 9a85b41..338ebad 100644 (file)
@@ -2214,11 +2214,12 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
        /*
         * Nothing to do if the console is not suspending
         * except stop_rx to prevent any asynchronous data
-        * over RX line. Re-start_rx, when required, is
-        * done by set_termios in resume sequence
+        * over RX line. However ensure that we will be
+        * able to Re-start_rx later.
         */
        if (!console_suspend_enabled && uart_console(uport)) {
-               uport->ops->stop_rx(uport);
+               if (uport->ops->start_rx)
+                       uport->ops->stop_rx(uport);
                goto unlock;
        }
 
@@ -2310,6 +2311,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
                if (console_suspend_enabled)
                        uart_change_pm(state, UART_PM_STATE_ON);
                uport->ops->set_termios(uport, &termios, NULL);
+               if (!console_suspend_enabled && uport->ops->start_rx)
+                       uport->ops->start_rx(uport);
                if (console_suspend_enabled)
                        console_start(uport->cons);
        }
index 18e6233..d2b2720 100644 (file)
@@ -581,7 +581,6 @@ void __handle_sysrq(int key, bool check_mask)
 
        rcu_sysrq_start();
        rcu_read_lock();
-       printk_prefer_direct_enter();
        /*
         * Raise the apparent loglevel to maximum so that the sysrq header
         * is shown to provide the user with positive feedback.  We do not
@@ -623,7 +622,6 @@ void __handle_sysrq(int key, bool check_mask)
                pr_cont("\n");
                console_loglevel = orig_log_level;
        }
-       printk_prefer_direct_exit();
        rcu_read_unlock();
        rcu_sysrq_end();
 
index 01fb4ba..ce86d1b 100644 (file)
@@ -748,17 +748,28 @@ static enum utp_ocs ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp)
 }
 
 /**
- * ufshcd_utrl_clear - Clear a bit in UTRLCLR register
+ * ufshcd_utrl_clear() - Clear requests from the controller request list.
  * @hba: per adapter instance
- * @pos: position of the bit to be cleared
+ * @mask: mask with one bit set for each request to be cleared
  */
-static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
+static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 mask)
 {
        if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR)
-               ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
-       else
-               ufshcd_writel(hba, ~(1 << pos),
-                               REG_UTP_TRANSFER_REQ_LIST_CLEAR);
+               mask = ~mask;
+       /*
+        * From the UFSHCI specification: "UTP Transfer Request List CLear
+        * Register (UTRLCLR): This field is bit significant. Each bit
+        * corresponds to a slot in the UTP Transfer Request List, where bit 0
+        * corresponds to request slot 0. A bit in this field is set to ‘0’
+        * by host software to indicate to the host controller that a transfer
+        * request slot is cleared. The host controller
+        * shall free up any resources associated to the request slot
+        * immediately, and shall set the associated bit in UTRLDBR to ‘0’. The
+        * host software indicates no change to request slots by setting the
+        * associated bits in this field to ‘1’. Bits in this field shall only
+        * be set ‘1’ or ‘0’ by host software when UTRLRSR is set to ‘1’."
+        */
+       ufshcd_writel(hba, ~mask, REG_UTP_TRANSFER_REQ_LIST_CLEAR);
 }
 
 /**
@@ -2863,27 +2874,26 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
        return ufshcd_compose_devman_upiu(hba, lrbp);
 }
 
-static int
-ufshcd_clear_cmd(struct ufs_hba *hba, int tag)
+/*
+ * Clear all the requests from the controller for which a bit has been set in
+ * @mask and wait until the controller confirms that these requests have been
+ * cleared.
+ */
+static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask)
 {
-       int err = 0;
        unsigned long flags;
-       u32 mask = 1 << tag;
 
        /* clear outstanding transaction before retry */
        spin_lock_irqsave(hba->host->host_lock, flags);
-       ufshcd_utrl_clear(hba, tag);
+       ufshcd_utrl_clear(hba, mask);
        spin_unlock_irqrestore(hba->host->host_lock, flags);
 
        /*
         * wait for h/w to clear corresponding bit in door-bell.
         * max. wait is 1 sec.
         */
-       err = ufshcd_wait_for_register(hba,
-                       REG_UTP_TRANSFER_REQ_DOOR_BELL,
-                       mask, ~mask, 1000, 1000);
-
-       return err;
+       return ufshcd_wait_for_register(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL,
+                                       mask, ~mask, 1000, 1000);
 }
 
 static int
@@ -2963,7 +2973,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
                err = -ETIMEDOUT;
                dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
                        __func__, lrbp->task_tag);
-               if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
+               if (!ufshcd_clear_cmds(hba, 1U << lrbp->task_tag))
                        /* successfully cleared the command, retry if needed */
                        err = -EAGAIN;
                /*
@@ -6958,14 +6968,14 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 }
 
 /**
- * ufshcd_eh_device_reset_handler - device reset handler registered to
- *                                    scsi layer.
+ * ufshcd_eh_device_reset_handler() - Reset a single logical unit.
  * @cmd: SCSI command pointer
  *
  * Returns SUCCESS/FAILED
  */
 static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
 {
+       unsigned long flags, pending_reqs = 0, not_cleared = 0;
        struct Scsi_Host *host;
        struct ufs_hba *hba;
        u32 pos;
@@ -6984,14 +6994,24 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
        }
 
        /* clear the commands that were pending for corresponding LUN */
-       for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs) {
-               if (hba->lrb[pos].lun == lun) {
-                       err = ufshcd_clear_cmd(hba, pos);
-                       if (err)
-                               break;
-                       __ufshcd_transfer_req_compl(hba, 1U << pos);
-               }
+       spin_lock_irqsave(&hba->outstanding_lock, flags);
+       for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs)
+               if (hba->lrb[pos].lun == lun)
+                       __set_bit(pos, &pending_reqs);
+       hba->outstanding_reqs &= ~pending_reqs;
+       spin_unlock_irqrestore(&hba->outstanding_lock, flags);
+
+       if (ufshcd_clear_cmds(hba, pending_reqs) < 0) {
+               spin_lock_irqsave(&hba->outstanding_lock, flags);
+               not_cleared = pending_reqs &
+                       ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+               hba->outstanding_reqs |= not_cleared;
+               spin_unlock_irqrestore(&hba->outstanding_lock, flags);
+
+               dev_err(hba->dev, "%s: failed to clear requests %#lx\n",
+                       __func__, not_cleared);
        }
+       __ufshcd_transfer_req_compl(hba, pending_reqs & ~not_cleared);
 
 out:
        hba->req_abort_count = 0;
@@ -7088,7 +7108,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
                goto out;
        }
 
-       err = ufshcd_clear_cmd(hba, tag);
+       err = ufshcd_clear_cmds(hba, 1U << tag);
        if (err)
                dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
                        __func__, tag, err);
index e45c3d6..794e413 100644 (file)
@@ -1941,13 +1941,16 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
                }
 
                if (enqd_len + trb_buff_len >= full_len) {
-                       if (need_zero_pkt)
-                               zero_len_trb = !zero_len_trb;
-
-                       field &= ~TRB_CHAIN;
-                       field |= TRB_IOC;
-                       more_trbs_coming = false;
-                       preq->td.last_trb = ring->enqueue;
+                       if (need_zero_pkt && !zero_len_trb) {
+                               zero_len_trb = true;
+                       } else {
+                               zero_len_trb = false;
+                               field &= ~TRB_CHAIN;
+                               field |= TRB_IOC;
+                               more_trbs_coming = false;
+                               need_zero_pkt = false;
+                               preq->td.last_trb = ring->enqueue;
+                       }
                }
 
                /* Only set interrupt on short packet for OUT endpoints. */
@@ -1962,7 +1965,7 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
                length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
 
-               cdnsp_queue_trb(pdev, ring, more_trbs_coming | zero_len_trb,
+               cdnsp_queue_trb(pdev, ring, more_trbs_coming,
                                lower_32_bits(send_addr),
                                upper_32_bits(send_addr),
                                length_field,
index f63a27d..3f107a0 100644 (file)
@@ -5190,7 +5190,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                retval = -EINVAL;
-               goto error1;
+               goto error2;
        }
        hcd->rsrc_start = res->start;
        hcd->rsrc_len = resource_size(res);
index e027c04..5734219 100644 (file)
@@ -1644,13 +1644,8 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
         * This device property is for kernel internal use only and
         * is expected to be set by the glue code.
         */
-       if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
-               edev = extcon_get_extcon_dev(name);
-               if (!edev)
-                       return ERR_PTR(-EPROBE_DEFER);
-
-               return edev;
-       }
+       if (device_property_read_string(dev, "linux,extcon-name", &name) == 0)
+               return extcon_get_extcon_dev(name);
 
        /*
         * Try to get an extcon device from the USB PHY controller's "port"
index ba51de7..6b01804 100644 (file)
@@ -127,6 +127,7 @@ static const struct property_entry dwc3_pci_intel_phy_charger_detect_properties[
        PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
        PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
        PROPERTY_ENTRY_BOOL("linux,phy_charger_detect"),
+       PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
        {}
 };
 
index 00427d1..8716bec 100644 (file)
@@ -2976,6 +2976,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
        struct dwc3 *dwc = dep->dwc;
        u32 mdwidth;
        int size;
+       int maxpacket;
 
        mdwidth = dwc3_mdwidth(dwc);
 
@@ -2988,21 +2989,24 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
        else
                size = DWC31_GTXFIFOSIZ_TXFDEP(size);
 
-       /* FIFO Depth is in MDWDITH bytes. Multiply */
-       size *= mdwidth;
-
        /*
-        * To meet performance requirement, a minimum TxFIFO size of 3x
-        * MaxPacketSize is recommended for endpoints that support burst and a
-        * minimum TxFIFO size of 2x MaxPacketSize for endpoints that don't
-        * support burst. Use those numbers and we can calculate the max packet
-        * limit as below.
+        * maxpacket size is determined as part of the following, after assuming
+        * a mult value of one maxpacket:
+        * DWC3 revision 280A and prior:
+        * fifo_size = mult * (max_packet / mdwidth) + 1;
+        * maxpacket = mdwidth * (fifo_size - 1);
+        *
+        * DWC3 revision 290A and onwards:
+        * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
+        * maxpacket = mdwidth * ((fifo_size - 1) - 1) - mdwidth;
         */
-       if (dwc->maximum_speed >= USB_SPEED_SUPER)
-               size /= 3;
+       if (DWC3_VER_IS_PRIOR(DWC3, 290A))
+               maxpacket = mdwidth * (size - 1);
        else
-               size /= 2;
+               maxpacket = mdwidth * ((size - 1) - 1) - mdwidth;
 
+       /* Functionally, space for one max packet is sufficient */
+       size = min_t(int, maxpacket, 1024);
        usb_ep_set_maxpacket_limit(&dep->endpoint, size);
 
        dep->endpoint.max_streams = 16;
index 4585ee3..e0fa4b1 100644 (file)
@@ -122,8 +122,6 @@ struct ffs_ep {
        struct usb_endpoint_descriptor  *descs[3];
 
        u8                              num;
-
-       int                             status; /* P: epfile->mutex */
 };
 
 struct ffs_epfile {
@@ -227,6 +225,9 @@ struct ffs_io_data {
        bool use_sg;
 
        struct ffs_data *ffs;
+
+       int status;
+       struct completion done;
 };
 
 struct ffs_desc_helper {
@@ -707,12 +708,15 @@ static const struct file_operations ffs_ep0_operations = {
 
 static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
 {
+       struct ffs_io_data *io_data = req->context;
+
        ENTER();
-       if (req->context) {
-               struct ffs_ep *ep = _ep->driver_data;
-               ep->status = req->status ? req->status : req->actual;
-               complete(req->context);
-       }
+       if (req->status)
+               io_data->status = req->status;
+       else
+               io_data->status = req->actual;
+
+       complete(&io_data->done);
 }
 
 static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter)
@@ -1050,7 +1054,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
                WARN(1, "%s: data_len == -EINVAL\n", __func__);
                ret = -EINVAL;
        } else if (!io_data->aio) {
-               DECLARE_COMPLETION_ONSTACK(done);
                bool interrupted = false;
 
                req = ep->req;
@@ -1066,7 +1069,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
 
                io_data->buf = data;
 
-               req->context  = &done;
+               init_completion(&io_data->done);
+               req->context  = io_data;
                req->complete = ffs_epfile_io_complete;
 
                ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
@@ -1075,7 +1079,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
 
                spin_unlock_irq(&epfile->ffs->eps_lock);
 
-               if (wait_for_completion_interruptible(&done)) {
+               if (wait_for_completion_interruptible(&io_data->done)) {
+                       spin_lock_irq(&epfile->ffs->eps_lock);
+                       if (epfile->ep != ep) {
+                               ret = -ESHUTDOWN;
+                               goto error_lock;
+                       }
                        /*
                         * To avoid race condition with ffs_epfile_io_complete,
                         * dequeue the request first then check
@@ -1083,17 +1092,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
                         * condition with req->complete callback.
                         */
                        usb_ep_dequeue(ep->ep, req);
-                       wait_for_completion(&done);
-                       interrupted = ep->status < 0;
+                       spin_unlock_irq(&epfile->ffs->eps_lock);
+                       wait_for_completion(&io_data->done);
+                       interrupted = io_data->status < 0;
                }
 
                if (interrupted)
                        ret = -EINTR;
-               else if (io_data->read && ep->status > 0)
-                       ret = __ffs_epfile_read_data(epfile, data, ep->status,
+               else if (io_data->read && io_data->status > 0)
+                       ret = __ffs_epfile_read_data(epfile, data, io_data->status,
                                                     &io_data->data);
                else
-                       ret = ep->status;
+                       ret = io_data->status;
                goto error_mutex;
        } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
                ret = -ENOMEM;
index 6f5d45e..f51694f 100644 (file)
@@ -775,9 +775,13 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
        dev->qmult = qmult;
        snprintf(net->name, sizeof(net->name), "%s%%d", netname);
 
-       if (get_ether_addr(dev_addr, addr))
+       if (get_ether_addr(dev_addr, addr)) {
+               net->addr_assign_type = NET_ADDR_RANDOM;
                dev_warn(&g->dev,
                        "using random %s ethernet address\n", "self");
+       } else {
+               net->addr_assign_type = NET_ADDR_SET;
+       }
        eth_hw_addr_set(net, addr);
        if (get_ether_addr(host_addr, dev->host_mac))
                dev_warn(&g->dev,
@@ -844,6 +848,10 @@ struct net_device *gether_setup_name_default(const char *netname)
 
        eth_random_addr(dev->dev_mac);
        pr_warn("using random %s ethernet address\n", "self");
+
+       /* by default we always have a random MAC address */
+       net->addr_assign_type = NET_ADDR_RANDOM;
+
        eth_random_addr(dev->host_mac);
        pr_warn("using random %s ethernet address\n", "host");
 
@@ -871,7 +879,6 @@ int gether_register_netdev(struct net_device *net)
        dev = netdev_priv(net);
        g = dev->gadget;
 
-       net->addr_assign_type = NET_ADDR_RANDOM;
        eth_hw_addr_set(net, dev->dev_mac);
 
        status = register_netdev(net);
@@ -912,6 +919,7 @@ int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
        if (get_ether_addr(dev_addr, new_addr))
                return -EINVAL;
        memcpy(dev->dev_mac, new_addr, ETH_ALEN);
+       net->addr_assign_type = NET_ADDR_SET;
        return 0;
 }
 EXPORT_SYMBOL_GPL(gether_set_dev_addr);
index 6117ae8..cea10cd 100644 (file)
@@ -3016,6 +3016,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
        }
 
        udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
+       of_node_put(isp1301_node);
        if (!udc->isp1301_i2c_client) {
                return -EPROBE_DEFER;
        }
index f0ab631..9ac56e9 100644 (file)
@@ -1107,7 +1107,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
        u32                     command, temp = 0;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
-       struct usb_hcd          *secondary_hcd;
        int                     retval = 0;
        bool                    comp_timer_running = false;
        bool                    pending_portevent = false;
@@ -1214,23 +1213,19 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                 * first with the primary HCD, and then with the secondary HCD.
                 * If we don't do the same, the host will never be started.
                 */
-               if (!usb_hcd_is_primary_hcd(hcd))
-                       secondary_hcd = hcd;
-               else
-                       secondary_hcd = xhci->shared_hcd;
-
                xhci_dbg(xhci, "Initialize the xhci_hcd\n");
-               retval = xhci_init(hcd->primary_hcd);
+               retval = xhci_init(hcd);
                if (retval)
                        return retval;
                comp_timer_running = true;
 
                xhci_dbg(xhci, "Start the primary HCD\n");
-               retval = xhci_run(hcd->primary_hcd);
-               if (!retval && secondary_hcd) {
+               retval = xhci_run(hcd);
+               if (!retval && xhci->shared_hcd) {
                        xhci_dbg(xhci, "Start the secondary HCD\n");
-                       retval = xhci_run(secondary_hcd);
+                       retval = xhci_run(xhci->shared_hcd);
                }
+
                hcd->state = HC_STATE_SUSPENDED;
                if (xhci->shared_hcd)
                        xhci->shared_hcd->state = HC_STATE_SUSPENDED;
index a7b3c15..feba2a8 100644 (file)
@@ -166,6 +166,7 @@ static const struct usb_device_id edgeport_2port_id_table[] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_E5805A) },
        { }
 };
 
@@ -204,6 +205,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
        { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
+       { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_E5805A) },
        { }
 };
 
index 52cbc35..9a6f742 100644 (file)
 //
 // Definitions for other product IDs
 #define ION_DEVICE_ID_MT4X56USB                        0x1403  // OEM device
+#define ION_DEVICE_ID_E5805A                   0x1A01  // OEM device (rebranded Edgeport/4)
 
 
 #define        GENERATION_ID_FROM_USB_PRODUCT_ID(ProductId)                            \
index e60425b..ed1e50d 100644 (file)
@@ -432,6 +432,8 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_CLS8                 0x00b0
 #define CINTERION_PRODUCT_MV31_MBIM            0x00b3
 #define CINTERION_PRODUCT_MV31_RMNET           0x00b7
+#define CINTERION_PRODUCT_MV31_2_MBIM          0x00b8
+#define CINTERION_PRODUCT_MV31_2_RMNET         0x00b9
 #define CINTERION_PRODUCT_MV32_WA              0x00f1
 #define CINTERION_PRODUCT_MV32_WB              0x00f2
 
@@ -1979,6 +1981,10 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(3)},
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff),
          .driver_info = RSVD(0)},
+       { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_MBIM, 0xff),
+         .driver_info = RSVD(3)},
+       { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_RMNET, 0xff),
+         .driver_info = RSVD(0)},
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
          .driver_info = RSVD(3)},
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
index b0b2d7a..2fd85be 100644 (file)
@@ -172,3 +172,4 @@ module_platform_driver(gxp_wdt_driver);
 MODULE_AUTHOR("Nick Hawkins <nick.hawkins@hpe.com>");
 MODULE_AUTHOR("Jean-Marie Verdun <verdun@hpe.com>");
 MODULE_DESCRIPTION("Driver for GXP watchdog timer");
+MODULE_LICENSE("GPL");
index 79df61f..baf2b15 100644 (file)
@@ -152,7 +152,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
        const unsigned char **wnames, *uname;
        int i, n, l, clone, access;
        struct v9fs_session_info *v9ses;
-       struct p9_fid *fid, *old_fid = NULL;
+       struct p9_fid *fid, *old_fid;
 
        v9ses = v9fs_dentry2v9ses(dentry);
        access = v9ses->flags & V9FS_ACCESS_MASK;
@@ -194,13 +194,12 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
                if (IS_ERR(fid))
                        return fid;
 
+               refcount_inc(&fid->count);
                v9fs_fid_add(dentry->d_sb->s_root, fid);
        }
        /* If we are root ourself just return that */
-       if (dentry->d_sb->s_root == dentry) {
-               refcount_inc(&fid->count);
+       if (dentry->d_sb->s_root == dentry)
                return fid;
-       }
        /*
         * Do a multipath walk with attached root.
         * When walking parent we need to make sure we
@@ -212,6 +211,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
                fid = ERR_PTR(n);
                goto err_out;
        }
+       old_fid = fid;
        clone = 1;
        i = 0;
        while (i < n) {
@@ -221,19 +221,15 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
                 * walk to ensure none of the patch component change
                 */
                fid = p9_client_walk(fid, l, &wnames[i], clone);
+               /* non-cloning walk will return the same fid */
+               if (fid != old_fid) {
+                       p9_client_clunk(old_fid);
+                       old_fid = fid;
+               }
                if (IS_ERR(fid)) {
-                       if (old_fid) {
-                               /*
-                                * If we fail, clunk fid which are mapping
-                                * to path component and not the last component
-                                * of the path.
-                                */
-                               p9_client_clunk(old_fid);
-                       }
                        kfree(wnames);
                        goto err_out;
                }
-               old_fid = fid;
                i += l;
                clone = 0;
        }
index a8f512b..d0833fa 100644 (file)
@@ -58,8 +58,21 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)
  */
 static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
 {
+       struct inode *inode = file_inode(file);
+       struct v9fs_inode *v9inode = V9FS_I(inode);
        struct p9_fid *fid = file->private_data;
 
+       BUG_ON(!fid);
+
+       /* we might need to read from a fid that was opened write-only
+        * for read-modify-write of page cache, use the writeback fid
+        * for that */
+       if (rreq->origin == NETFS_READ_FOR_WRITE &&
+                       (fid->mode & O_ACCMODE) == O_WRONLY) {
+               fid = v9inode->writeback_fid;
+               BUG_ON(!fid);
+       }
+
        refcount_inc(&fid->count);
        rreq->netfs_priv = fid;
        return 0;
index 419d2f3..3d82977 100644 (file)
@@ -1251,15 +1251,15 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
                return ERR_PTR(-ECHILD);
 
        v9ses = v9fs_dentry2v9ses(dentry);
-       fid = v9fs_fid_lookup(dentry);
+       if (!v9fs_proto_dotu(v9ses))
+               return ERR_PTR(-EBADF);
+
        p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
+       fid = v9fs_fid_lookup(dentry);
 
        if (IS_ERR(fid))
                return ERR_CAST(fid);
 
-       if (!v9fs_proto_dotu(v9ses))
-               return ERR_PTR(-EBADF);
-
        st = p9_client_stat(fid);
        p9_client_clunk(fid);
        if (IS_ERR(st))
index d17502a..b6eb116 100644 (file)
@@ -274,6 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(ofid)) {
                err = PTR_ERR(ofid);
                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
+               p9_client_clunk(dfid);
                goto out;
        }
 
@@ -285,6 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        if (err) {
                p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
                         err);
+               p9_client_clunk(dfid);
                goto error;
        }
        err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
@@ -292,6 +294,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        if (err < 0) {
                p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
                         err);
+               p9_client_clunk(dfid);
                goto error;
        }
        v9fs_invalidate_inode_attr(dir);
index 89630ac..64dab70 100644 (file)
@@ -745,7 +745,8 @@ int afs_getattr(struct user_namespace *mnt_userns, const struct path *path,
 
        _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
 
-       if (!(query_flags & AT_STATX_DONT_SYNC) &&
+       if (vnode->volume &&
+           !(query_flags & AT_STATX_DONT_SYNC) &&
            !test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
                key = afs_request_key(vnode->volume->cell);
                if (IS_ERR(key))
index 66899b6..dbe996b 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -61,9 +61,15 @@ static bool chgrp_ok(struct user_namespace *mnt_userns,
                     const struct inode *inode, kgid_t gid)
 {
        kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
-       if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode)) &&
-           (in_group_p(gid) || gid_eq(gid, inode->i_gid)))
-               return true;
+       if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) {
+               kgid_t mapped_gid;
+
+               if (gid_eq(gid, inode->i_gid))
+                       return true;
+               mapped_gid = mapped_kgid_fs(mnt_userns, i_user_ns(inode), gid);
+               if (in_group_p(mapped_gid))
+                       return true;
+       }
        if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
        if (gid_eq(kgid, INVALID_GID) &&
@@ -123,12 +129,20 @@ int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
 
        /* Make sure a caller can chmod. */
        if (ia_valid & ATTR_MODE) {
+               kgid_t mapped_gid;
+
                if (!inode_owner_or_capable(mnt_userns, inode))
                        return -EPERM;
+
+               if (ia_valid & ATTR_GID)
+                       mapped_gid = mapped_kgid_fs(mnt_userns,
+                                               i_user_ns(inode), attr->ia_gid);
+               else
+                       mapped_gid = i_gid_into_mnt(mnt_userns, inode);
+
                /* Also check the setgid bit! */
-               if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
-                                i_gid_into_mnt(mnt_userns, inode)) &&
-                    !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
+               if (!in_group_p(mapped_gid) &&
+                   !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
                        attr->ia_mode &= ~S_ISGID;
        }
 
index 89e94ea..4ba005c 100644 (file)
@@ -4632,6 +4632,17 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        int ret;
 
        set_bit(BTRFS_FS_CLOSING_START, &fs_info->flags);
+
+       /*
+        * We may have the reclaim task running and relocating a data block group,
+        * in which case it may create delayed iputs. So stop it before we park
+        * the cleaner kthread otherwise we can get new delayed iputs after
+        * parking the cleaner, and that can make the async reclaim task to hang
+        * if it's waiting for delayed iputs to complete, since the cleaner is
+        * parked and can not run delayed iputs - this will make us hang when
+        * trying to stop the async reclaim task.
+        */
+       cancel_work_sync(&fs_info->reclaim_bgs_work);
        /*
         * We don't want the cleaner to start new transactions, add more delayed
         * iputs, etc. while we're closing. We can't use kthread_stop() yet
@@ -4672,8 +4683,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        cancel_work_sync(&fs_info->async_data_reclaim_work);
        cancel_work_sync(&fs_info->preempt_reclaim_work);
 
-       cancel_work_sync(&fs_info->reclaim_bgs_work);
-
        /* Cancel or finish ongoing discard work */
        btrfs_discard_cleanup(fs_info);
 
index b1fdc6a..6627dd7 100644 (file)
@@ -763,6 +763,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                                compress_force = false;
                                no_compress++;
                        } else {
+                               btrfs_err(info, "unrecognized compression value %s",
+                                         args[0].from);
                                ret = -EINVAL;
                                goto out;
                        }
@@ -821,8 +823,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                case Opt_thread_pool:
                        ret = match_int(&args[0], &intarg);
                        if (ret) {
+                               btrfs_err(info, "unrecognized thread_pool value %s",
+                                         args[0].from);
                                goto out;
                        } else if (intarg == 0) {
+                               btrfs_err(info, "invalid value 0 for thread_pool");
                                ret = -EINVAL;
                                goto out;
                        }
@@ -883,8 +888,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        break;
                case Opt_ratio:
                        ret = match_int(&args[0], &intarg);
-                       if (ret)
+                       if (ret) {
+                               btrfs_err(info, "unrecognized metadata_ratio value %s",
+                                         args[0].from);
                                goto out;
+                       }
                        info->metadata_ratio = intarg;
                        btrfs_info(info, "metadata ratio %u",
                                   info->metadata_ratio);
@@ -901,6 +909,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                                btrfs_set_and_info(info, DISCARD_ASYNC,
                                                   "turning on async discard");
                        } else {
+                               btrfs_err(info, "unrecognized discard mode value %s",
+                                         args[0].from);
                                ret = -EINVAL;
                                goto out;
                        }
@@ -933,6 +943,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                                btrfs_set_and_info(info, FREE_SPACE_TREE,
                                                   "enabling free space tree");
                        } else {
+                               btrfs_err(info, "unrecognized space_cache value %s",
+                                         args[0].from);
                                ret = -EINVAL;
                                goto out;
                        }
@@ -1014,8 +1026,12 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        break;
                case Opt_check_integrity_print_mask:
                        ret = match_int(&args[0], &intarg);
-                       if (ret)
+                       if (ret) {
+                               btrfs_err(info,
+                               "unrecognized check_integrity_print_mask value %s",
+                                       args[0].from);
                                goto out;
+                       }
                        info->check_integrity_print_mask = intarg;
                        btrfs_info(info, "check_integrity_print_mask 0x%x",
                                   info->check_integrity_print_mask);
@@ -1030,13 +1046,15 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        goto out;
 #endif
                case Opt_fatal_errors:
-                       if (strcmp(args[0].from, "panic") == 0)
+                       if (strcmp(args[0].from, "panic") == 0) {
                                btrfs_set_opt(info->mount_opt,
                                              PANIC_ON_FATAL_ERROR);
-                       else if (strcmp(args[0].from, "bug") == 0)
+                       } else if (strcmp(args[0].from, "bug") == 0) {
                                btrfs_clear_opt(info->mount_opt,
                                              PANIC_ON_FATAL_ERROR);
-                       else {
+                       } else {
+                               btrfs_err(info, "unrecognized fatal_errors value %s",
+                                         args[0].from);
                                ret = -EINVAL;
                                goto out;
                        }
@@ -1044,8 +1062,12 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                case Opt_commit_interval:
                        intarg = 0;
                        ret = match_int(&args[0], &intarg);
-                       if (ret)
+                       if (ret) {
+                               btrfs_err(info, "unrecognized commit_interval value %s",
+                                         args[0].from);
+                               ret = -EINVAL;
                                goto out;
+                       }
                        if (intarg == 0) {
                                btrfs_info(info,
                                           "using default commit interval %us",
@@ -1059,8 +1081,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        break;
                case Opt_rescue:
                        ret = parse_rescue_options(info, args[0].from);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               btrfs_err(info, "unrecognized rescue value %s",
+                                         args[0].from);
                                goto out;
+                       }
                        break;
 #ifdef CONFIG_BTRFS_DEBUG
                case Opt_fragment_all:
@@ -1985,6 +2010,14 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
        if (ret)
                goto restore;
 
+       /* V1 cache is not supported for subpage mount. */
+       if (fs_info->sectorsize < PAGE_SIZE && btrfs_test_opt(fs_info, SPACE_CACHE)) {
+               btrfs_warn(fs_info,
+       "v1 space cache is not supported for page size %lu with sectorsize %u",
+                          PAGE_SIZE, fs_info->sectorsize);
+               ret = -EINVAL;
+               goto restore;
+       }
        btrfs_remount_begin(fs_info, old_opts, *flags);
        btrfs_resize_thread_pool(fs_info,
                fs_info->thread_pool_size, old_thread_pool_size);
index 0bece97..d417de3 100644 (file)
@@ -81,6 +81,9 @@ cifs_ses_get_chan_index(struct cifs_ses *ses,
        }
 
        /* If we didn't find the channel, it is likely a bug */
+       if (server)
+               cifs_dbg(VFS, "unable to get chan index for server: 0x%llx",
+                        server->conn_id);
        WARN_ON(1);
        return 0;
 }
index eaf975f..b515140 100644 (file)
@@ -5154,6 +5154,8 @@ SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        data = &info;
        size = sizeof(struct smb2_file_eof_info);
 
+       trace_smb3_set_eof(xid, persistent_fid, tcon->tid, tcon->ses->Suid, le64_to_cpu(*eof));
+
        return send_set_info(xid, tcon, persistent_fid, volatile_fid,
                        pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE,
                        0, 1, &data, &size);
index 2be5e0c..6b88dc2 100644 (file)
@@ -121,6 +121,44 @@ DEFINE_SMB3_RW_DONE_EVENT(query_dir_done);
 DEFINE_SMB3_RW_DONE_EVENT(zero_done);
 DEFINE_SMB3_RW_DONE_EVENT(falloc_done);
 
+/* For logging successful set EOF (truncate) */
+DECLARE_EVENT_CLASS(smb3_eof_class,
+       TP_PROTO(unsigned int xid,
+               __u64   fid,
+               __u32   tid,
+               __u64   sesid,
+               __u64   offset),
+       TP_ARGS(xid, fid, tid, sesid, offset),
+       TP_STRUCT__entry(
+               __field(unsigned int, xid)
+               __field(__u64, fid)
+               __field(__u32, tid)
+               __field(__u64, sesid)
+               __field(__u64, offset)
+       ),
+       TP_fast_assign(
+               __entry->xid = xid;
+               __entry->fid = fid;
+               __entry->tid = tid;
+               __entry->sesid = sesid;
+               __entry->offset = offset;
+       ),
+       TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx",
+               __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+               __entry->offset)
+)
+
+#define DEFINE_SMB3_EOF_EVENT(name)         \
+DEFINE_EVENT(smb3_eof_class, smb3_##name,   \
+       TP_PROTO(unsigned int xid,              \
+               __u64   fid,                    \
+               __u32   tid,                    \
+               __u64   sesid,                  \
+               __u64   offset),                \
+       TP_ARGS(xid, fid, tid, sesid, offset))
+
+DEFINE_SMB3_EOF_EVENT(set_eof);
+
 /*
  * For handle based calls other than read and write, and get/set info
  */
index 2c2f179..43de293 100644 (file)
@@ -672,17 +672,14 @@ int ext2_empty_dir (struct inode * inode)
        void *page_addr = NULL;
        struct page *page = NULL;
        unsigned long i, npages = dir_pages(inode);
-       int dir_has_error = 0;
 
        for (i = 0; i < npages; i++) {
                char *kaddr;
                ext2_dirent * de;
-               page = ext2_get_page(inode, i, dir_has_error, &page_addr);
+               page = ext2_get_page(inode, i, 0, &page_addr);
 
-               if (IS_ERR(page)) {
-                       dir_has_error = 1;
-                       continue;
-               }
+               if (IS_ERR(page))
+                       goto not_empty;
 
                kaddr = page_addr;
                de = (ext2_dirent *)kaddr;
index 3dce7d0..84c0eb5 100644 (file)
@@ -829,7 +829,7 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
        ext4_debug("ext4_get_block_unwritten: inode %lu, create flag %d\n",
                   inode->i_ino, create);
        return _ext4_get_block(inode, iblock, bh_result,
-                              EXT4_GET_BLOCKS_IO_CREATE_EXT);
+                              EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT);
 }
 
 /* Maximum number of blocks we map for direct IO at once. */
index 9f12f29..9e06334 100644 (file)
@@ -4104,6 +4104,15 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
        size = size >> bsbits;
        start = start_off >> bsbits;
 
+       /*
+        * For tiny groups (smaller than 8MB) the chosen allocation
+        * alignment may be larger than group size. Make sure the
+        * alignment does not move allocation to a different group which
+        * makes mballoc fail assertions later.
+        */
+       start = max(start, rounddown(ac->ac_o_ex.fe_logical,
+                       (ext4_lblk_t)EXT4_BLOCKS_PER_GROUP(ac->ac_sb)));
+
        /* don't cover already allocated blocks in selected range */
        if (ar->pleft && start <= ar->lleft) {
                size -= ar->lleft + 1 - start;
@@ -4176,7 +4185,22 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
        }
        rcu_read_unlock();
 
-       if (start + size <= ac->ac_o_ex.fe_logical &&
+       /*
+        * In this function "start" and "size" are normalized for better
+        * alignment and length such that we could preallocate more blocks.
+        * This normalization is done such that original request of
+        * ac->ac_o_ex.fe_logical & fe_len should always lie within "start" and
+        * "size" boundaries.
+        * (Note fe_len can be relaxed since FS block allocation API does not
+        * provide gurantee on number of contiguous blocks allocation since that
+        * depends upon free space left, etc).
+        * In case of inode pa, later we use the allocated blocks
+        * [pa_start + fe_logical - pa_lstart, fe_len/size] from the preallocated
+        * range of goal/best blocks [start, size] to put it at the
+        * ac_o_ex.fe_logical extent of this inode.
+        * (See ext4_mb_use_inode_pa() for more details)
+        */
+       if (start + size <= ac->ac_o_ex.fe_logical ||
                        start > ac->ac_o_ex.fe_logical) {
                ext4_msg(ac->ac_sb, KERN_ERR,
                         "start %lu, size %lu, fe_logical %lu",
index 7a5353a..42f5905 100644 (file)
@@ -438,7 +438,7 @@ int ext4_ext_migrate(struct inode *inode)
 
        /*
         * Worst case we can touch the allocation bitmaps and a block
-        * group descriptor block.  We do need need to worry about
+        * group descriptor block.  We do need to worry about
         * credits for modifying the quota inode.
         */
        handle = ext4_journal_start(inode, EXT4_HT_MIGRATE,
index 47d0ca4..db4ba99 100644 (file)
@@ -1929,7 +1929,8 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct dx_hash_info *hinfo)
 {
        unsigned blocksize = dir->i_sb->s_blocksize;
-       unsigned count, continued;
+       unsigned continued;
+       int count;
        struct buffer_head *bh2;
        ext4_lblk_t newblock;
        u32 hash2;
index 14695e2..97fa7b4 100644 (file)
@@ -465,7 +465,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
        /*
         * In the first loop we prepare and mark buffers to submit. We have to
         * mark all buffers in the page before submitting so that
-        * end_page_writeback() cannot be called from ext4_bio_end_io() when IO
+        * end_page_writeback() cannot be called from ext4_end_bio() when IO
         * on the first buffer finishes and we are still working on submitting
         * the second buffer.
         */
index 90a941d..8b70a47 100644 (file)
@@ -53,6 +53,16 @@ int ext4_resize_begin(struct super_block *sb)
        if (!capable(CAP_SYS_RESOURCE))
                return -EPERM;
 
+       /*
+        * If the reserved GDT blocks is non-zero, the resize_inode feature
+        * should always be set.
+        */
+       if (EXT4_SB(sb)->s_es->s_reserved_gdt_blocks &&
+           !ext4_has_feature_resize_inode(sb)) {
+               ext4_error(sb, "resize_inode disabled but reserved GDT blocks non-zero");
+               return -EFSCORRUPTED;
+       }
+
        /*
         * If we are not using the primary superblock/GDT copy don't resize,
          * because the user tools have no way of handling this.  Probably a
index 450c918..845f2f8 100644 (file)
@@ -87,7 +87,7 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
 static int ext4_validate_options(struct fs_context *fc);
 static int ext4_check_opt_consistency(struct fs_context *fc,
                                      struct super_block *sb);
-static int ext4_apply_options(struct fs_context *fc, struct super_block *sb);
+static void ext4_apply_options(struct fs_context *fc, struct super_block *sb);
 static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param);
 static int ext4_get_tree(struct fs_context *fc);
 static int ext4_reconfigure(struct fs_context *fc);
@@ -1870,31 +1870,12 @@ ext4_sb_read_encoding(const struct ext4_super_block *es)
 }
 #endif
 
-static int ext4_set_test_dummy_encryption(struct super_block *sb, char *arg)
-{
-#ifdef CONFIG_FS_ENCRYPTION
-       struct ext4_sb_info *sbi = EXT4_SB(sb);
-       int err;
-
-       err = fscrypt_set_test_dummy_encryption(sb, arg,
-                                               &sbi->s_dummy_enc_policy);
-       if (err) {
-               ext4_msg(sb, KERN_WARNING,
-                        "Error while setting test dummy encryption [%d]", err);
-               return err;
-       }
-       ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
-#endif
-       return 0;
-}
-
 #define EXT4_SPEC_JQUOTA                       (1 <<  0)
 #define EXT4_SPEC_JQFMT                                (1 <<  1)
 #define EXT4_SPEC_DATAJ                                (1 <<  2)
 #define EXT4_SPEC_SB_BLOCK                     (1 <<  3)
 #define EXT4_SPEC_JOURNAL_DEV                  (1 <<  4)
 #define EXT4_SPEC_JOURNAL_IOPRIO               (1 <<  5)
-#define EXT4_SPEC_DUMMY_ENCRYPTION             (1 <<  6)
 #define EXT4_SPEC_s_want_extra_isize           (1 <<  7)
 #define EXT4_SPEC_s_max_batch_time             (1 <<  8)
 #define EXT4_SPEC_s_min_batch_time             (1 <<  9)
@@ -1911,7 +1892,7 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb, char *arg)
 
 struct ext4_fs_context {
        char            *s_qf_names[EXT4_MAXQUOTAS];
-       char            *test_dummy_enc_arg;
+       struct fscrypt_dummy_policy dummy_enc_policy;
        int             s_jquota_fmt;   /* Format of quota to use */
 #ifdef CONFIG_EXT4_DEBUG
        int s_fc_debug_max_replay;
@@ -1953,7 +1934,7 @@ static void ext4_fc_free(struct fs_context *fc)
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(ctx->s_qf_names[i]);
 
-       kfree(ctx->test_dummy_enc_arg);
+       fscrypt_free_dummy_policy(&ctx->dummy_enc_policy);
        kfree(ctx);
 }
 
@@ -2029,6 +2010,29 @@ static int unnote_qf_name(struct fs_context *fc, int qtype)
 }
 #endif
 
+static int ext4_parse_test_dummy_encryption(const struct fs_parameter *param,
+                                           struct ext4_fs_context *ctx)
+{
+       int err;
+
+       if (!IS_ENABLED(CONFIG_FS_ENCRYPTION)) {
+               ext4_msg(NULL, KERN_WARNING,
+                        "test_dummy_encryption option not supported");
+               return -EINVAL;
+       }
+       err = fscrypt_parse_test_dummy_encryption(param,
+                                                 &ctx->dummy_enc_policy);
+       if (err == -EINVAL) {
+               ext4_msg(NULL, KERN_WARNING,
+                        "Value of option \"%s\" is unrecognized", param->key);
+       } else if (err == -EEXIST) {
+               ext4_msg(NULL, KERN_WARNING,
+                        "Conflicting test_dummy_encryption options");
+               return -EINVAL;
+       }
+       return err;
+}
+
 #define EXT4_SET_CTX(name)                                             \
 static inline void ctx_set_##name(struct ext4_fs_context *ctx,         \
                                  unsigned long flag)                   \
@@ -2291,29 +2295,7 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
                ctx->spec |= EXT4_SPEC_JOURNAL_IOPRIO;
                return 0;
        case Opt_test_dummy_encryption:
-#ifdef CONFIG_FS_ENCRYPTION
-               if (param->type == fs_value_is_flag) {
-                       ctx->spec |= EXT4_SPEC_DUMMY_ENCRYPTION;
-                       ctx->test_dummy_enc_arg = NULL;
-                       return 0;
-               }
-               if (*param->string &&
-                   !(!strcmp(param->string, "v1") ||
-                     !strcmp(param->string, "v2"))) {
-                       ext4_msg(NULL, KERN_WARNING,
-                                "Value of option \"%s\" is unrecognized",
-                                param->key);
-                       return -EINVAL;
-               }
-               ctx->spec |= EXT4_SPEC_DUMMY_ENCRYPTION;
-               ctx->test_dummy_enc_arg = kmemdup_nul(param->string, param->size,
-                                                     GFP_KERNEL);
-               return 0;
-#else
-               ext4_msg(NULL, KERN_WARNING,
-                        "test_dummy_encryption option not supported");
-               return -EINVAL;
-#endif
+               return ext4_parse_test_dummy_encryption(param, ctx);
        case Opt_dax:
        case Opt_dax_type:
 #ifdef CONFIG_FS_DAX
@@ -2504,7 +2486,8 @@ parse_failed:
        if (s_ctx->spec & EXT4_SPEC_JOURNAL_IOPRIO)
                m_ctx->journal_ioprio = s_ctx->journal_ioprio;
 
-       ret = ext4_apply_options(fc, sb);
+       ext4_apply_options(fc, sb);
+       ret = 0;
 
 out_free:
        if (fc) {
@@ -2673,11 +2656,11 @@ err_jquota_specified:
 static int ext4_check_test_dummy_encryption(const struct fs_context *fc,
                                            struct super_block *sb)
 {
-#ifdef CONFIG_FS_ENCRYPTION
        const struct ext4_fs_context *ctx = fc->fs_private;
        const struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int err;
 
-       if (!(ctx->spec & EXT4_SPEC_DUMMY_ENCRYPTION))
+       if (!fscrypt_is_dummy_policy_set(&ctx->dummy_enc_policy))
                return 0;
 
        if (!ext4_has_feature_encrypt(sb)) {
@@ -2691,14 +2674,46 @@ static int ext4_check_test_dummy_encryption(const struct fs_context *fc,
         * needed to allow it to be set or changed during remount.  We do allow
         * it to be specified during remount, but only if there is no change.
         */
-       if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE &&
-           !sbi->s_dummy_enc_policy.policy) {
+       if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
+               if (fscrypt_dummy_policies_equal(&sbi->s_dummy_enc_policy,
+                                                &ctx->dummy_enc_policy))
+                       return 0;
                ext4_msg(NULL, KERN_WARNING,
-                        "Can't set test_dummy_encryption on remount");
+                        "Can't set or change test_dummy_encryption on remount");
                return -EINVAL;
        }
-#endif /* CONFIG_FS_ENCRYPTION */
-       return 0;
+       /* Also make sure s_mount_opts didn't contain a conflicting value. */
+       if (fscrypt_is_dummy_policy_set(&sbi->s_dummy_enc_policy)) {
+               if (fscrypt_dummy_policies_equal(&sbi->s_dummy_enc_policy,
+                                                &ctx->dummy_enc_policy))
+                       return 0;
+               ext4_msg(NULL, KERN_WARNING,
+                        "Conflicting test_dummy_encryption options");
+               return -EINVAL;
+       }
+       /*
+        * fscrypt_add_test_dummy_key() technically changes the super_block, so
+        * technically it should be delayed until ext4_apply_options() like the
+        * other changes.  But since we never get here for remounts (see above),
+        * and this is the last chance to report errors, we do it here.
+        */
+       err = fscrypt_add_test_dummy_key(sb, &ctx->dummy_enc_policy);
+       if (err)
+               ext4_msg(NULL, KERN_WARNING,
+                        "Error adding test dummy encryption key [%d]", err);
+       return err;
+}
+
+static void ext4_apply_test_dummy_encryption(struct ext4_fs_context *ctx,
+                                            struct super_block *sb)
+{
+       if (!fscrypt_is_dummy_policy_set(&ctx->dummy_enc_policy) ||
+           /* if already set, it was already verified to be the same */
+           fscrypt_is_dummy_policy_set(&EXT4_SB(sb)->s_dummy_enc_policy))
+               return;
+       EXT4_SB(sb)->s_dummy_enc_policy = ctx->dummy_enc_policy;
+       memset(&ctx->dummy_enc_policy, 0, sizeof(ctx->dummy_enc_policy));
+       ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
 }
 
 static int ext4_check_opt_consistency(struct fs_context *fc,
@@ -2785,11 +2800,10 @@ fail_dax_change_remount:
        return ext4_check_quota_consistency(fc, sb);
 }
 
-static int ext4_apply_options(struct fs_context *fc, struct super_block *sb)
+static void ext4_apply_options(struct fs_context *fc, struct super_block *sb)
 {
        struct ext4_fs_context *ctx = fc->fs_private;
        struct ext4_sb_info *sbi = fc->s_fs_info;
-       int ret = 0;
 
        sbi->s_mount_opt &= ~ctx->mask_s_mount_opt;
        sbi->s_mount_opt |= ctx->vals_s_mount_opt;
@@ -2825,11 +2839,7 @@ static int ext4_apply_options(struct fs_context *fc, struct super_block *sb)
 #endif
 
        ext4_apply_quota_options(fc, sb);
-
-       if (ctx->spec & EXT4_SPEC_DUMMY_ENCRYPTION)
-               ret = ext4_set_test_dummy_encryption(sb, ctx->test_dummy_enc_arg);
-
-       return ret;
+       ext4_apply_test_dummy_encryption(ctx, sb);
 }
 
 
@@ -4552,9 +4562,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
        if (err < 0)
                goto failed_mount;
 
-       err = ext4_apply_options(fc, sb);
-       if (err < 0)
-               goto failed_mount;
+       ext4_apply_options(fc, sb);
 
 #if IS_ENABLED(CONFIG_UNICODE)
        if (ext4_has_feature_casefold(sb) && !sb->s_encoding) {
@@ -5302,14 +5310,6 @@ no_journal:
                err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
                                          GFP_KERNEL);
        }
-       /*
-        * Update the checksum after updating free space/inode
-        * counters.  Otherwise the superblock can have an incorrect
-        * checksum in the buffer cache until it is written out and
-        * e2fsprogs programs trying to open a file system immediately
-        * after it is mounted can fail.
-        */
-       ext4_superblock_csum_set(sb);
        if (!err)
                err = percpu_counter_init(&sbi->s_dirs_counter,
                                          ext4_count_dirs(sb), GFP_KERNEL);
@@ -5367,6 +5367,14 @@ no_journal:
        EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
        ext4_orphan_cleanup(sb, es);
        EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
+       /*
+        * Update the checksum after updating free space/inode counters and
+        * ext4_orphan_cleanup. Otherwise the superblock can have an incorrect
+        * checksum in the buffer cache until it is written out and
+        * e2fsprogs programs trying to open a file system immediately
+        * after it is mounted can fail.
+        */
+       ext4_superblock_csum_set(sb);
        if (needs_recovery) {
                ext4_msg(sb, KERN_INFO, "recovery complete");
                err = ext4_mark_recovery_complete(sb, es);
@@ -5898,7 +5906,6 @@ static void ext4_update_super(struct super_block *sb)
 static int ext4_commit_super(struct super_block *sb)
 {
        struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
-       int error = 0;
 
        if (!sbh)
                return -EINVAL;
@@ -5907,6 +5914,13 @@ static int ext4_commit_super(struct super_block *sb)
 
        ext4_update_super(sb);
 
+       lock_buffer(sbh);
+       /* Buffer got discarded which means block device got invalidated */
+       if (!buffer_mapped(sbh)) {
+               unlock_buffer(sbh);
+               return -EIO;
+       }
+
        if (buffer_write_io_error(sbh) || !buffer_uptodate(sbh)) {
                /*
                 * Oh, dear.  A previous attempt to write the
@@ -5921,17 +5935,21 @@ static int ext4_commit_super(struct super_block *sb)
                clear_buffer_write_io_error(sbh);
                set_buffer_uptodate(sbh);
        }
-       BUFFER_TRACE(sbh, "marking dirty");
-       mark_buffer_dirty(sbh);
-       error = __sync_dirty_buffer(sbh,
-               REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0));
+       get_bh(sbh);
+       /* Clear potential dirty bit if it was journalled update */
+       clear_buffer_dirty(sbh);
+       sbh->b_end_io = end_buffer_write_sync;
+       submit_bh(REQ_OP_WRITE,
+                 REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0), sbh);
+       wait_on_buffer(sbh);
        if (buffer_write_io_error(sbh)) {
                ext4_msg(sb, KERN_ERR, "I/O error while writing "
                       "superblock");
                clear_buffer_write_io_error(sbh);
                set_buffer_uptodate(sbh);
+               return -EIO;
        }
-       return error;
+       return 0;
 }
 
 /*
index 0423253..564e28a 100644 (file)
@@ -1895,11 +1895,10 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
 
                        unlock_buffer(bs->bh);
                        ea_bdebug(bs->bh, "cloning");
-                       s->base = kmalloc(bs->bh->b_size, GFP_NOFS);
+                       s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS);
                        error = -ENOMEM;
                        if (s->base == NULL)
                                goto cleanup;
-                       memcpy(s->base, BHDR(bs->bh), bs->bh->b_size);
                        s->first = ENTRY(header(s->base)+1);
                        header(s->base)->h_refcount = cpu_to_le32(1);
                        s->here = ENTRY(s->base + offset);
index e49bb09..e9c308a 100644 (file)
@@ -2114,7 +2114,7 @@ out:
 /**
  * jbd2_journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
- * @page: to try and free
+ * @folio: Folio to detach data from.
  *
  * For all the buffers on this page,
  * if they are fully written out ordered data, move them onto BUF_CLEAN
index c852028..c1eda73 100644 (file)
@@ -288,6 +288,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
                rv = NFS4_OK;
                break;
        case -ENOENT:
+               set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags);
                /* Embrace your forgetfulness! */
                rv = NFS4ERR_NOMATCHING_LAYOUT;
 
index a8ecdd5..0c4e8dd 100644 (file)
@@ -2124,6 +2124,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
                }
                goto out;
        }
+       file->f_mode |= FMODE_CAN_ODIRECT;
 
        err = nfs_finish_open(ctx, ctx->dentry, file, open_flags);
        trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
index 03d3a27..e88f6b1 100644 (file)
@@ -93,6 +93,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
        nfs_file_set_open_context(filp, ctx);
        nfs_fscache_open_file(inode, filp);
        err = 0;
+       filp->f_mode |= FMODE_CAN_ODIRECT;
 
 out_put_ctx:
        put_nfs_open_context(ctx);
index 68a87be..41a9b6b 100644 (file)
@@ -469,6 +469,7 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
                pnfs_clear_lseg_state(lseg, lseg_list);
        pnfs_clear_layoutreturn_info(lo);
        pnfs_free_returned_lsegs(lo, lseg_list, &range, 0);
+       set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags);
        if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) &&
            !test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags))
                pnfs_clear_layoutreturn_waitbit(lo);
@@ -1917,8 +1918,9 @@ static void nfs_layoutget_begin(struct pnfs_layout_hdr *lo)
 
 static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)
 {
-       if (atomic_dec_and_test(&lo->plh_outstanding))
-               wake_up_var(&lo->plh_outstanding);
+       if (atomic_dec_and_test(&lo->plh_outstanding) &&
+           test_and_clear_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags))
+               wake_up_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN);
 }
 
 static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo)
@@ -2025,11 +2027,11 @@ lookup_again:
         * If the layout segment list is empty, but there are outstanding
         * layoutget calls, then they might be subject to a layoutrecall.
         */
-       if ((list_empty(&lo->plh_segs) || !pnfs_layout_is_valid(lo)) &&
+       if (test_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags) &&
            atomic_read(&lo->plh_outstanding) != 0) {
                spin_unlock(&ino->i_lock);
-               lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding,
-                                       !atomic_read(&lo->plh_outstanding)));
+               lseg = ERR_PTR(wait_on_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN,
+                                          TASK_KILLABLE));
                if (IS_ERR(lseg))
                        goto out_put_layout_hdr;
                pnfs_put_layout_hdr(lo);
@@ -2152,6 +2154,12 @@ lookup_again:
                case -ERECALLCONFLICT:
                case -EAGAIN:
                        break;
+               case -ENODATA:
+                       /* The server returned NFS4ERR_LAYOUTUNAVAILABLE */
+                       pnfs_layout_set_fail_bit(
+                               lo, pnfs_iomode_to_fail_bit(iomode));
+                       lseg = NULL;
+                       goto out_put_layout_hdr;
                default:
                        if (!nfs_error_is_fatal(PTR_ERR(lseg))) {
                                pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
@@ -2407,7 +2415,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                goto out_forget;
        }
 
-       if (!pnfs_layout_is_valid(lo) && !pnfs_is_first_layoutget(lo))
+       if (test_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags) &&
+           !pnfs_is_first_layoutget(lo))
                goto out_forget;
 
        if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
index 07f1148..f331f06 100644 (file)
@@ -105,6 +105,7 @@ enum {
        NFS_LAYOUT_FIRST_LAYOUTGET,     /* Serialize first layoutget */
        NFS_LAYOUT_INODE_FREEING,       /* The inode is being freed */
        NFS_LAYOUT_HASHED,              /* The layout visible */
+       NFS_LAYOUT_DRAIN,
 };
 
 enum layoutdriver_policy_flags {
index de72527..81d26ab 100644 (file)
@@ -553,7 +553,7 @@ struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
  *
  * Only one instances directory is allowed.
  *
- * The instances directory is special as it allows for mkdir and rmdir to
+ * The instances directory is special as it allows for mkdir and rmdir
  * to be done by userspace. When a mkdir or rmdir is performed, the inode
  * locks are released and the methods passed in (@mkdir and @rmdir) are
  * called without locks and with the name of the directory being created
index 836ab1b..1824f61 100644 (file)
@@ -997,9 +997,11 @@ xfs_attr_set(
        /*
         * We have no control over the attribute names that userspace passes us
         * to remove, so we have to allow the name lookup prior to attribute
-        * removal to fail as well.
+        * removal to fail as well.  Preserve the logged flag, since we need
+        * to pass that through to the logging code.
         */
-       args->op_flags = XFS_DA_OP_OKNOENT;
+       args->op_flags = XFS_DA_OP_OKNOENT |
+                                       (args->op_flags & XFS_DA_OP_LOGGED);
 
        if (args->value) {
                XFS_STATS_INC(mp, xs_attr_set);
@@ -1439,12 +1441,11 @@ static int
 xfs_attr_node_try_addname(
        struct xfs_attr_intent          *attr)
 {
-       struct xfs_da_args              *args = attr->xattri_da_args;
        struct xfs_da_state             *state = attr->xattri_da_state;
        struct xfs_da_state_blk         *blk;
        int                             error;
 
-       trace_xfs_attr_node_addname(args);
+       trace_xfs_attr_node_addname(state->args);
 
        blk = &state->path.blk[state->path.active-1];
        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
index e329da3..b4a2fc7 100644 (file)
@@ -28,16 +28,6 @@ struct xfs_attr_list_context;
  */
 #define        ATTR_MAX_VALUELEN       (64*1024)       /* max length of a value */
 
-static inline bool xfs_has_larp(struct xfs_mount *mp)
-{
-#ifdef DEBUG
-       /* Logged xattrs require a V5 super for log_incompat */
-       return xfs_has_crc(mp) && xfs_globals.larp;
-#else
-       return false;
-#endif
-}
-
 /*
  * Kernel-internal version of the attrlist cursor.
  */
@@ -624,7 +614,7 @@ static inline enum xfs_delattr_state
 xfs_attr_init_replace_state(struct xfs_da_args *args)
 {
        args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
-       if (xfs_has_larp(args->dp->i_mount))
+       if (args->op_flags & XFS_DA_OP_LOGGED)
                return xfs_attr_init_remove_state(args);
        return xfs_attr_init_add_state(args);
 }
index 15a9904..37e7c33 100644 (file)
@@ -1530,7 +1530,7 @@ xfs_attr3_leaf_add_work(
        if (tmp)
                entry->flags |= XFS_ATTR_LOCAL;
        if (args->op_flags & XFS_DA_OP_REPLACE) {
-               if (!xfs_has_larp(mp))
+               if (!(args->op_flags & XFS_DA_OP_LOGGED))
                        entry->flags |= XFS_ATTR_INCOMPLETE;
                if ((args->blkno2 == args->blkno) &&
                    (args->index2 <= args->index)) {
index d33b768..ffa3df5 100644 (file)
@@ -92,6 +92,7 @@ typedef struct xfs_da_args {
 #define XFS_DA_OP_NOTIME       (1u << 5) /* don't update inode timestamps */
 #define XFS_DA_OP_REMOVE       (1u << 6) /* this is a remove operation */
 #define XFS_DA_OP_RECOVERY     (1u << 7) /* Log recovery operation */
+#define XFS_DA_OP_LOGGED       (1u << 8) /* Use intent items to track op */
 
 #define XFS_DA_OP_FLAGS \
        { XFS_DA_OP_JUSTCHECK,  "JUSTCHECK" }, \
@@ -101,7 +102,8 @@ typedef struct xfs_da_args {
        { XFS_DA_OP_CILOOKUP,   "CILOOKUP" }, \
        { XFS_DA_OP_NOTIME,     "NOTIME" }, \
        { XFS_DA_OP_REMOVE,     "REMOVE" }, \
-       { XFS_DA_OP_RECOVERY,   "RECOVERY" }
+       { XFS_DA_OP_RECOVERY,   "RECOVERY" }, \
+       { XFS_DA_OP_LOGGED,     "LOGGED" }
 
 /*
  * Storage for holding state during Btree searches and split/join ops.
index 4a28c2d..135d441 100644 (file)
@@ -413,18 +413,20 @@ xfs_attr_create_intent(
        struct xfs_mount                *mp = tp->t_mountp;
        struct xfs_attri_log_item       *attrip;
        struct xfs_attr_intent          *attr;
+       struct xfs_da_args              *args;
 
        ASSERT(count == 1);
 
-       if (!xfs_sb_version_haslogxattrs(&mp->m_sb))
-               return NULL;
-
        /*
         * Each attr item only performs one attribute operation at a time, so
         * this is a list of one
         */
        attr = list_first_entry_or_null(items, struct xfs_attr_intent,
                        xattri_list);
+       args = attr->xattri_da_args;
+
+       if (!(args->op_flags & XFS_DA_OP_LOGGED))
+               return NULL;
 
        /*
         * Create a buffer to store the attribute name and value.  This buffer
@@ -432,8 +434,6 @@ xfs_attr_create_intent(
         * and the lower level xattr log items.
         */
        if (!attr->xattri_nameval) {
-               struct xfs_da_args      *args = attr->xattri_da_args;
-
                /*
                 * Transfer our reference to the name/value buffer to the
                 * deferred work state structure.
@@ -617,7 +617,10 @@ xfs_attri_item_recover(
        args->namelen = nv->name.i_len;
        args->hashval = xfs_da_hashname(args->name, args->namelen);
        args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
-       args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT;
+       args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
+                        XFS_DA_OP_LOGGED;
+
+       ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
 
        switch (attr->xattri_op_flags) {
        case XFS_ATTRI_OP_FLAGS_SET:
index 5a364a7..0d67ff8 100644 (file)
@@ -1096,7 +1096,8 @@ xfs_flags2diflags2(
 {
        uint64_t                di_flags2 =
                (ip->i_diflags2 & (XFS_DIFLAG2_REFLINK |
-                                  XFS_DIFLAG2_BIGTIME));
+                                  XFS_DIFLAG2_BIGTIME |
+                                  XFS_DIFLAG2_NREXT64));
 
        if (xflags & FS_XFLAG_DAX)
                di_flags2 |= XFS_DIFLAG2_DAX;
index 35e13e1..c325a28 100644 (file)
@@ -68,6 +68,18 @@ xfs_attr_rele_log_assist(
        xlog_drop_incompat_feat(mp->m_log);
 }
 
+static inline bool
+xfs_attr_want_log_assist(
+       struct xfs_mount        *mp)
+{
+#ifdef DEBUG
+       /* Logged xattrs require a V5 super for log_incompat */
+       return xfs_has_crc(mp) && xfs_globals.larp;
+#else
+       return false;
+#endif
+}
+
 /*
  * Set or remove an xattr, having grabbed the appropriate logging resources
  * prior to calling libxfs.
@@ -80,11 +92,14 @@ xfs_attr_change(
        bool                    use_logging = false;
        int                     error;
 
-       if (xfs_has_larp(mp)) {
+       ASSERT(!(args->op_flags & XFS_DA_OP_LOGGED));
+
+       if (xfs_attr_want_log_assist(mp)) {
                error = xfs_attr_grab_log_assist(mp);
                if (error)
                        return error;
 
+               args->op_flags |= XFS_DA_OP_LOGGED;
                use_logging = true;
        }
 
index 0777725..10b1990 100644 (file)
@@ -1022,6 +1022,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
        for ((__i) = 0; \
             (__i) < (__state)->num_private_objs && \
                     ((obj) = (__state)->private_objs[__i].ptr, \
+                     (void)(obj) /* Only to avoid unused-but-set-variable warning */, \
                      (new_obj_state) = (__state)->private_objs[__i].new_state, 1); \
             (__i)++)
 
index 4416536..ca89a48 100644 (file)
@@ -311,12 +311,12 @@ ttm_resource_manager_cleanup(struct ttm_resource_manager *man)
 }
 
 void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk);
-void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk,
-                          struct ttm_resource *res);
-void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
-                          struct ttm_resource *res);
 void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk);
 
+void ttm_resource_add_bulk_move(struct ttm_resource *res,
+                               struct ttm_buffer_object *bo);
+void ttm_resource_del_bulk_move(struct ttm_resource *res,
+                               struct ttm_buffer_object *bo);
 void ttm_resource_move_to_lru_tail(struct ttm_resource *res);
 
 void ttm_resource_init(struct ttm_buffer_object *bo,
index 6c5d496..69a13e1 100644 (file)
@@ -84,6 +84,9 @@ extern struct key *find_asymmetric_key(struct key *keyring,
                                       const struct asymmetric_key_id *id_2,
                                       bool partial);
 
+int x509_load_certificate_list(const u8 cert_list[], const unsigned long list_size,
+                              const struct key *keyring);
+
 /*
  * The payload is at the discretion of the subtype.
  */
index 2bd073f..d452071 100644 (file)
@@ -119,6 +119,8 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
 
 extern struct backing_dev_info noop_backing_dev_info;
 
+int bdi_init(struct backing_dev_info *bdi);
+
 /**
  * writeback_in_progress - determine whether there is writeback in progress
  * @wb: bdi_writeback of interest
index 608d577..bb6e3c3 100644 (file)
@@ -575,6 +575,7 @@ struct request_queue {
 #define QUEUE_FLAG_RQ_ALLOC_TIME 27    /* record rq->alloc_time_ns */
 #define QUEUE_FLAG_HCTX_ACTIVE 28      /* at least one blk-mq hctx is active */
 #define QUEUE_FLAG_NOWAIT       29     /* device supports NOWAIT */
+#define QUEUE_FLAG_SQ_SCHED     30     /* single queue style io dispatch */
 
 #define QUEUE_FLAG_MQ_DEFAULT  ((1 << QUEUE_FLAG_IO_STAT) |            \
                                 (1 << QUEUE_FLAG_SAME_COMP) |          \
@@ -616,6 +617,7 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
 #define blk_queue_pm_only(q)   atomic_read(&(q)->pm_only)
 #define blk_queue_registered(q)        test_bit(QUEUE_FLAG_REGISTERED, &(q)->queue_flags)
 #define blk_queue_nowait(q)    test_bit(QUEUE_FLAG_NOWAIT, &(q)->queue_flags)
+#define blk_queue_sq_sched(q)  test_bit(QUEUE_FLAG_SQ_SCHED, &(q)->queue_flags)
 
 extern void blk_set_pm_only(struct request_queue *q);
 extern void blk_clear_pm_only(struct request_queue *q);
@@ -1006,8 +1008,6 @@ void disk_set_independent_access_ranges(struct gendisk *disk,
  */
 /* Supports zoned block devices sequential write constraint */
 #define ELEVATOR_F_ZBD_SEQ_WRITE       (1U << 0)
-/* Supports scheduling on multiple hardware queues */
-#define ELEVATOR_F_MQ_AWARE            (1U << 1)
 
 extern void blk_queue_required_elevator_features(struct request_queue *q,
                                                 unsigned int features);
index 1436530..8c1686e 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/atomic.h>
 #include <linux/types.h>
-#include <linux/mutex.h>
 
 struct vc_data;
 struct console_font_op;
@@ -154,22 +153,6 @@ struct console {
        uint    ospeed;
        u64     seq;
        unsigned long dropped;
-       struct task_struct *thread;
-       bool    blocked;
-
-       /*
-        * The per-console lock is used by printing kthreads to synchronize
-        * this console with callers of console_lock(). This is necessary in
-        * order to allow printing kthreads to run in parallel to each other,
-        * while each safely accessing the @blocked field and synchronizing
-        * against direct printing via console_lock/console_unlock.
-        *
-        * Note: For synchronizing against direct printing via
-        *       console_trylock/console_unlock, see the static global
-        *       variable @console_kthreads_active.
-        */
-       struct mutex lock;
-
        void    *data;
        struct   console *next;
 };
index 54dc2f9..2c74773 100644 (file)
@@ -65,6 +65,9 @@ extern ssize_t cpu_show_tsx_async_abort(struct device *dev,
 extern ssize_t cpu_show_itlb_multihit(struct device *dev,
                                      struct device_attribute *attr, char *buf);
 extern ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_mmio_stale_data(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
 
 extern __printf(4, 5)
 struct device *cpu_device_create(struct device *parent, void *drvdata,
index 097cdd6..1773e5d 100644 (file)
@@ -304,7 +304,7 @@ static inline struct netfs_inode *netfs_inode(struct inode *inode)
 
 /**
  * netfs_inode_init - Initialise a netfslib inode context
- * @inode: The netfs inode to initialise
+ * @ctx: The netfs inode to initialise
  * @ops: The netfs's operations list
  *
  * Initialise the netfs library context struct.  This is expected to follow on
index 6491fa8..15b940e 100644 (file)
@@ -143,6 +143,12 @@ struct unwind_hint {
        .popsection
 .endm
 
+.macro STACK_FRAME_NON_STANDARD_FP func:req
+#ifdef CONFIG_FRAME_POINTER
+       STACK_FRAME_NON_STANDARD \func
+#endif
+.endm
+
 .macro ANNOTATE_NOENDBR
 .Lhere_\@:
        .pushsection .discard.noendbr
index 10ec29b..cf7d666 100644 (file)
@@ -169,9 +169,6 @@ extern void __printk_safe_exit(void);
 #define printk_deferred_enter __printk_safe_enter
 #define printk_deferred_exit __printk_safe_exit
 
-extern void printk_prefer_direct_enter(void);
-extern void printk_prefer_direct_exit(void);
-
 extern bool pr_flush(int timeout_ms, bool reset_on_progress);
 
 /*
@@ -224,14 +221,6 @@ static inline void printk_deferred_exit(void)
 {
 }
 
-static inline void printk_prefer_direct_enter(void)
-{
-}
-
-static inline void printk_prefer_direct_exit(void)
-{
-}
-
 static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
 {
        return true;
index c21c7f8..0022666 100644 (file)
@@ -23,12 +23,16 @@ struct ratelimit_state {
        unsigned long   flags;
 };
 
-#define RATELIMIT_STATE_INIT(name, interval_init, burst_init) {                \
-               .lock           = __RAW_SPIN_LOCK_UNLOCKED(name.lock),  \
-               .interval       = interval_init,                        \
-               .burst          = burst_init,                           \
+#define RATELIMIT_STATE_INIT_FLAGS(name, interval_init, burst_init, flags_init) { \
+               .lock           = __RAW_SPIN_LOCK_UNLOCKED(name.lock),            \
+               .interval       = interval_init,                                  \
+               .burst          = burst_init,                                     \
+               .flags          = flags_init,                                     \
        }
 
+#define RATELIMIT_STATE_INIT(name, interval_init, burst_init) \
+       RATELIMIT_STATE_INIT_FLAGS(name, interval_init, burst_init, 0)
+
 #define RATELIMIT_STATE_INIT_DISABLED                                  \
        RATELIMIT_STATE_INIT(ratelimit_state, 0, DEFAULT_RATELIMIT_BURST)
 
index cbd5070..657a0fc 100644 (file)
@@ -45,6 +45,7 @@ struct uart_ops {
        void            (*unthrottle)(struct uart_port *);
        void            (*send_xchar)(struct uart_port *, char ch);
        void            (*stop_rx)(struct uart_port *);
+       void            (*start_rx)(struct uart_port *);
        void            (*enable_ms)(struct uart_port *);
        void            (*break_ctl)(struct uart_port *, int ctl);
        int             (*startup)(struct uart_port *);
diff --git a/include/linux/visorbus.h b/include/linux/visorbus.h
deleted file mode 100644 (file)
index 0d8bd67..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
- * All rights reserved.
- */
-
-/*
- *  This header file is to be included by other kernel mode components that
- *  implement a particular kind of visor_device.  Each of these other kernel
- *  mode components is called a visor device driver.  Refer to visortemplate
- *  for a minimal sample visor device driver.
- *
- *  There should be nothing in this file that is private to the visorbus
- *  bus implementation itself.
- */
-
-#ifndef __VISORBUS_H__
-#define __VISORBUS_H__
-
-#include <linux/device.h>
-
-#define VISOR_CHANNEL_SIGNATURE ('L' << 24 | 'N' << 16 | 'C' << 8 | 'E')
-
-/*
- * enum channel_serverstate
- * @CHANNELSRV_UNINITIALIZED: Channel is in an undefined state.
- * @CHANNELSRV_READY:        Channel has been initialized by server.
- */
-enum channel_serverstate {
-       CHANNELSRV_UNINITIALIZED = 0,
-       CHANNELSRV_READY = 1
-};
-
-/*
- * enum channel_clientstate
- * @CHANNELCLI_DETACHED:
- * @CHANNELCLI_DISABLED:  Client can see channel but is NOT allowed to use it
- *                       unless given TBD* explicit request
- *                       (should actually be < DETACHED).
- * @CHANNELCLI_ATTACHING: Legacy EFI client request for EFI server to attach.
- * @CHANNELCLI_ATTACHED:  Idle, but client may want to use channel any time.
- * @CHANNELCLI_BUSY:     Client either wants to use or is using channel.
- * @CHANNELCLI_OWNED:    "No worries" state - client can access channel
- *                       anytime.
- */
-enum channel_clientstate {
-       CHANNELCLI_DETACHED = 0,
-       CHANNELCLI_DISABLED = 1,
-       CHANNELCLI_ATTACHING = 2,
-       CHANNELCLI_ATTACHED = 3,
-       CHANNELCLI_BUSY = 4,
-       CHANNELCLI_OWNED = 5
-};
-
-/*
- * Values for VISOR_CHANNEL_PROTOCOL.Features: This define exists so that
- * a guest can look at the FeatureFlags in the io channel, and configure the
- * driver to use interrupts or not based on this setting. All feature bits for
- * all channels should be defined here. The io channel feature bits are defined
- * below.
- */
-#define VISOR_DRIVER_ENABLES_INTS (0x1ULL << 1)
-#define VISOR_CHANNEL_IS_POLLING (0x1ULL << 3)
-#define VISOR_IOVM_OK_DRIVER_DISABLING_INTS (0x1ULL << 4)
-#define VISOR_DRIVER_DISABLES_INTS (0x1ULL << 5)
-#define VISOR_DRIVER_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
-
-/*
- * struct channel_header - Common Channel Header
- * @signature:        Signature.
- * @legacy_state:      DEPRECATED - being replaced by.
- * @header_size:       sizeof(struct channel_header).
- * @size:             Total size of this channel in bytes.
- * @features:         Flags to modify behavior.
- * @chtype:           Channel type: data, bus, control, etc..
- * @partition_handle:  ID of guest partition.
- * @handle:           Device number of this channel in client.
- * @ch_space_offset:   Offset in bytes to channel specific area.
- * @version_id:               Struct channel_header Version ID.
- * @partition_index:   Index of guest partition.
- * @zone_uuid:        Guid of Channel's zone.
- * @cli_str_offset:    Offset from channel header to null-terminated
- *                    ClientString (0 if ClientString not present).
- * @cli_state_boot:    CHANNEL_CLIENTSTATE of pre-boot EFI client of this
- *                    channel.
- * @cmd_state_cli:     CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see
- *                    ServerStateUp, ServerStateDown, etc).
- * @cli_state_os:      CHANNEL_CLIENTSTATE of Guest OS client of this channel.
- * @ch_characteristic: CHANNEL_CHARACTERISTIC_<xxx>.
- * @cmd_state_srv:     CHANNEL_COMMANDSTATE (overloaded in Windows drivers, see
- *                    ServerStateUp, ServerStateDown, etc).
- * @srv_state:        CHANNEL_SERVERSTATE.
- * @cli_error_boot:    Bits to indicate err states for boot clients, so err
- *                    messages can be throttled.
- * @cli_error_os:      Bits to indicate err states for OS clients, so err
- *                    messages can be throttled.
- * @filler:           Pad out to 128 byte cacheline.
- * @recover_channel:   Please add all new single-byte values below here.
- */
-struct channel_header {
-       u64 signature;
-       u32 legacy_state;
-       /* SrvState, CliStateBoot, and CliStateOS below */
-       u32 header_size;
-       u64 size;
-       u64 features;
-       guid_t chtype;
-       u64 partition_handle;
-       u64 handle;
-       u64 ch_space_offset;
-       u32 version_id;
-       u32 partition_index;
-       guid_t zone_guid;
-       u32 cli_str_offset;
-       u32 cli_state_boot;
-       u32 cmd_state_cli;
-       u32 cli_state_os;
-       u32 ch_characteristic;
-       u32 cmd_state_srv;
-       u32 srv_state;
-       u8 cli_error_boot;
-       u8 cli_error_os;
-       u8 filler[1];
-       u8 recover_channel;
-} __packed;
-
-#define VISOR_CHANNEL_ENABLE_INTS (0x1ULL << 0)
-
-/*
- * struct signal_queue_header - Subheader for the Signal Type variation of the
- *                              Common Channel.
- * @version:         SIGNAL_QUEUE_HEADER Version ID.
- * @chtype:          Queue type: storage, network.
- * @size:            Total size of this queue in bytes.
- * @sig_base_offset:  Offset to signal queue area.
- * @features:        Flags to modify behavior.
- * @num_sent:        Total # of signals placed in this queue.
- * @num_overflows:    Total # of inserts failed due to full queue.
- * @signal_size:      Total size of a signal for this queue.
- * @max_slots:        Max # of slots in queue, 1 slot is always empty.
- * @max_signals:      Max # of signals in queue (MaxSignalSlots-1).
- * @head:            Queue head signal #.
- * @num_received:     Total # of signals removed from this queue.
- * @tail:            Queue tail signal.
- * @reserved1:       Reserved field.
- * @reserved2:       Reserved field.
- * @client_queue:
- * @num_irq_received: Total # of Interrupts received. This is incremented by the
- *                   ISR in the guest windows driver.
- * @num_empty:       Number of times that visor_signal_remove is called and
- *                   returned Empty Status.
- * @errorflags:              Error bits set during SignalReinit to denote trouble with
- *                   client's fields.
- * @filler:          Pad out to 64 byte cacheline.
- */
-struct signal_queue_header {
-       /* 1st cache line */
-       u32 version;
-       u32 chtype;
-       u64 size;
-       u64 sig_base_offset;
-       u64 features;
-       u64 num_sent;
-       u64 num_overflows;
-       u32 signal_size;
-       u32 max_slots;
-       u32 max_signals;
-       u32 head;
-       /* 2nd cache line */
-       u64 num_received;
-       u32 tail;
-       u32 reserved1;
-       u64 reserved2;
-       u64 client_queue;
-       u64 num_irq_received;
-       u64 num_empty;
-       u32 errorflags;
-       u8 filler[12];
-} __packed;
-
-/* VISORCHANNEL Guids */
-/* {414815ed-c58c-11da-95a9-00e08161165f} */
-#define VISOR_VHBA_CHANNEL_GUID \
-       GUID_INIT(0x414815ed, 0xc58c, 0x11da, \
-                 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
-#define VISOR_VHBA_CHANNEL_GUID_STR \
-       "414815ed-c58c-11da-95a9-00e08161165f"
-struct visorchipset_state {
-       u32 created:1;
-       u32 attached:1;
-       u32 configured:1;
-       u32 running:1;
-       /* Remaining bits in this 32-bit word are reserved. */
-};
-
-/**
- * struct visor_device - A device type for things "plugged" into the visorbus
- *                       bus
- * @visorchannel:              Points to the channel that the device is
- *                             associated with.
- * @channel_type_guid:         Identifies the channel type to the bus driver.
- * @device:                    Device struct meant for use by the bus driver
- *                             only.
- * @list_all:                  Used by the bus driver to enumerate devices.
- * @timer:                     Timer fired periodically to do interrupt-type
- *                             activity.
- * @being_removed:             Indicates that the device is being removed from
- *                             the bus. Private bus driver use only.
- * @visordriver_callback_lock: Used by the bus driver to lock when adding and
- *                             removing devices.
- * @pausing:                   Indicates that a change towards a paused state.
- *                             is in progress. Only modified by the bus driver.
- * @resuming:                  Indicates that a change towards a running state
- *                             is in progress. Only modified by the bus driver.
- * @chipset_bus_no:            Private field used by the bus driver.
- * @chipset_dev_no:            Private field used the bus driver.
- * @state:                     Used to indicate the current state of the
- *                             device.
- * @inst:                      Unique GUID for this instance of the device.
- * @name:                      Name of the device.
- * @pending_msg_hdr:           For private use by bus driver to respond to
- *                             hypervisor requests.
- * @vbus_hdr_info:             A pointer to header info. Private use by bus
- *                             driver.
- * @partition_guid:            Indicates client partion id. This should be the
- *                             same across all visor_devices in the current
- *                             guest. Private use by bus driver only.
- */
-struct visor_device {
-       struct visorchannel *visorchannel;
-       guid_t channel_type_guid;
-       /* These fields are for private use by the bus driver only. */
-       struct device device;
-       struct list_head list_all;
-       struct timer_list timer;
-       bool timer_active;
-       bool being_removed;
-       struct mutex visordriver_callback_lock; /* synchronize probe/remove */
-       bool pausing;
-       bool resuming;
-       u32 chipset_bus_no;
-       u32 chipset_dev_no;
-       struct visorchipset_state state;
-       guid_t inst;
-       u8 *name;
-       struct controlvm_message_header *pending_msg_hdr;
-       void *vbus_hdr_info;
-       guid_t partition_guid;
-       struct dentry *debugfs_dir;
-       struct dentry *debugfs_bus_info;
-};
-
-#define to_visor_device(x) container_of(x, struct visor_device, device)
-
-typedef void (*visorbus_state_complete_func) (struct visor_device *dev,
-                                             int status);
-
-/*
- * This struct describes a specific visor channel, by providing its GUID, name,
- * and sizes.
- */
-struct visor_channeltype_descriptor {
-       const guid_t guid;
-       const char *name;
-       u64 min_bytes;
-       u32 version;
-};
-
-/**
- * struct visor_driver - Information provided by each visor driver when it
- *                       registers with the visorbus driver
- * @name:              Name of the visor driver.
- * @owner:             The module owner.
- * @channel_types:     Types of channels handled by this driver, ending with
- *                     a zero GUID. Our specialized BUS.match() method knows
- *                     about this list, and uses it to determine whether this
- *                     driver will in fact handle a new device that it has
- *                     detected.
- * @probe:             Called when a new device comes online, by our probe()
- *                     function specified by driver.probe() (triggered
- *                     ultimately by some call to driver_register(),
- *                     bus_add_driver(), or driver_attach()).
- * @remove:            Called when a new device is removed, by our remove()
- *                     function specified by driver.remove() (triggered
- *                     ultimately by some call to device_release_driver()).
- * @channel_interrupt: Called periodically, whenever there is a possiblity
- *                     that "something interesting" may have happened to the
- *                     channel.
- * @pause:             Called to initiate a change of the device's state.  If
- *                     the return valu`e is < 0, there was an error and the
- *                     state transition will NOT occur.  If the return value
- *                     is >= 0, then the state transition was INITIATED
- *                     successfully, and complete_func() will be called (or
- *                     was just called) with the final status when either the
- *                     state transition fails or completes successfully.
- * @resume:            Behaves similar to pause.
- * @driver:            Private reference to the device driver. For use by bus
- *                     driver only.
- */
-struct visor_driver {
-       const char *name;
-       struct module *owner;
-       struct visor_channeltype_descriptor *channel_types;
-       int (*probe)(struct visor_device *dev);
-       void (*remove)(struct visor_device *dev);
-       void (*channel_interrupt)(struct visor_device *dev);
-       int (*pause)(struct visor_device *dev,
-                    visorbus_state_complete_func complete_func);
-       int (*resume)(struct visor_device *dev,
-                     visorbus_state_complete_func complete_func);
-
-       /* These fields are for private use by the bus driver only. */
-       struct device_driver driver;
-};
-
-#define to_visor_driver(x) (container_of(x, struct visor_driver, driver))
-
-int visor_check_channel(struct channel_header *ch, struct device *dev,
-                       const guid_t *expected_uuid, char *chname,
-                       u64 expected_min_bytes, u32 expected_version,
-                       u64 expected_signature);
-
-int visorbus_register_visor_driver(struct visor_driver *drv);
-void visorbus_unregister_visor_driver(struct visor_driver *drv);
-int visorbus_read_channel(struct visor_device *dev,
-                         unsigned long offset, void *dest,
-                         unsigned long nbytes);
-int visorbus_write_channel(struct visor_device *dev,
-                          unsigned long offset, void *src,
-                          unsigned long nbytes);
-int visorbus_enable_channel_interrupts(struct visor_device *dev);
-void visorbus_disable_channel_interrupts(struct visor_device *dev);
-
-int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
-                             void *msg);
-int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
-                             void *msg);
-bool visorchannel_signalempty(struct visorchannel *channel, u32 queue);
-const guid_t *visorchannel_get_guid(struct visorchannel *channel);
-
-#define BUS_ROOT_DEVICE UINT_MAX
-struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
-                                              struct visor_device *from);
-#endif
index b159c27..096d48a 100644 (file)
@@ -215,6 +215,7 @@ extern struct vm_struct *__get_vm_area_caller(unsigned long size,
 void free_vm_area(struct vm_struct *area);
 extern struct vm_struct *remove_vm_area(const void *addr);
 extern struct vm_struct *find_vm_area(const void *addr);
+struct vmap_area *find_vmap_area(unsigned long addr);
 
 static inline bool is_vm_area_hugepages(const void *addr)
 {
index 077cd73..85cd695 100644 (file)
@@ -25,7 +25,6 @@
 #undef INET_CSK_CLEAR_TIMERS
 
 struct inet_bind_bucket;
-struct inet_bind2_bucket;
 struct tcp_congestion_ops;
 
 /*
@@ -58,7 +57,6 @@ struct inet_connection_sock_af_ops {
  *
  * @icsk_accept_queue:    FIFO of established children
  * @icsk_bind_hash:       Bind node
- * @icsk_bind2_hash:      Bind node in the bhash2 table
  * @icsk_timeout:         Timeout
  * @icsk_retransmit_timer: Resend (no ack)
  * @icsk_rto:             Retransmit timeout
@@ -85,7 +83,6 @@ struct inet_connection_sock {
        struct inet_sock          icsk_inet;
        struct request_sock_queue icsk_accept_queue;
        struct inet_bind_bucket   *icsk_bind_hash;
-       struct inet_bind2_bucket  *icsk_bind2_hash;
        unsigned long             icsk_timeout;
        struct timer_list         icsk_retransmit_timer;
        struct timer_list         icsk_delack_timer;
index a0887b7..ebfa3df 100644 (file)
@@ -90,32 +90,11 @@ struct inet_bind_bucket {
        struct hlist_head       owners;
 };
 
-struct inet_bind2_bucket {
-       possible_net_t          ib_net;
-       int                     l3mdev;
-       unsigned short          port;
-       union {
-#if IS_ENABLED(CONFIG_IPV6)
-               struct in6_addr         v6_rcv_saddr;
-#endif
-               __be32                  rcv_saddr;
-       };
-       /* Node in the inet2_bind_hashbucket chain */
-       struct hlist_node       node;
-       /* List of sockets hashed to this bucket */
-       struct hlist_head       owners;
-};
-
 static inline struct net *ib_net(struct inet_bind_bucket *ib)
 {
        return read_pnet(&ib->ib_net);
 }
 
-static inline struct net *ib2_net(struct inet_bind2_bucket *ib)
-{
-       return read_pnet(&ib->ib_net);
-}
-
 #define inet_bind_bucket_for_each(tb, head) \
        hlist_for_each_entry(tb, head, node)
 
@@ -124,15 +103,6 @@ struct inet_bind_hashbucket {
        struct hlist_head       chain;
 };
 
-/* This is synchronized using the inet_bind_hashbucket's spinlock.
- * Instead of having separate spinlocks, the inet_bind2_hashbucket can share
- * the inet_bind_hashbucket's given that in every case where the bhash2 table
- * is useful, a lookup in the bhash table also occurs.
- */
-struct inet_bind2_hashbucket {
-       struct hlist_head       chain;
-};
-
 /* Sockets can be hashed in established or listening table.
  * We must use different 'nulls' end-of-chain value for all hash buckets :
  * A socket might transition from ESTABLISH to LISTEN state without
@@ -164,12 +134,6 @@ struct inet_hashinfo {
         */
        struct kmem_cache               *bind_bucket_cachep;
        struct inet_bind_hashbucket     *bhash;
-       /* The 2nd binding table hashed by port and address.
-        * This is used primarily for expediting the resolution of bind
-        * conflicts.
-        */
-       struct kmem_cache               *bind2_bucket_cachep;
-       struct inet_bind2_hashbucket    *bhash2;
        unsigned int                    bhash_size;
 
        /* The 2nd listener table hashed by local port and address */
@@ -229,36 +193,6 @@ inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
 void inet_bind_bucket_destroy(struct kmem_cache *cachep,
                              struct inet_bind_bucket *tb);
 
-static inline bool check_bind_bucket_match(struct inet_bind_bucket *tb,
-                                          struct net *net,
-                                          const unsigned short port,
-                                          int l3mdev)
-{
-       return net_eq(ib_net(tb), net) && tb->port == port &&
-               tb->l3mdev == l3mdev;
-}
-
-struct inet_bind2_bucket *
-inet_bind2_bucket_create(struct kmem_cache *cachep, struct net *net,
-                        struct inet_bind2_hashbucket *head,
-                        const unsigned short port, int l3mdev,
-                        const struct sock *sk);
-
-void inet_bind2_bucket_destroy(struct kmem_cache *cachep,
-                              struct inet_bind2_bucket *tb);
-
-struct inet_bind2_bucket *
-inet_bind2_bucket_find(struct inet_hashinfo *hinfo, struct net *net,
-                      const unsigned short port, int l3mdev,
-                      struct sock *sk,
-                      struct inet_bind2_hashbucket **head);
-
-bool check_bind2_bucket_match_nulladdr(struct inet_bind2_bucket *tb,
-                                      struct net *net,
-                                      const unsigned short port,
-                                      int l3mdev,
-                                      const struct sock *sk);
-
 static inline u32 inet_bhashfn(const struct net *net, const __u16 lport,
                               const u32 bhash_size)
 {
@@ -266,7 +200,7 @@ static inline u32 inet_bhashfn(const struct net *net, const __u16 lport,
 }
 
 void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
-                   struct inet_bind2_bucket *tb2, const unsigned short snum);
+                   const unsigned short snum);
 
 /* Caller must disable local BH processing. */
 int __inet_inherit_port(const struct sock *sk, struct sock *child);
index c1b5dcd..daead5f 100644 (file)
@@ -253,6 +253,11 @@ struct inet_sock {
 #define IP_CMSG_CHECKSUM       BIT(7)
 #define IP_CMSG_RECVFRAGSIZE   BIT(8)
 
+static inline bool sk_is_inet(struct sock *sk)
+{
+       return sk->sk_family == AF_INET || sk->sk_family == AF_INET6;
+}
+
 /**
  * sk_to_full_sk - Access to a full socket
  * @sk: pointer to a socket
index c585ef6..72ca97c 100644 (file)
@@ -348,7 +348,6 @@ struct sk_filter;
   *    @sk_txtime_report_errors: set report errors mode for SO_TXTIME
   *    @sk_txtime_unused: unused txtime flags
   *    @ns_tracker: tracker for netns reference
-  *    @sk_bind2_node: bind node in the bhash2 table
   */
 struct sock {
        /*
@@ -538,7 +537,6 @@ struct sock {
 #endif
        struct rcu_head         sk_rcu;
        netns_tracker           ns_tracker;
-       struct hlist_node       sk_bind2_node;
 };
 
 enum sk_pacing {
@@ -819,16 +817,6 @@ static inline void sk_add_bind_node(struct sock *sk,
        hlist_add_head(&sk->sk_bind_node, list);
 }
 
-static inline void __sk_del_bind2_node(struct sock *sk)
-{
-       __hlist_del(&sk->sk_bind2_node);
-}
-
-static inline void sk_add_bind2_node(struct sock *sk, struct hlist_head *list)
-{
-       hlist_add_head(&sk->sk_bind2_node, list);
-}
-
 #define sk_for_each(__sk, list) \
        hlist_for_each_entry(__sk, list, sk_node)
 #define sk_for_each_rcu(__sk, list) \
@@ -846,8 +834,6 @@ static inline void sk_add_bind2_node(struct sock *sk, struct hlist_head *list)
        hlist_for_each_entry_safe(__sk, tmp, list, sk_node)
 #define sk_for_each_bound(__sk, list) \
        hlist_for_each_entry(__sk, list, sk_bind_node)
-#define sk_for_each_bound_bhash2(__sk, list) \
-       hlist_for_each_entry(__sk, list, sk_bind2_node)
 
 /**
  * sk_for_each_entry_offset_rcu - iterate over a list at a given struct offset
index f3a2abd..3a8c9d7 100644 (file)
@@ -1014,10 +1014,10 @@ static void audit_reset_context(struct audit_context *ctx)
        ctx->target_comm[0] = '\0';
        unroll_tree_refs(ctx, NULL, 0);
        WARN_ON(!list_empty(&ctx->killed_trees));
-       ctx->type = 0;
        audit_free_module(ctx);
        ctx->fds[0] = -1;
        audit_proctitle_free(ctx);
+       ctx->type = 0; /* reset last for audit_free_*() */
 }
 
 static inline struct audit_context *audit_alloc_context(enum audit_state state)
index 63d0ac7..eb12d4f 100644 (file)
@@ -4815,6 +4815,7 @@ static int btf_check_type_tags(struct btf_verifier_env *env,
        n = btf_nr_types(btf);
        for (i = start_id; i < n; i++) {
                const struct btf_type *t;
+               int chain_limit = 32;
                u32 cur_id = i;
 
                t = btf_type_by_id(btf, i);
@@ -4827,6 +4828,10 @@ static int btf_check_type_tags(struct btf_verifier_env *env,
 
                in_tags = btf_type_is_type_tag(t);
                while (btf_type_is_modifier(t)) {
+                       if (!chain_limit--) {
+                               btf_verifier_log(env, "Max chain length or cycle detected");
+                               return -ELOOP;
+                       }
                        if (btf_type_is_type_tag(t)) {
                                if (!in_tags) {
                                        btf_verifier_log(env, "Type tags don't precede modifiers");
index 9594cfd..08102d1 100644 (file)
@@ -281,6 +281,8 @@ static inline cfi_check_fn find_module_check_fn(unsigned long ptr)
 static inline cfi_check_fn find_check_fn(unsigned long ptr)
 {
        cfi_check_fn fn = NULL;
+       unsigned long flags;
+       bool rcu_idle;
 
        if (is_kernel_text(ptr))
                return __cfi_check;
@@ -290,13 +292,21 @@ static inline cfi_check_fn find_check_fn(unsigned long ptr)
         * the shadow and __module_address use RCU, so we need to wake it
         * up if necessary.
         */
-       RCU_NONIDLE({
-               if (IS_ENABLED(CONFIG_CFI_CLANG_SHADOW))
-                       fn = find_shadow_check_fn(ptr);
+       rcu_idle = !rcu_is_watching();
+       if (rcu_idle) {
+               local_irq_save(flags);
+               rcu_irq_enter();
+       }
+
+       if (IS_ENABLED(CONFIG_CFI_CLANG_SHADOW))
+               fn = find_shadow_check_fn(ptr);
+       if (!fn)
+               fn = find_module_check_fn(ptr);
 
-               if (!fn)
-                       fn = find_module_check_fn(ptr);
-       });
+       if (rcu_idle) {
+               rcu_irq_exit();
+               local_irq_restore(flags);
+       }
 
        return fn;
 }
index 80bfea5..cff3ae8 100644 (file)
@@ -127,8 +127,6 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
         * complain:
         */
        if (sysctl_hung_task_warnings) {
-               printk_prefer_direct_enter();
-
                if (sysctl_hung_task_warnings > 0)
                        sysctl_hung_task_warnings--;
                pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
@@ -144,8 +142,6 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 
                if (sysctl_hung_task_all_cpu_backtrace)
                        hung_task_show_all_bt = true;
-
-               printk_prefer_direct_exit();
        }
 
        touch_nmi_watchdog();
@@ -208,17 +204,12 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
        }
  unlock:
        rcu_read_unlock();
-       if (hung_task_show_lock) {
-               printk_prefer_direct_enter();
+       if (hung_task_show_lock)
                debug_show_all_locks();
-               printk_prefer_direct_exit();
-       }
 
        if (hung_task_show_all_bt) {
                hung_task_show_all_bt = false;
-               printk_prefer_direct_enter();
                trigger_all_cpu_backtrace();
-               printk_prefer_direct_exit();
        }
 
        if (hung_task_call_panic)
index e6b8e56..886789d 100644 (file)
@@ -1006,8 +1006,10 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
                if (desc->irq_data.chip != &no_irq_chip)
                        mask_ack_irq(desc);
                irq_state_set_disabled(desc);
-               if (is_chained)
+               if (is_chained) {
                        desc->action = NULL;
+                       WARN_ON(irq_chip_pm_put(irq_desc_get_irq_data(desc)));
+               }
                desc->depth = 1;
        }
        desc->handle_irq = handle;
@@ -1033,6 +1035,7 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
                irq_settings_set_norequest(desc);
                irq_settings_set_nothread(desc);
                desc->action = &chained_action;
+               WARN_ON(irq_chip_pm_get(irq_desc_get_irq_data(desc)));
                irq_activate_and_startup(desc, IRQ_RESEND);
        }
 }
index 81e8728..f06b91c 100644 (file)
@@ -5432,7 +5432,7 @@ static struct pin_cookie __lock_pin_lock(struct lockdep_map *lock)
                         * be guessable and still allows some pin nesting in
                         * our u32 pin_count.
                         */
-                       cookie.val = 1 + (prandom_u32() >> 16);
+                       cookie.val = 1 + (sched_clock() & 0xffff);
                        hlock->pin_count += cookie.val;
                        return cookie;
                }
index a3c758d..a3308af 100644 (file)
@@ -603,8 +603,6 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
 {
        disable_trace_on_warning();
 
-       printk_prefer_direct_enter();
-
        if (file)
                pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n",
                        raw_smp_processor_id(), current->pid, file, line,
@@ -634,8 +632,6 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
 
        /* Just a warning, don't kill lockdep. */
        add_taint(taint, LOCKDEP_STILL_OK);
-
-       printk_prefer_direct_exit();
 }
 
 #ifndef __WARN_FLAGS
index 20a66bf..89c71fc 100644 (file)
@@ -665,7 +665,7 @@ static void power_down(void)
                hibernation_platform_enter();
                fallthrough;
        case HIBERNATION_SHUTDOWN:
-               if (pm_power_off)
+               if (kernel_can_power_off())
                        kernel_power_off();
                break;
        }
index ea3dd55..b49c6ff 100644 (file)
@@ -223,33 +223,6 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
 /* Number of registered extended console drivers. */
 static int nr_ext_console_drivers;
 
-/*
- * Used to synchronize printing kthreads against direct printing via
- * console_trylock/console_unlock.
- *
- * Values:
- * -1 = console kthreads atomically blocked (via global trylock)
- *  0 = no kthread printing, console not locked (via trylock)
- * >0 = kthread(s) actively printing
- *
- * Note: For synchronizing against direct printing via
- *       console_lock/console_unlock, see the @lock variable in
- *       struct console.
- */
-static atomic_t console_kthreads_active = ATOMIC_INIT(0);
-
-#define console_kthreads_atomic_tryblock() \
-       (atomic_cmpxchg(&console_kthreads_active, 0, -1) == 0)
-#define console_kthreads_atomic_unblock() \
-       atomic_cmpxchg(&console_kthreads_active, -1, 0)
-#define console_kthreads_atomically_blocked() \
-       (atomic_read(&console_kthreads_active) == -1)
-
-#define console_kthread_printing_tryenter() \
-       atomic_inc_unless_negative(&console_kthreads_active)
-#define console_kthread_printing_exit() \
-       atomic_dec(&console_kthreads_active)
-
 /*
  * Helper macros to handle lockdep when locking/unlocking console_sem. We use
  * macros instead of functions so that _RET_IP_ contains useful information.
@@ -298,49 +271,14 @@ static bool panic_in_progress(void)
 }
 
 /*
- * Tracks whether kthread printers are all blocked. A value of true implies
- * that the console is locked via console_lock() or the console is suspended.
- * Writing to this variable requires holding @console_sem.
+ * This is used for debugging the mess that is the VT code by
+ * keeping track if we have the console semaphore held. It's
+ * definitely not the perfect debug tool (we don't know if _WE_
+ * hold it and are racing, but it helps tracking those weird code
+ * paths in the console code where we end up in places I want
+ * locked without the console semaphore held).
  */
-static bool console_kthreads_blocked;
-
-/*
- * Block all kthread printers from a schedulable context.
- *
- * Requires holding @console_sem.
- */
-static void console_kthreads_block(void)
-{
-       struct console *con;
-
-       for_each_console(con) {
-               mutex_lock(&con->lock);
-               con->blocked = true;
-               mutex_unlock(&con->lock);
-       }
-
-       console_kthreads_blocked = true;
-}
-
-/*
- * Unblock all kthread printers from a schedulable context.
- *
- * Requires holding @console_sem.
- */
-static void console_kthreads_unblock(void)
-{
-       struct console *con;
-
-       for_each_console(con) {
-               mutex_lock(&con->lock);
-               con->blocked = false;
-               mutex_unlock(&con->lock);
-       }
-
-       console_kthreads_blocked = false;
-}
-
-static int console_suspended;
+static int console_locked, console_suspended;
 
 /*
  *     Array of consoles built from command line options (console=)
@@ -423,75 +361,7 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
 /* syslog_lock protects syslog_* variables and write access to clear_seq. */
 static DEFINE_MUTEX(syslog_lock);
 
-/*
- * A flag to signify if printk_activate_kthreads() has already started the
- * kthread printers. If true, any later registered consoles must start their
- * own kthread directly. The flag is write protected by the console_lock.
- */
-static bool printk_kthreads_available;
-
 #ifdef CONFIG_PRINTK
-static atomic_t printk_prefer_direct = ATOMIC_INIT(0);
-
-/**
- * printk_prefer_direct_enter - cause printk() calls to attempt direct
- *                              printing to all enabled consoles
- *
- * Since it is not possible to call into the console printing code from any
- * context, there is no guarantee that direct printing will occur.
- *
- * This globally effects all printk() callers.
- *
- * Context: Any context.
- */
-void printk_prefer_direct_enter(void)
-{
-       atomic_inc(&printk_prefer_direct);
-}
-
-/**
- * printk_prefer_direct_exit - restore printk() behavior
- *
- * Context: Any context.
- */
-void printk_prefer_direct_exit(void)
-{
-       WARN_ON(atomic_dec_if_positive(&printk_prefer_direct) < 0);
-}
-
-/*
- * Calling printk() always wakes kthread printers so that they can
- * flush the new message to their respective consoles. Also, if direct
- * printing is allowed, printk() tries to flush the messages directly.
- *
- * Direct printing is allowed in situations when the kthreads
- * are not available or the system is in a problematic state.
- *
- * See the implementation about possible races.
- */
-static inline bool allow_direct_printing(void)
-{
-       /*
-        * Checking kthread availability is a possible race because the
-        * kthread printers can become permanently disabled during runtime.
-        * However, doing that requires holding the console_lock, so any
-        * pending messages will be direct printed by console_unlock().
-        */
-       if (!printk_kthreads_available)
-               return true;
-
-       /*
-        * Prefer direct printing when the system is in a problematic state.
-        * The context that sets this state will always see the updated value.
-        * The other contexts do not care. Anyway, direct printing is just a
-        * best effort. The direct output is only possible when console_lock
-        * is not already taken and no kthread printers are actively printing.
-        */
-       return (system_state > SYSTEM_RUNNING ||
-               oops_in_progress ||
-               atomic_read(&printk_prefer_direct));
-}
-
 DECLARE_WAIT_QUEUE_HEAD(log_wait);
 /* All 3 protected by @syslog_lock. */
 /* the next printk record to read by syslog(READ) or /proc/kmsg */
@@ -2382,10 +2252,10 @@ asmlinkage int vprintk_emit(int facility, int level,
        printed_len = vprintk_store(facility, level, dev_info, fmt, args);
 
        /* If called from the scheduler, we can not call up(). */
-       if (!in_sched && allow_direct_printing()) {
+       if (!in_sched) {
                /*
                 * The caller may be holding system-critical or
-                * timing-sensitive locks. Disable preemption during direct
+                * timing-sensitive locks. Disable preemption during
                 * printing of all remaining records to all consoles so that
                 * this context can return as soon as possible. Hopefully
                 * another printk() caller will take over the printing.
@@ -2428,8 +2298,6 @@ EXPORT_SYMBOL(_printk);
 
 static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
 
-static void printk_start_kthread(struct console *con);
-
 #else /* CONFIG_PRINTK */
 
 #define CONSOLE_LOG_MAX                0
@@ -2463,8 +2331,6 @@ static void call_console_driver(struct console *con, const char *text, size_t le
 }
 static bool suppress_message_printing(int level) { return false; }
 static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
-static void printk_start_kthread(struct console *con) { }
-static bool allow_direct_printing(void) { return true; }
 
 #endif /* CONFIG_PRINTK */
 
@@ -2683,14 +2549,6 @@ static int console_cpu_notify(unsigned int cpu)
                /* If trylock fails, someone else is doing the printing */
                if (console_trylock())
                        console_unlock();
-               else {
-                       /*
-                        * If a new CPU comes online, the conditions for
-                        * printer_should_wake() may have changed for some
-                        * kthread printer with !CON_ANYTIME.
-                        */
-                       wake_up_klogd();
-               }
        }
        return 0;
 }
@@ -2710,7 +2568,7 @@ void console_lock(void)
        down_console_sem();
        if (console_suspended)
                return;
-       console_kthreads_block();
+       console_locked = 1;
        console_may_schedule = 1;
 }
 EXPORT_SYMBOL(console_lock);
@@ -2731,30 +2589,15 @@ int console_trylock(void)
                up_console_sem();
                return 0;
        }
-       if (!console_kthreads_atomic_tryblock()) {
-               up_console_sem();
-               return 0;
-       }
+       console_locked = 1;
        console_may_schedule = 0;
        return 1;
 }
 EXPORT_SYMBOL(console_trylock);
 
-/*
- * This is used to help to make sure that certain paths within the VT code are
- * running with the console lock held. It is definitely not the perfect debug
- * tool (it is not known if the VT code is the task holding the console lock),
- * but it helps tracking those weird code paths in the console code such as
- * when the console is suspended: where the console is not locked but no
- * console printing may occur.
- *
- * Note: This returns true when the console is suspended but is not locked.
- *       This is intentional because the VT code must consider that situation
- *       the same as if the console was locked.
- */
 int is_console_locked(void)
 {
-       return (console_kthreads_blocked || atomic_read(&console_kthreads_active));
+       return console_locked;
 }
 EXPORT_SYMBOL(is_console_locked);
 
@@ -2777,9 +2620,18 @@ static bool abandon_console_lock_in_panic(void)
        return atomic_read(&panic_cpu) != raw_smp_processor_id();
 }
 
-static inline bool __console_is_usable(short flags)
+/*
+ * Check if the given console is currently capable and allowed to print
+ * records.
+ *
+ * Requires the console_lock.
+ */
+static inline bool console_is_usable(struct console *con)
 {
-       if (!(flags & CON_ENABLED))
+       if (!(con->flags & CON_ENABLED))
+               return false;
+
+       if (!con->write)
                return false;
 
        /*
@@ -2788,43 +2640,15 @@ static inline bool __console_is_usable(short flags)
         * cope (CON_ANYTIME) don't call them until this CPU is officially up.
         */
        if (!cpu_online(raw_smp_processor_id()) &&
-           !(flags & CON_ANYTIME))
+           !(con->flags & CON_ANYTIME))
                return false;
 
        return true;
 }
 
-/*
- * Check if the given console is currently capable and allowed to print
- * records.
- *
- * Requires holding the console_lock.
- */
-static inline bool console_is_usable(struct console *con)
-{
-       if (!con->write)
-               return false;
-
-       return __console_is_usable(con->flags);
-}
-
 static void __console_unlock(void)
 {
-       /*
-        * Depending on whether console_lock() or console_trylock() was used,
-        * appropriately allow the kthread printers to continue.
-        */
-       if (console_kthreads_blocked)
-               console_kthreads_unblock();
-       else
-               console_kthreads_atomic_unblock();
-
-       /*
-        * New records may have arrived while the console was locked.
-        * Wake the kthread printers to print them.
-        */
-       wake_up_klogd();
-
+       console_locked = 0;
        up_console_sem();
 }
 
@@ -2842,19 +2666,17 @@ static void __console_unlock(void)
  *
  * @handover will be set to true if a printk waiter has taken over the
  * console_lock, in which case the caller is no longer holding the
- * console_lock. Otherwise it is set to false. A NULL pointer may be provided
- * to disable allowing the console_lock to be taken over by a printk waiter.
+ * console_lock. Otherwise it is set to false.
  *
  * Returns false if the given console has no next record to print, otherwise
  * true.
  *
- * Requires the console_lock if @handover is non-NULL.
- * Requires con->lock otherwise.
+ * Requires the console_lock.
  */
-static bool __console_emit_next_record(struct console *con, char *text, char *ext_text,
-                                      char *dropped_text, bool *handover)
+static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
+                                    char *dropped_text, bool *handover)
 {
-       static atomic_t panic_console_dropped = ATOMIC_INIT(0);
+       static int panic_console_dropped;
        struct printk_info info;
        struct printk_record r;
        unsigned long flags;
@@ -2863,8 +2685,7 @@ static bool __console_emit_next_record(struct console *con, char *text, char *ex
 
        prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX);
 
-       if (handover)
-               *handover = false;
+       *handover = false;
 
        if (!prb_read_valid(prb, con->seq, &r))
                return false;
@@ -2872,8 +2693,7 @@ static bool __console_emit_next_record(struct console *con, char *text, char *ex
        if (con->seq != r.info->seq) {
                con->dropped += r.info->seq - con->seq;
                con->seq = r.info->seq;
-               if (panic_in_progress() &&
-                   atomic_fetch_inc_relaxed(&panic_console_dropped) > 10) {
+               if (panic_in_progress() && panic_console_dropped++ > 10) {
                        suppress_panic_printk = 1;
                        pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
                }
@@ -2895,61 +2715,31 @@ static bool __console_emit_next_record(struct console *con, char *text, char *ex
                len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
        }
 
-       if (handover) {
-               /*
-                * While actively printing out messages, if another printk()
-                * were to occur on another CPU, it may wait for this one to
-                * finish. This task can not be preempted if there is a
-                * waiter waiting to take over.
-                *
-                * Interrupts are disabled because the hand over to a waiter
-                * must not be interrupted until the hand over is completed
-                * (@console_waiter is cleared).
-                */
-               printk_safe_enter_irqsave(flags);
-               console_lock_spinning_enable();
-
-               /* don't trace irqsoff print latency */
-               stop_critical_timings();
-       }
+       /*
+        * While actively printing out messages, if another printk()
+        * were to occur on another CPU, it may wait for this one to
+        * finish. This task can not be preempted if there is a
+        * waiter waiting to take over.
+        *
+        * Interrupts are disabled because the hand over to a waiter
+        * must not be interrupted until the hand over is completed
+        * (@console_waiter is cleared).
+        */
+       printk_safe_enter_irqsave(flags);
+       console_lock_spinning_enable();
 
+       stop_critical_timings();        /* don't trace print latency */
        call_console_driver(con, write_text, len, dropped_text);
+       start_critical_timings();
 
        con->seq++;
 
-       if (handover) {
-               start_critical_timings();
-               *handover = console_lock_spinning_disable_and_check();
-               printk_safe_exit_irqrestore(flags);
-       }
+       *handover = console_lock_spinning_disable_and_check();
+       printk_safe_exit_irqrestore(flags);
 skip:
        return true;
 }
 
-/*
- * Print a record for a given console, but allow another printk() caller to
- * take over the console_lock and continue printing.
- *
- * Requires the console_lock, but depending on @handover after the call, the
- * caller may no longer have the console_lock.
- *
- * See __console_emit_next_record() for argument and return details.
- */
-static bool console_emit_next_record_transferable(struct console *con, char *text, char *ext_text,
-                                                 char *dropped_text, bool *handover)
-{
-       /*
-        * Handovers are only supported if threaded printers are atomically
-        * blocked. The context taking over the console_lock may be atomic.
-        */
-       if (!console_kthreads_atomically_blocked()) {
-               *handover = false;
-               handover = NULL;
-       }
-
-       return __console_emit_next_record(con, text, ext_text, dropped_text, handover);
-}
-
 /*
  * Print out all remaining records to all consoles.
  *
@@ -2968,8 +2758,8 @@ static bool console_emit_next_record_transferable(struct console *con, char *tex
  * were flushed to all usable consoles. A returned false informs the caller
  * that everything was not flushed (either there were no usable consoles or
  * another context has taken over printing or it is a panic situation and this
- * is not the panic CPU or direct printing is not preferred). Regardless the
- * reason, the caller should assume it is not useful to immediately try again.
+ * is not the panic CPU). Regardless the reason, the caller should assume it
+ * is not useful to immediately try again.
  *
  * Requires the console_lock.
  */
@@ -2986,10 +2776,6 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
        *handover = false;
 
        do {
-               /* Let the kthread printers do the work if they can. */
-               if (!allow_direct_printing())
-                       return false;
-
                any_progress = false;
 
                for_each_console(con) {
@@ -3001,11 +2787,13 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
 
                        if (con->flags & CON_EXTENDED) {
                                /* Extended consoles do not print "dropped messages". */
-                               progress = console_emit_next_record_transferable(con, &text[0],
-                                                               &ext_text[0], NULL, handover);
+                               progress = console_emit_next_record(con, &text[0],
+                                                                   &ext_text[0], NULL,
+                                                                   handover);
                        } else {
-                               progress = console_emit_next_record_transferable(con, &text[0],
-                                                               NULL, &dropped_text[0], handover);
+                               progress = console_emit_next_record(con, &text[0],
+                                                                   NULL, &dropped_text[0],
+                                                                   handover);
                        }
                        if (*handover)
                                return false;
@@ -3120,13 +2908,10 @@ void console_unblank(void)
        if (oops_in_progress) {
                if (down_trylock_console_sem() != 0)
                        return;
-               if (!console_kthreads_atomic_tryblock()) {
-                       up_console_sem();
-                       return;
-               }
        } else
                console_lock();
 
+       console_locked = 1;
        console_may_schedule = 0;
        for_each_console(c)
                if ((c->flags & CON_ENABLED) && c->unblank)
@@ -3405,10 +3190,6 @@ void register_console(struct console *newcon)
                nr_ext_console_drivers++;
 
        newcon->dropped = 0;
-       newcon->thread = NULL;
-       newcon->blocked = true;
-       mutex_init(&newcon->lock);
-
        if (newcon->flags & CON_PRINTBUFFER) {
                /* Get a consistent copy of @syslog_seq. */
                mutex_lock(&syslog_lock);
@@ -3418,10 +3199,6 @@ void register_console(struct console *newcon)
                /* Begin with next message. */
                newcon->seq = prb_next_seq(prb);
        }
-
-       if (printk_kthreads_available)
-               printk_start_kthread(newcon);
-
        console_unlock();
        console_sysfs_notify();
 
@@ -3448,7 +3225,6 @@ EXPORT_SYMBOL(register_console);
 
 int unregister_console(struct console *console)
 {
-       struct task_struct *thd;
        struct console *con;
        int res;
 
@@ -3489,20 +3265,7 @@ int unregister_console(struct console *console)
                console_drivers->flags |= CON_CONSDEV;
 
        console->flags &= ~CON_ENABLED;
-
-       /*
-        * console->thread can only be cleared under the console lock. But
-        * stopping the thread must be done without the console lock. The
-        * task that clears @thread is the task that stops the kthread.
-        */
-       thd = console->thread;
-       console->thread = NULL;
-
        console_unlock();
-
-       if (thd)
-               kthread_stop(thd);
-
        console_sysfs_notify();
 
        if (console->exit)
@@ -3598,20 +3361,6 @@ static int __init printk_late_init(void)
 }
 late_initcall(printk_late_init);
 
-static int __init printk_activate_kthreads(void)
-{
-       struct console *con;
-
-       console_lock();
-       printk_kthreads_available = true;
-       for_each_console(con)
-               printk_start_kthread(con);
-       console_unlock();
-
-       return 0;
-}
-early_initcall(printk_activate_kthreads);
-
 #if defined CONFIG_PRINTK
 /* If @con is specified, only wait for that console. Otherwise wait for all. */
 static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress)
@@ -3686,206 +3435,11 @@ bool pr_flush(int timeout_ms, bool reset_on_progress)
 }
 EXPORT_SYMBOL(pr_flush);
 
-static void __printk_fallback_preferred_direct(void)
-{
-       printk_prefer_direct_enter();
-       pr_err("falling back to preferred direct printing\n");
-       printk_kthreads_available = false;
-}
-
-/*
- * Enter preferred direct printing, but never exit. Mark console threads as
- * unavailable. The system is then forever in preferred direct printing and
- * any printing threads will exit.
- *
- * Must *not* be called under console_lock. Use
- * __printk_fallback_preferred_direct() if already holding console_lock.
- */
-static void printk_fallback_preferred_direct(void)
-{
-       console_lock();
-       __printk_fallback_preferred_direct();
-       console_unlock();
-}
-
-/*
- * Print a record for a given console, not allowing another printk() caller
- * to take over. This is appropriate for contexts that do not have the
- * console_lock.
- *
- * See __console_emit_next_record() for argument and return details.
- */
-static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
-                                    char *dropped_text)
-{
-       return __console_emit_next_record(con, text, ext_text, dropped_text, NULL);
-}
-
-static bool printer_should_wake(struct console *con, u64 seq)
-{
-       short flags;
-
-       if (kthread_should_stop() || !printk_kthreads_available)
-               return true;
-
-       if (con->blocked ||
-           console_kthreads_atomically_blocked()) {
-               return false;
-       }
-
-       /*
-        * This is an unsafe read from con->flags, but a false positive is
-        * not a problem. Worst case it would allow the printer to wake up
-        * although it is disabled. But the printer will notice that when
-        * attempting to print and instead go back to sleep.
-        */
-       flags = data_race(READ_ONCE(con->flags));
-
-       if (!__console_is_usable(flags))
-               return false;
-
-       return prb_read_valid(prb, seq, NULL);
-}
-
-static int printk_kthread_func(void *data)
-{
-       struct console *con = data;
-       char *dropped_text = NULL;
-       char *ext_text = NULL;
-       u64 seq = 0;
-       char *text;
-       int error;
-
-       text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
-       if (!text) {
-               con_printk(KERN_ERR, con, "failed to allocate text buffer\n");
-               printk_fallback_preferred_direct();
-               goto out;
-       }
-
-       if (con->flags & CON_EXTENDED) {
-               ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
-               if (!ext_text) {
-                       con_printk(KERN_ERR, con, "failed to allocate ext_text buffer\n");
-                       printk_fallback_preferred_direct();
-                       goto out;
-               }
-       } else {
-               dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL);
-               if (!dropped_text) {
-                       con_printk(KERN_ERR, con, "failed to allocate dropped_text buffer\n");
-                       printk_fallback_preferred_direct();
-                       goto out;
-               }
-       }
-
-       con_printk(KERN_INFO, con, "printing thread started\n");
-
-       for (;;) {
-               /*
-                * Guarantee this task is visible on the waitqueue before
-                * checking the wake condition.
-                *
-                * The full memory barrier within set_current_state() of
-                * prepare_to_wait_event() pairs with the full memory barrier
-                * within wq_has_sleeper().
-                *
-                * This pairs with __wake_up_klogd:A.
-                */
-               error = wait_event_interruptible(log_wait,
-                               printer_should_wake(con, seq)); /* LMM(printk_kthread_func:A) */
-
-               if (kthread_should_stop() || !printk_kthreads_available)
-                       break;
-
-               if (error)
-                       continue;
-
-               error = mutex_lock_interruptible(&con->lock);
-               if (error)
-                       continue;
-
-               if (con->blocked ||
-                   !console_kthread_printing_tryenter()) {
-                       /* Another context has locked the console_lock. */
-                       mutex_unlock(&con->lock);
-                       continue;
-               }
-
-               /*
-                * Although this context has not locked the console_lock, it
-                * is known that the console_lock is not locked and it is not
-                * possible for any other context to lock the console_lock.
-                * Therefore it is safe to read con->flags.
-                */
-
-               if (!__console_is_usable(con->flags)) {
-                       console_kthread_printing_exit();
-                       mutex_unlock(&con->lock);
-                       continue;
-               }
-
-               /*
-                * Even though the printk kthread is always preemptible, it is
-                * still not allowed to call cond_resched() from within
-                * console drivers. The task may become non-preemptible in the
-                * console driver call chain. For example, vt_console_print()
-                * takes a spinlock and then can call into fbcon_redraw(),
-                * which can conditionally invoke cond_resched().
-                */
-               console_may_schedule = 0;
-               console_emit_next_record(con, text, ext_text, dropped_text);
-
-               seq = con->seq;
-
-               console_kthread_printing_exit();
-
-               mutex_unlock(&con->lock);
-       }
-
-       con_printk(KERN_INFO, con, "printing thread stopped\n");
-out:
-       kfree(dropped_text);
-       kfree(ext_text);
-       kfree(text);
-
-       console_lock();
-       /*
-        * If this kthread is being stopped by another task, con->thread will
-        * already be NULL. That is fine. The important thing is that it is
-        * NULL after the kthread exits.
-        */
-       con->thread = NULL;
-       console_unlock();
-
-       return 0;
-}
-
-/* Must be called under console_lock. */
-static void printk_start_kthread(struct console *con)
-{
-       /*
-        * Do not start a kthread if there is no write() callback. The
-        * kthreads assume the write() callback exists.
-        */
-       if (!con->write)
-               return;
-
-       con->thread = kthread_run(printk_kthread_func, con,
-                                 "pr/%s%d", con->name, con->index);
-       if (IS_ERR(con->thread)) {
-               con->thread = NULL;
-               con_printk(KERN_ERR, con, "unable to start printing thread\n");
-               __printk_fallback_preferred_direct();
-               return;
-       }
-}
-
 /*
  * Delayed printk version, for scheduler-internal messages:
  */
-#define PRINTK_PENDING_WAKEUP          0x01
-#define PRINTK_PENDING_DIRECT_OUTPUT   0x02
+#define PRINTK_PENDING_WAKEUP  0x01
+#define PRINTK_PENDING_OUTPUT  0x02
 
 static DEFINE_PER_CPU(int, printk_pending);
 
@@ -3893,14 +3447,10 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work)
 {
        int pending = this_cpu_xchg(printk_pending, 0);
 
-       if (pending & PRINTK_PENDING_DIRECT_OUTPUT) {
-               printk_prefer_direct_enter();
-
+       if (pending & PRINTK_PENDING_OUTPUT) {
                /* If trylock fails, someone else is doing the printing */
                if (console_trylock())
                        console_unlock();
-
-               printk_prefer_direct_exit();
        }
 
        if (pending & PRINTK_PENDING_WAKEUP)
@@ -3925,11 +3475,10 @@ static void __wake_up_klogd(int val)
         * prepare_to_wait_event(), which is called after ___wait_event() adds
         * the waiter but before it has checked the wait condition.
         *
-        * This pairs with devkmsg_read:A, syslog_print:A, and
-        * printk_kthread_func:A.
+        * This pairs with devkmsg_read:A and syslog_print:A.
         */
        if (wq_has_sleeper(&log_wait) || /* LMM(__wake_up_klogd:A) */
-           (val & PRINTK_PENDING_DIRECT_OUTPUT)) {
+           (val & PRINTK_PENDING_OUTPUT)) {
                this_cpu_or(printk_pending, val);
                irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
        }
@@ -3947,17 +3496,7 @@ void defer_console_output(void)
         * New messages may have been added directly to the ringbuffer
         * using vprintk_store(), so wake any waiters as well.
         */
-       int val = PRINTK_PENDING_WAKEUP;
-
-       /*
-        * Make sure that some context will print the messages when direct
-        * printing is allowed. This happens in situations when the kthreads
-        * may not be as reliable or perhaps unusable.
-        */
-       if (allow_direct_printing())
-               val |= PRINTK_PENDING_DIRECT_OUTPUT;
-
-       __wake_up_klogd(val);
+       __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT);
 }
 
 void printk_trigger_flush(void)
index 4995c07..a001e1e 100644 (file)
@@ -647,7 +647,6 @@ static void print_cpu_stall(unsigned long gps)
         * See Documentation/RCU/stallwarn.rst for info on how to debug
         * RCU CPU stall warnings.
         */
-       printk_prefer_direct_enter();
        trace_rcu_stall_warning(rcu_state.name, TPS("SelfDetected"));
        pr_err("INFO: %s self-detected stall on CPU\n", rcu_state.name);
        raw_spin_lock_irqsave_rcu_node(rdp->mynode, flags);
@@ -685,7 +684,6 @@ static void print_cpu_stall(unsigned long gps)
         */
        set_tsk_need_resched(current);
        set_preempt_need_resched();
-       printk_prefer_direct_exit();
 }
 
 static void check_cpu_stall(struct rcu_data *rdp)
index b5a71d1..3c35445 100644 (file)
@@ -819,11 +819,9 @@ static int __orderly_reboot(void)
        ret = run_cmd(reboot_cmd);
 
        if (ret) {
-               printk_prefer_direct_enter();
                pr_warn("Failed to start orderly reboot: forcing the issue\n");
                emergency_sync();
                kernel_restart(NULL);
-               printk_prefer_direct_exit();
        }
 
        return ret;
@@ -836,7 +834,6 @@ static int __orderly_poweroff(bool force)
        ret = run_cmd(poweroff_cmd);
 
        if (ret && force) {
-               printk_prefer_direct_enter();
                pr_warn("Failed to start orderly shutdown: forcing the issue\n");
 
                /*
@@ -846,7 +843,6 @@ static int __orderly_poweroff(bool force)
                 */
                emergency_sync();
                kernel_power_off();
-               printk_prefer_direct_exit();
        }
 
        return ret;
@@ -904,8 +900,6 @@ EXPORT_SYMBOL_GPL(orderly_reboot);
  */
 static void hw_failure_emergency_poweroff_func(struct work_struct *work)
 {
-       printk_prefer_direct_enter();
-
        /*
         * We have reached here after the emergency shutdown waiting period has
         * expired. This means orderly_poweroff has not been able to shut off
@@ -922,8 +916,6 @@ static void hw_failure_emergency_poweroff_func(struct work_struct *work)
         */
        pr_emerg("Hardware protection shutdown failed. Trying emergency restart\n");
        emergency_restart();
-
-       printk_prefer_direct_exit();
 }
 
 static DECLARE_DELAYED_WORK(hw_failure_emergency_poweroff_work,
@@ -962,13 +954,11 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced)
 {
        static atomic_t allow_proceed = ATOMIC_INIT(1);
 
-       printk_prefer_direct_enter();
-
        pr_emerg("HARDWARE PROTECTION shutdown (%s)\n", reason);
 
        /* Shutdown should be initiated only once. */
        if (!atomic_dec_and_test(&allow_proceed))
-               goto out;
+               return;
 
        /*
         * Queue a backup emergency shutdown in the event of
@@ -976,8 +966,6 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced)
         */
        hw_failure_emergency_poweroff(ms_until_forced);
        orderly_poweroff(true);
-out:
-       printk_prefer_direct_exit();
 }
 EXPORT_SYMBOL_GPL(hw_protection_shutdown);
 
index bfa7452..da0bf6f 100644 (file)
@@ -4798,25 +4798,55 @@ static void do_balance_callbacks(struct rq *rq, struct callback_head *head)
 
 static void balance_push(struct rq *rq);
 
+/*
+ * balance_push_callback is a right abuse of the callback interface and plays
+ * by significantly different rules.
+ *
+ * Where the normal balance_callback's purpose is to be ran in the same context
+ * that queued it (only later, when it's safe to drop rq->lock again),
+ * balance_push_callback is specifically targeted at __schedule().
+ *
+ * This abuse is tolerated because it places all the unlikely/odd cases behind
+ * a single test, namely: rq->balance_callback == NULL.
+ */
 struct callback_head balance_push_callback = {
        .next = NULL,
        .func = (void (*)(struct callback_head *))balance_push,
 };
 
-static inline struct callback_head *splice_balance_callbacks(struct rq *rq)
+static inline struct callback_head *
+__splice_balance_callbacks(struct rq *rq, bool split)
 {
        struct callback_head *head = rq->balance_callback;
 
+       if (likely(!head))
+               return NULL;
+
        lockdep_assert_rq_held(rq);
-       if (head)
+       /*
+        * Must not take balance_push_callback off the list when
+        * splice_balance_callbacks() and balance_callbacks() are not
+        * in the same rq->lock section.
+        *
+        * In that case it would be possible for __schedule() to interleave
+        * and observe the list empty.
+        */
+       if (split && head == &balance_push_callback)
+               head = NULL;
+       else
                rq->balance_callback = NULL;
 
        return head;
 }
 
+static inline struct callback_head *splice_balance_callbacks(struct rq *rq)
+{
+       return __splice_balance_callbacks(rq, true);
+}
+
 static void __balance_callbacks(struct rq *rq)
 {
-       do_balance_callbacks(rq, splice_balance_callbacks(rq));
+       do_balance_callbacks(rq, __splice_balance_callbacks(rq, false));
 }
 
 static inline void balance_callbacks(struct rq *rq, struct callback_head *head)
index 0125961..47b89a0 100644 (file)
@@ -1693,6 +1693,11 @@ queue_balance_callback(struct rq *rq,
 {
        lockdep_assert_rq_held(rq);
 
+       /*
+        * Don't (re)queue an already queued item; nor queue anything when
+        * balance_push() is active, see the comment with
+        * balance_push_callback.
+        */
        if (unlikely(head->next || rq->balance_callback == &balance_push_callback))
                return;
 
index 7a13e6a..88589d7 100644 (file)
@@ -2423,7 +2423,7 @@ kprobe_multi_link_handler(struct fprobe *fp, unsigned long entry_ip,
        kprobe_multi_link_prog_run(link, entry_ip, regs);
 }
 
-static int symbols_cmp(const void *a, const void *b)
+static int symbols_cmp_r(const void *a, const void *b, const void *priv)
 {
        const char **str_a = (const char **) a;
        const char **str_b = (const char **) b;
@@ -2431,6 +2431,28 @@ static int symbols_cmp(const void *a, const void *b)
        return strcmp(*str_a, *str_b);
 }
 
+struct multi_symbols_sort {
+       const char **funcs;
+       u64 *cookies;
+};
+
+static void symbols_swap_r(void *a, void *b, int size, const void *priv)
+{
+       const struct multi_symbols_sort *data = priv;
+       const char **name_a = a, **name_b = b;
+
+       swap(*name_a, *name_b);
+
+       /* If defined, swap also related cookies. */
+       if (data->cookies) {
+               u64 *cookie_a, *cookie_b;
+
+               cookie_a = data->cookies + (name_a - data->funcs);
+               cookie_b = data->cookies + (name_b - data->funcs);
+               swap(*cookie_a, *cookie_b);
+       }
+}
+
 int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 {
        struct bpf_kprobe_multi_link *link = NULL;
@@ -2468,38 +2490,46 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
        if (!addrs)
                return -ENOMEM;
 
+       ucookies = u64_to_user_ptr(attr->link_create.kprobe_multi.cookies);
+       if (ucookies) {
+               cookies = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
+               if (!cookies) {
+                       err = -ENOMEM;
+                       goto error;
+               }
+               if (copy_from_user(cookies, ucookies, size)) {
+                       err = -EFAULT;
+                       goto error;
+               }
+       }
+
        if (uaddrs) {
                if (copy_from_user(addrs, uaddrs, size)) {
                        err = -EFAULT;
                        goto error;
                }
        } else {
+               struct multi_symbols_sort data = {
+                       .cookies = cookies,
+               };
                struct user_syms us;
 
                err = copy_user_syms(&us, usyms, cnt);
                if (err)
                        goto error;
 
-               sort(us.syms, cnt, sizeof(*us.syms), symbols_cmp, NULL);
+               if (cookies)
+                       data.funcs = us.syms;
+
+               sort_r(us.syms, cnt, sizeof(*us.syms), symbols_cmp_r,
+                      symbols_swap_r, &data);
+
                err = ftrace_lookup_symbols(us.syms, cnt, addrs);
                free_user_syms(&us);
                if (err)
                        goto error;
        }
 
-       ucookies = u64_to_user_ptr(attr->link_create.kprobe_multi.cookies);
-       if (ucookies) {
-               cookies = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL);
-               if (!cookies) {
-                       err = -ENOMEM;
-                       goto error;
-               }
-               if (copy_from_user(cookies, ucookies, size)) {
-                       err = -EFAULT;
-                       goto error;
-               }
-       }
-
        link = kzalloc(sizeof(*link), GFP_KERNEL);
        if (!link) {
                err = -ENOMEM;
index e750fe1..601ccf1 100644 (file)
@@ -8029,15 +8029,23 @@ static int kallsyms_callback(void *data, const char *name,
                             struct module *mod, unsigned long addr)
 {
        struct kallsyms_data *args = data;
+       const char **sym;
+       int idx;
 
-       if (!bsearch(&name, args->syms, args->cnt, sizeof(*args->syms), symbols_cmp))
+       sym = bsearch(&name, args->syms, args->cnt, sizeof(*args->syms), symbols_cmp);
+       if (!sym)
+               return 0;
+
+       idx = sym - args->syms;
+       if (args->addrs[idx])
                return 0;
 
        addr = ftrace_location(addr);
        if (!addr)
                return 0;
 
-       args->addrs[args->found++] = addr;
+       args->addrs[idx] = addr;
+       args->found++;
        return args->found == args->cnt ? 1 : 0;
 }
 
@@ -8062,6 +8070,7 @@ int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *a
        struct kallsyms_data args;
        int err;
 
+       memset(addrs, 0, sizeof(*addrs) * cnt);
        args.addrs = addrs;
        args.syms = sorted_syms;
        args.cnt = cnt;
index b568337..c69d822 100644 (file)
@@ -154,6 +154,15 @@ struct rethook_node *rethook_try_get(struct rethook *rh)
        if (unlikely(!handler))
                return NULL;
 
+       /*
+        * This expects the caller will set up a rethook on a function entry.
+        * When the function returns, the rethook will eventually be reclaimed
+        * or released in the rethook_recycle() with call_rcu().
+        * This means the caller must be run in the RCU-availabe context.
+        */
+       if (unlikely(!rcu_is_watching()))
+               return NULL;
+
        fn = freelist_try_get(&rh->pool);
        if (!fn)
                return NULL;
index 2c95992..a8cfac0 100644 (file)
@@ -6424,9 +6424,7 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
                synchronize_rcu();
                free_snapshot(tr);
        }
-#endif
 
-#ifdef CONFIG_TRACER_MAX_TRACE
        if (t->use_max_tr && !had_max_tr) {
                ret = tracing_alloc_snapshot_instance(tr);
                if (ret < 0)
index 9350733..a245ea6 100644 (file)
@@ -1718,8 +1718,17 @@ static int
 kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
        struct kretprobe *rp = get_kretprobe(ri);
-       struct trace_kprobe *tk = container_of(rp, struct trace_kprobe, rp);
+       struct trace_kprobe *tk;
+
+       /*
+        * There is a small chance that get_kretprobe(ri) returns NULL when
+        * the kretprobe is unregister on another CPU between kretprobe's
+        * trampoline_handler and this function.
+        */
+       if (unlikely(!rp))
+               return 0;
 
+       tk = container_of(rp, struct trace_kprobe, rp);
        raw_cpu_inc(*tk->nhit);
 
        if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE))
index 9711589..c3dc4f8 100644 (file)
@@ -546,7 +546,6 @@ static int __trace_uprobe_create(int argc, const char **argv)
        bool is_return = false;
        int i, ret;
 
-       ret = 0;
        ref_ctr_offset = 0;
 
        switch (argv[0][0]) {
index 20a7a55..ecb0e83 100644 (file)
@@ -424,8 +424,6 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
                /* Start period for the next softlockup warning. */
                update_report_ts();
 
-               printk_prefer_direct_enter();
-
                pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
                        smp_processor_id(), duration,
                        current->comm, task_pid_nr(current));
@@ -444,8 +442,6 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
                add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
                if (softlockup_panic)
                        panic("softlockup: hung tasks");
-
-               printk_prefer_direct_exit();
        }
 
        return HRTIMER_RESTART;
index 701f35f..247bf0b 100644 (file)
@@ -135,8 +135,6 @@ static void watchdog_overflow_callback(struct perf_event *event,
                if (__this_cpu_read(hard_watchdog_warn) == true)
                        return;
 
-               printk_prefer_direct_enter();
-
                pr_emerg("Watchdog detected hard LOCKUP on cpu %d\n",
                         this_cpu);
                print_modules();
@@ -157,8 +155,6 @@ static void watchdog_overflow_callback(struct perf_event *event,
                if (hardlockup_panic)
                        nmi_panic(regs, "Hard LOCKUP");
 
-               printk_prefer_direct_exit();
-
                __this_cpu_write(hard_watchdog_warn, true);
                return;
        }
index 6a84363..eaaad4d 100644 (file)
@@ -120,6 +120,9 @@ config INDIRECT_IOMEM_FALLBACK
 
 source "lib/crypto/Kconfig"
 
+config LIB_MEMNEQ
+       bool
+
 config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
index c4fe15d..a9f7eb0 100644 (file)
@@ -94,7 +94,7 @@ config UBSAN_UNREACHABLE
        bool "Perform checking for unreachable code"
        # objtool already handles unreachable checking and gets angry about
        # seeing UBSan instrumentation located in unreachable places.
-       depends on !(OBJTOOL && (STACK_VALIDATION || UNWINDER_ORC || X86_SMAP))
+       depends on !(OBJTOOL && (STACK_VALIDATION || UNWINDER_ORC || HAVE_UACCESS_VALIDATION))
        depends on $(cc-option,-fsanitize=unreachable)
        help
          This option enables -fsanitize=unreachable which checks for control
index ea54294..f99bf61 100644 (file)
@@ -251,6 +251,7 @@ obj-$(CONFIG_DIMLIB) += dim/
 obj-$(CONFIG_SIGNATURE) += digsig.o
 
 lib-$(CONFIG_CLZ_TAB) += clz_tab.o
+lib-$(CONFIG_LIB_MEMNEQ) += memneq.o
 
 obj-$(CONFIG_GENERIC_STRNCPY_FROM_USER) += strncpy_from_user.o
 obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o
index 9856e29..2082af4 100644 (file)
@@ -71,6 +71,7 @@ config CRYPTO_LIB_CURVE25519
        tristate "Curve25519 scalar multiplication library"
        depends on CRYPTO_ARCH_HAVE_LIB_CURVE25519 || !CRYPTO_ARCH_HAVE_LIB_CURVE25519
        select CRYPTO_LIB_CURVE25519_GENERIC if CRYPTO_ARCH_HAVE_LIB_CURVE25519=n
+       select LIB_MEMNEQ
        help
          Enable the Curve25519 library interface. This interface may be
          fulfilled by either the generic implementation or an arch-specific
diff --git a/lib/memneq.c b/lib/memneq.c
new file mode 100644 (file)
index 0000000..fb11608
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Constant-time equality testing of memory regions.
+ *
+ * Authors:
+ *
+ *   James Yonan <james@openvpn.net>
+ *   Daniel Borkmann <dborkman@redhat.com>
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * 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.
+ *   * Neither the name of OpenVPN Technologies nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#include <crypto/algapi.h>
+#include <asm/unaligned.h>
+
+#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ
+
+/* Generic path for arbitrary size */
+static inline unsigned long
+__crypto_memneq_generic(const void *a, const void *b, size_t size)
+{
+       unsigned long neq = 0;
+
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       while (size >= sizeof(unsigned long)) {
+               neq |= get_unaligned((unsigned long *)a) ^
+                      get_unaligned((unsigned long *)b);
+               OPTIMIZER_HIDE_VAR(neq);
+               a += sizeof(unsigned long);
+               b += sizeof(unsigned long);
+               size -= sizeof(unsigned long);
+       }
+#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+       while (size > 0) {
+               neq |= *(unsigned char *)a ^ *(unsigned char *)b;
+               OPTIMIZER_HIDE_VAR(neq);
+               a += 1;
+               b += 1;
+               size -= 1;
+       }
+       return neq;
+}
+
+/* Loop-free fast-path for frequently used 16-byte size */
+static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
+{
+       unsigned long neq = 0;
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       if (sizeof(unsigned long) == 8) {
+               neq |= get_unaligned((unsigned long *)a) ^
+                      get_unaligned((unsigned long *)b);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= get_unaligned((unsigned long *)(a + 8)) ^
+                      get_unaligned((unsigned long *)(b + 8));
+               OPTIMIZER_HIDE_VAR(neq);
+       } else if (sizeof(unsigned int) == 4) {
+               neq |= get_unaligned((unsigned int *)a) ^
+                      get_unaligned((unsigned int *)b);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= get_unaligned((unsigned int *)(a + 4)) ^
+                      get_unaligned((unsigned int *)(b + 4));
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= get_unaligned((unsigned int *)(a + 8)) ^
+                      get_unaligned((unsigned int *)(b + 8));
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= get_unaligned((unsigned int *)(a + 12)) ^
+                      get_unaligned((unsigned int *)(b + 12));
+               OPTIMIZER_HIDE_VAR(neq);
+       } else
+#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+       {
+               neq |= *(unsigned char *)(a)    ^ *(unsigned char *)(b);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+1)  ^ *(unsigned char *)(b+1);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+2)  ^ *(unsigned char *)(b+2);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+3)  ^ *(unsigned char *)(b+3);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+4)  ^ *(unsigned char *)(b+4);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+5)  ^ *(unsigned char *)(b+5);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+6)  ^ *(unsigned char *)(b+6);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+7)  ^ *(unsigned char *)(b+7);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+8)  ^ *(unsigned char *)(b+8);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+9)  ^ *(unsigned char *)(b+9);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15);
+               OPTIMIZER_HIDE_VAR(neq);
+       }
+
+       return neq;
+}
+
+/* Compare two areas of memory without leaking timing information,
+ * and with special optimizations for common sizes.  Users should
+ * not call this function directly, but should instead use
+ * crypto_memneq defined in crypto/algapi.h.
+ */
+noinline unsigned long __crypto_memneq(const void *a, const void *b,
+                                      size_t size)
+{
+       switch (size) {
+       case 16:
+               return __crypto_memneq_16(a, b);
+       default:
+               return __crypto_memneq_generic(a, b, size);
+       }
+}
+EXPORT_SYMBOL(__crypto_memneq);
+
+#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */
index ff60bd7..95550b8 100644 (file)
@@ -231,20 +231,13 @@ static __init int bdi_class_init(void)
 }
 postcore_initcall(bdi_class_init);
 
-static int bdi_init(struct backing_dev_info *bdi);
-
 static int __init default_bdi_init(void)
 {
-       int err;
-
        bdi_wq = alloc_workqueue("writeback", WQ_MEM_RECLAIM | WQ_UNBOUND |
                                 WQ_SYSFS, 0);
        if (!bdi_wq)
                return -ENOMEM;
-
-       err = bdi_init(&noop_backing_dev_info);
-
-       return err;
+       return 0;
 }
 subsys_initcall(default_bdi_init);
 
@@ -781,7 +774,7 @@ static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb)
 
 #endif /* CONFIG_CGROUP_WRITEBACK */
 
-static int bdi_init(struct backing_dev_info *bdi)
+int bdi_init(struct backing_dev_info *bdi)
 {
        int ret;
 
index ac3775c..ffdfbc8 100644 (file)
@@ -2385,6 +2385,8 @@ static void filemap_get_read_batch(struct address_space *mapping,
                        continue;
                if (xas.xa_index > max || xa_is_value(folio))
                        break;
+               if (xa_is_sibling(folio))
+                       break;
                if (!folio_try_get_rcu(folio))
                        goto retry;
 
@@ -2629,6 +2631,13 @@ err:
        return err;
 }
 
+static inline bool pos_same_folio(loff_t pos1, loff_t pos2, struct folio *folio)
+{
+       unsigned int shift = folio_shift(folio);
+
+       return (pos1 >> shift == pos2 >> shift);
+}
+
 /**
  * filemap_read - Read data from the page cache.
  * @iocb: The iocb to read.
@@ -2700,11 +2709,11 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
                writably_mapped = mapping_writably_mapped(mapping);
 
                /*
-                * When a sequential read accesses a page several times, only
+                * When a read accesses the same folio several times, only
                 * mark it as accessed the first time.
                 */
-               if (iocb->ki_pos >> PAGE_SHIFT !=
-                   ra->prev_pos >> PAGE_SHIFT)
+               if (!pos_same_folio(iocb->ki_pos, ra->prev_pos - 1,
+                                                       fbatch.folios[0]))
                        folio_mark_accessed(fbatch.folios[0]);
 
                for (i = 0; i < folio_batch_count(&fbatch); i++) {
index f724800..834f288 100644 (file)
@@ -2377,6 +2377,7 @@ static void __split_huge_page_tail(struct page *head, int tail,
                        page_tail);
        page_tail->mapping = head->mapping;
        page_tail->index = head->index + tail;
+       page_tail->private = 0;
 
        /* Page flags must be visible before we make the page non-compound. */
        smp_wmb();
index e51588e..6c1ea61 100644 (file)
@@ -1106,6 +1106,7 @@ static int unmap_and_move(new_page_t get_new_page,
        if (!newpage)
                return -ENOMEM;
 
+       newpage->private = 0;
        rc = __unmap_and_move(page, newpage, force, mode);
        if (rc == MIGRATEPAGE_SUCCESS)
                set_page_owner_migrate_reason(newpage, reason);
index 57a0151..fdcd28c 100644 (file)
@@ -510,6 +510,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
                        new_order--;
        }
 
+       filemap_invalidate_lock_shared(mapping);
        while (index <= limit) {
                unsigned int order = new_order;
 
@@ -536,6 +537,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
        }
 
        read_pages(ractl);
+       filemap_invalidate_unlock_shared(mapping);
 
        /*
         * If there were already pages in the page cache, then we may have
index e553502..b1281b8 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -726,25 +726,48 @@ static struct track *get_track(struct kmem_cache *s, void *object,
        return kasan_reset_tag(p + alloc);
 }
 
-static void noinline set_track(struct kmem_cache *s, void *object,
-                       enum track_item alloc, unsigned long addr)
-{
-       struct track *p = get_track(s, object, alloc);
-
 #ifdef CONFIG_STACKDEPOT
+static noinline depot_stack_handle_t set_track_prepare(void)
+{
+       depot_stack_handle_t handle;
        unsigned long entries[TRACK_ADDRS_COUNT];
        unsigned int nr_entries;
 
        nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3);
-       p->handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT);
+       handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT);
+
+       return handle;
+}
+#else
+static inline depot_stack_handle_t set_track_prepare(void)
+{
+       return 0;
+}
 #endif
 
+static void set_track_update(struct kmem_cache *s, void *object,
+                            enum track_item alloc, unsigned long addr,
+                            depot_stack_handle_t handle)
+{
+       struct track *p = get_track(s, object, alloc);
+
+#ifdef CONFIG_STACKDEPOT
+       p->handle = handle;
+#endif
        p->addr = addr;
        p->cpu = smp_processor_id();
        p->pid = current->pid;
        p->when = jiffies;
 }
 
+static __always_inline void set_track(struct kmem_cache *s, void *object,
+                                     enum track_item alloc, unsigned long addr)
+{
+       depot_stack_handle_t handle = set_track_prepare();
+
+       set_track_update(s, object, alloc, addr, handle);
+}
+
 static void init_tracking(struct kmem_cache *s, void *object)
 {
        struct track *p;
@@ -1373,6 +1396,10 @@ static noinline int free_debug_processing(
        int cnt = 0;
        unsigned long flags, flags2;
        int ret = 0;
+       depot_stack_handle_t handle = 0;
+
+       if (s->flags & SLAB_STORE_USER)
+               handle = set_track_prepare();
 
        spin_lock_irqsave(&n->list_lock, flags);
        slab_lock(slab, &flags2);
@@ -1391,7 +1418,7 @@ next_object:
        }
 
        if (s->flags & SLAB_STORE_USER)
-               set_track(s, object, TRACK_FREE, addr);
+               set_track_update(s, object, TRACK_FREE, addr, handle);
        trace(s, slab, object, 0);
        /* Freepointer not overwritten by init_object(), SLAB_POISON moved it */
        init_object(s, object, SLUB_RED_INACTIVE);
@@ -2936,6 +2963,7 @@ redo:
 
        if (!freelist) {
                c->slab = NULL;
+               c->tid = next_tid(c->tid);
                local_unlock_irqrestore(&s->cpu_slab->lock, flags);
                stat(s, DEACTIVATE_BYPASS);
                goto new_slab;
@@ -2968,6 +2996,7 @@ deactivate_slab:
        freelist = c->freelist;
        c->slab = NULL;
        c->freelist = NULL;
+       c->tid = next_tid(c->tid);
        local_unlock_irqrestore(&s->cpu_slab->lock, flags);
        deactivate_slab(s, slab, freelist);
 
index baeacc7..4e1da70 100644 (file)
@@ -161,29 +161,27 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n,
 static inline void check_heap_object(const void *ptr, unsigned long n,
                                     bool to_user)
 {
+       uintptr_t addr = (uintptr_t)ptr;
+       unsigned long offset;
        struct folio *folio;
 
        if (is_kmap_addr(ptr)) {
-               unsigned long page_end = (unsigned long)ptr | (PAGE_SIZE - 1);
-
-               if ((unsigned long)ptr + n - 1 > page_end)
-                       usercopy_abort("kmap", NULL, to_user,
-                                       offset_in_page(ptr), n);
+               offset = offset_in_page(ptr);
+               if (n > PAGE_SIZE - offset)
+                       usercopy_abort("kmap", NULL, to_user, offset, n);
                return;
        }
 
        if (is_vmalloc_addr(ptr)) {
-               struct vm_struct *area = find_vm_area(ptr);
-               unsigned long offset;
+               struct vmap_area *area = find_vmap_area(addr);
 
-               if (!area) {
+               if (!area)
                        usercopy_abort("vmalloc", "no area", to_user, 0, n);
-                       return;
-               }
 
-               offset = ptr - area->addr;
-               if (offset + n > get_vm_area_size(area))
+               if (n > area->va_end - addr) {
+                       offset = addr - area->va_start;
                        usercopy_abort("vmalloc", NULL, to_user, offset, n);
+               }
                return;
        }
 
@@ -196,8 +194,8 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
                /* Check slab allocator for flags and size. */
                __check_heap_object(ptr, n, folio_slab(folio), to_user);
        } else if (folio_test_large(folio)) {
-               unsigned long offset = ptr - folio_address(folio);
-               if (offset + n > folio_size(folio))
+               offset = ptr - folio_address(folio);
+               if (n > folio_size(folio) - offset)
                        usercopy_abort("page alloc", NULL, to_user, offset, n);
        }
 }
index 07db424..effd1ff 100644 (file)
@@ -1798,7 +1798,7 @@ static void free_unmap_vmap_area(struct vmap_area *va)
        free_vmap_area_noflush(va);
 }
 
-static struct vmap_area *find_vmap_area(unsigned long addr)
+struct vmap_area *find_vmap_area(unsigned long addr)
 {
        struct vmap_area *va;
 
index 95393bb..4c7030e 100644 (file)
@@ -1661,9 +1661,12 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
                        int flags)
 {
        struct sock *sk = sock->sk;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *last;
+       struct sk_buff_head *sk_queue;
        int copied;
        int err = 0;
+       int off = 0;
+       long timeo;
 
        lock_sock(sk);
        /*
@@ -1675,10 +1678,29 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
                goto out;
        }
 
-       /* Now we can treat all alike */
-       skb = skb_recv_datagram(sk, flags, &err);
-       if (skb == NULL)
-               goto out;
+       /*  We need support for non-blocking reads. */
+       sk_queue = &sk->sk_receive_queue;
+       skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off, &err, &last);
+       /* If no packet is available, release_sock(sk) and try again. */
+       if (!skb) {
+               if (err != -EAGAIN)
+                       goto out;
+               release_sock(sk);
+               timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+               while (timeo && !__skb_wait_for_more_packets(sk, sk_queue, &err,
+                                                            &timeo, last)) {
+                       skb = __skb_try_recv_datagram(sk, sk_queue, flags, &off,
+                                                     &err, &last);
+                       if (skb)
+                               break;
+
+                       if (err != -EAGAIN)
+                               goto done;
+               }
+               if (!skb)
+                       goto done;
+               lock_sock(sk);
+       }
 
        if (!sk_to_ax25(sk)->pidincl)
                skb_pull(skb, 1);               /* Remove PID */
@@ -1725,6 +1747,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
 out:
        release_sock(sk);
 
+done:
        return err;
 }
 
index 08ce317..8e6f229 100644 (file)
@@ -397,16 +397,18 @@ static void list_netdevice(struct net_device *dev)
 /* Device list removal
  * caller must respect a RCU grace period before freeing/reusing dev
  */
-static void unlist_netdevice(struct net_device *dev)
+static void unlist_netdevice(struct net_device *dev, bool lock)
 {
        ASSERT_RTNL();
 
        /* Unlink dev from the device chain */
-       write_lock(&dev_base_lock);
+       if (lock)
+               write_lock(&dev_base_lock);
        list_del_rcu(&dev->dev_list);
        netdev_name_node_del(dev->name_node);
        hlist_del_rcu(&dev->index_hlist);
-       write_unlock(&dev_base_lock);
+       if (lock)
+               write_unlock(&dev_base_lock);
 
        dev_base_seq_inc(dev_net(dev));
 }
@@ -10043,11 +10045,11 @@ int register_netdevice(struct net_device *dev)
                goto err_uninit;
 
        ret = netdev_register_kobject(dev);
-       if (ret) {
-               dev->reg_state = NETREG_UNREGISTERED;
+       write_lock(&dev_base_lock);
+       dev->reg_state = ret ? NETREG_UNREGISTERED : NETREG_REGISTERED;
+       write_unlock(&dev_base_lock);
+       if (ret)
                goto err_uninit;
-       }
-       dev->reg_state = NETREG_REGISTERED;
 
        __netdev_update_features(dev);
 
@@ -10329,7 +10331,9 @@ void netdev_run_todo(void)
                        continue;
                }
 
+               write_lock(&dev_base_lock);
                dev->reg_state = NETREG_UNREGISTERED;
+               write_unlock(&dev_base_lock);
                linkwatch_forget_dev(dev);
        }
 
@@ -10810,9 +10814,10 @@ void unregister_netdevice_many(struct list_head *head)
 
        list_for_each_entry(dev, head, unreg_list) {
                /* And unlink it from device chain. */
-               unlist_netdevice(dev);
-
+               write_lock(&dev_base_lock);
+               unlist_netdevice(dev, false);
                dev->reg_state = NETREG_UNREGISTERING;
+               write_unlock(&dev_base_lock);
        }
        flush_all_backlogs();
 
@@ -10959,7 +10964,7 @@ int __dev_change_net_namespace(struct net_device *dev, struct net *net,
        dev_close(dev);
 
        /* And unlink it from device chain */
-       unlist_netdevice(dev);
+       unlist_netdevice(dev, true);
 
        synchronize_net();
 
index 5af58eb..5d16d66 100644 (file)
@@ -6516,10 +6516,21 @@ __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
                                           ifindex, proto, netns_id, flags);
 
        if (sk) {
-               sk = sk_to_full_sk(sk);
-               if (!sk_fullsock(sk)) {
+               struct sock *sk2 = sk_to_full_sk(sk);
+
+               /* sk_to_full_sk() may return (sk)->rsk_listener, so make sure the original sk
+                * sock refcnt is decremented to prevent a request_sock leak.
+                */
+               if (!sk_fullsock(sk2))
+                       sk2 = NULL;
+               if (sk2 != sk) {
                        sock_gen_put(sk);
-                       return NULL;
+                       /* Ensure there is no need to bump sk2 refcnt */
+                       if (unlikely(sk2 && !sock_flag(sk2, SOCK_RCU_FREE))) {
+                               WARN_ONCE(1, "Found non-RCU, unreferenced socket!");
+                               return NULL;
+                       }
+                       sk = sk2;
                }
        }
 
@@ -6553,10 +6564,21 @@ bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
                                         flags);
 
        if (sk) {
-               sk = sk_to_full_sk(sk);
-               if (!sk_fullsock(sk)) {
+               struct sock *sk2 = sk_to_full_sk(sk);
+
+               /* sk_to_full_sk() may return (sk)->rsk_listener, so make sure the original sk
+                * sock refcnt is decremented to prevent a request_sock leak.
+                */
+               if (!sk_fullsock(sk2))
+                       sk2 = NULL;
+               if (sk2 != sk) {
                        sock_gen_put(sk);
-                       return NULL;
+                       /* Ensure there is no need to bump sk2 refcnt */
+                       if (unlikely(sk2 && !sock_flag(sk2, SOCK_RCU_FREE))) {
+                               WARN_ONCE(1, "Found non-RCU, unreferenced socket!");
+                               return NULL;
+                       }
+                       sk = sk2;
                }
        }
 
index e319e24..a364256 100644 (file)
@@ -33,6 +33,7 @@ static const char fmt_dec[] = "%d\n";
 static const char fmt_ulong[] = "%lu\n";
 static const char fmt_u64[] = "%llu\n";
 
+/* Caller holds RTNL or dev_base_lock */
 static inline int dev_isalive(const struct net_device *dev)
 {
        return dev->reg_state <= NETREG_REGISTERED;
index 22b983a..b0fcd02 100644 (file)
@@ -699,6 +699,11 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
 
        write_lock_bh(&sk->sk_callback_lock);
 
+       if (sk_is_inet(sk) && inet_csk_has_ulp(sk)) {
+               psock = ERR_PTR(-EINVAL);
+               goto out;
+       }
+
        if (sk->sk_user_data) {
                psock = ERR_PTR(-EBUSY);
                goto out;
index 2e78458..eb8e128 100644 (file)
@@ -1120,12 +1120,6 @@ static int __init dccp_init(void)
                                  SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL);
        if (!dccp_hashinfo.bind_bucket_cachep)
                goto out_free_hashinfo2;
-       dccp_hashinfo.bind2_bucket_cachep =
-               kmem_cache_create("dccp_bind2_bucket",
-                                 sizeof(struct inet_bind2_bucket), 0,
-                                 SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL);
-       if (!dccp_hashinfo.bind2_bucket_cachep)
-               goto out_free_bind_bucket_cachep;
 
        /*
         * Size and allocate the main established and bind bucket
@@ -1156,7 +1150,7 @@ static int __init dccp_init(void)
 
        if (!dccp_hashinfo.ehash) {
                DCCP_CRIT("Failed to allocate DCCP established hash table");
-               goto out_free_bind2_bucket_cachep;
+               goto out_free_bind_bucket_cachep;
        }
 
        for (i = 0; i <= dccp_hashinfo.ehash_mask; i++)
@@ -1182,23 +1176,14 @@ static int __init dccp_init(void)
                goto out_free_dccp_locks;
        }
 
-       dccp_hashinfo.bhash2 = (struct inet_bind2_hashbucket *)
-               __get_free_pages(GFP_ATOMIC | __GFP_NOWARN, bhash_order);
-
-       if (!dccp_hashinfo.bhash2) {
-               DCCP_CRIT("Failed to allocate DCCP bind2 hash table");
-               goto out_free_dccp_bhash;
-       }
-
        for (i = 0; i < dccp_hashinfo.bhash_size; i++) {
                spin_lock_init(&dccp_hashinfo.bhash[i].lock);
                INIT_HLIST_HEAD(&dccp_hashinfo.bhash[i].chain);
-               INIT_HLIST_HEAD(&dccp_hashinfo.bhash2[i].chain);
        }
 
        rc = dccp_mib_init();
        if (rc)
-               goto out_free_dccp_bhash2;
+               goto out_free_dccp_bhash;
 
        rc = dccp_ackvec_init();
        if (rc)
@@ -1222,38 +1207,30 @@ out_ackvec_exit:
        dccp_ackvec_exit();
 out_free_dccp_mib:
        dccp_mib_exit();
-out_free_dccp_bhash2:
-       free_pages((unsigned long)dccp_hashinfo.bhash2, bhash_order);
 out_free_dccp_bhash:
        free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
 out_free_dccp_locks:
        inet_ehash_locks_free(&dccp_hashinfo);
 out_free_dccp_ehash:
        free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order);
-out_free_bind2_bucket_cachep:
-       kmem_cache_destroy(dccp_hashinfo.bind2_bucket_cachep);
 out_free_bind_bucket_cachep:
        kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
 out_free_hashinfo2:
        inet_hashinfo2_free_mod(&dccp_hashinfo);
 out_fail:
        dccp_hashinfo.bhash = NULL;
-       dccp_hashinfo.bhash2 = NULL;
        dccp_hashinfo.ehash = NULL;
        dccp_hashinfo.bind_bucket_cachep = NULL;
-       dccp_hashinfo.bind2_bucket_cachep = NULL;
        return rc;
 }
 
 static void __exit dccp_fini(void)
 {
-       int bhash_order = get_order(dccp_hashinfo.bhash_size *
-                                   sizeof(struct inet_bind_hashbucket));
-
        ccid_cleanup_builtins();
        dccp_mib_exit();
-       free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
-       free_pages((unsigned long)dccp_hashinfo.bhash2, bhash_order);
+       free_pages((unsigned long)dccp_hashinfo.bhash,
+                  get_order(dccp_hashinfo.bhash_size *
+                            sizeof(struct inet_bind_hashbucket)));
        free_pages((unsigned long)dccp_hashinfo.ehash,
                   get_order((dccp_hashinfo.ehash_mask + 1) *
                             sizeof(struct inet_ehash_bucket)));
index 7e6b37a..1c94bb8 100644 (file)
@@ -36,7 +36,7 @@ static int fallback_set_params(struct eeprom_req_info *request,
        if (request->page)
                offset = request->page * ETH_MODULE_EEPROM_PAGE_LEN + offset;
 
-       if (modinfo->type == ETH_MODULE_SFF_8079 &&
+       if (modinfo->type == ETH_MODULE_SFF_8472 &&
            request->i2c_address == 0x51)
                offset += ETH_MODULE_EEPROM_PAGE_LEN * 2;
 
index c0b7e6c..53f5f95 100644 (file)
@@ -117,32 +117,6 @@ bool inet_rcv_saddr_any(const struct sock *sk)
        return !sk->sk_rcv_saddr;
 }
 
-static bool use_bhash2_on_bind(const struct sock *sk)
-{
-#if IS_ENABLED(CONFIG_IPV6)
-       int addr_type;
-
-       if (sk->sk_family == AF_INET6) {
-               addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
-               return addr_type != IPV6_ADDR_ANY &&
-                       addr_type != IPV6_ADDR_MAPPED;
-       }
-#endif
-       return sk->sk_rcv_saddr != htonl(INADDR_ANY);
-}
-
-static u32 get_bhash2_nulladdr_hash(const struct sock *sk, struct net *net,
-                                   int port)
-{
-#if IS_ENABLED(CONFIG_IPV6)
-       struct in6_addr nulladdr = {};
-
-       if (sk->sk_family == AF_INET6)
-               return ipv6_portaddr_hash(net, &nulladdr, port);
-#endif
-       return ipv4_portaddr_hash(net, 0, port);
-}
-
 void inet_get_local_port_range(struct net *net, int *low, int *high)
 {
        unsigned int seq;
@@ -156,71 +130,16 @@ void inet_get_local_port_range(struct net *net, int *low, int *high)
 }
 EXPORT_SYMBOL(inet_get_local_port_range);
 
-static bool bind_conflict_exist(const struct sock *sk, struct sock *sk2,
-                               kuid_t sk_uid, bool relax,
-                               bool reuseport_cb_ok, bool reuseport_ok)
-{
-       int bound_dev_if2;
-
-       if (sk == sk2)
-               return false;
-
-       bound_dev_if2 = READ_ONCE(sk2->sk_bound_dev_if);
-
-       if (!sk->sk_bound_dev_if || !bound_dev_if2 ||
-           sk->sk_bound_dev_if == bound_dev_if2) {
-               if (sk->sk_reuse && sk2->sk_reuse &&
-                   sk2->sk_state != TCP_LISTEN) {
-                       if (!relax || (!reuseport_ok && sk->sk_reuseport &&
-                                      sk2->sk_reuseport && reuseport_cb_ok &&
-                                      (sk2->sk_state == TCP_TIME_WAIT ||
-                                       uid_eq(sk_uid, sock_i_uid(sk2)))))
-                               return true;
-               } else if (!reuseport_ok || !sk->sk_reuseport ||
-                          !sk2->sk_reuseport || !reuseport_cb_ok ||
-                          (sk2->sk_state != TCP_TIME_WAIT &&
-                           !uid_eq(sk_uid, sock_i_uid(sk2)))) {
-                       return true;
-               }
-       }
-       return false;
-}
-
-static bool check_bhash2_conflict(const struct sock *sk,
-                                 struct inet_bind2_bucket *tb2, kuid_t sk_uid,
-                                 bool relax, bool reuseport_cb_ok,
-                                 bool reuseport_ok)
-{
-       struct sock *sk2;
-
-       sk_for_each_bound_bhash2(sk2, &tb2->owners) {
-               if (sk->sk_family == AF_INET && ipv6_only_sock(sk2))
-                       continue;
-
-               if (bind_conflict_exist(sk, sk2, sk_uid, relax,
-                                       reuseport_cb_ok, reuseport_ok))
-                       return true;
-       }
-       return false;
-}
-
-/* This should be called only when the corresponding inet_bind_bucket spinlock
- * is held
- */
-static int inet_csk_bind_conflict(const struct sock *sk, int port,
-                                 struct inet_bind_bucket *tb,
-                                 struct inet_bind2_bucket *tb2, /* may be null */
+static int inet_csk_bind_conflict(const struct sock *sk,
+                                 const struct inet_bind_bucket *tb,
                                  bool relax, bool reuseport_ok)
 {
-       struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
-       kuid_t uid = sock_i_uid((struct sock *)sk);
-       struct sock_reuseport *reuseport_cb;
-       struct inet_bind2_hashbucket *head2;
-       bool reuseport_cb_ok;
        struct sock *sk2;
-       struct net *net;
-       int l3mdev;
-       u32 hash;
+       bool reuseport_cb_ok;
+       bool reuse = sk->sk_reuse;
+       bool reuseport = !!sk->sk_reuseport;
+       struct sock_reuseport *reuseport_cb;
+       kuid_t uid = sock_i_uid((struct sock *)sk);
 
        rcu_read_lock();
        reuseport_cb = rcu_dereference(sk->sk_reuseport_cb);
@@ -231,42 +150,40 @@ static int inet_csk_bind_conflict(const struct sock *sk, int port,
        /*
         * Unlike other sk lookup places we do not check
         * for sk_net here, since _all_ the socks listed
-        * in tb->owners and tb2->owners list belong
-        * to the same net
+        * in tb->owners list belong to the same net - the
+        * one this bucket belongs to.
         */
 
-       if (!use_bhash2_on_bind(sk)) {
-               sk_for_each_bound(sk2, &tb->owners)
-                       if (bind_conflict_exist(sk, sk2, uid, relax,
-                                               reuseport_cb_ok, reuseport_ok) &&
-                           inet_rcv_saddr_equal(sk, sk2, true))
-                               return true;
+       sk_for_each_bound(sk2, &tb->owners) {
+               int bound_dev_if2;
 
-               return false;
+               if (sk == sk2)
+                       continue;
+               bound_dev_if2 = READ_ONCE(sk2->sk_bound_dev_if);
+               if ((!sk->sk_bound_dev_if ||
+                    !bound_dev_if2 ||
+                    sk->sk_bound_dev_if == bound_dev_if2)) {
+                       if (reuse && sk2->sk_reuse &&
+                           sk2->sk_state != TCP_LISTEN) {
+                               if ((!relax ||
+                                    (!reuseport_ok &&
+                                     reuseport && sk2->sk_reuseport &&
+                                     reuseport_cb_ok &&
+                                     (sk2->sk_state == TCP_TIME_WAIT ||
+                                      uid_eq(uid, sock_i_uid(sk2))))) &&
+                                   inet_rcv_saddr_equal(sk, sk2, true))
+                                       break;
+                       } else if (!reuseport_ok ||
+                                  !reuseport || !sk2->sk_reuseport ||
+                                  !reuseport_cb_ok ||
+                                  (sk2->sk_state != TCP_TIME_WAIT &&
+                                   !uid_eq(uid, sock_i_uid(sk2)))) {
+                               if (inet_rcv_saddr_equal(sk, sk2, true))
+                                       break;
+                       }
+               }
        }
-
-       if (tb2 && check_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok,
-                                        reuseport_ok))
-               return true;
-
-       net = sock_net(sk);
-
-       /* check there's no conflict with an existing IPV6_ADDR_ANY (if ipv6) or
-        * INADDR_ANY (if ipv4) socket.
-        */
-       hash = get_bhash2_nulladdr_hash(sk, net, port);
-       head2 = &hinfo->bhash2[hash & (hinfo->bhash_size - 1)];
-
-       l3mdev = inet_sk_bound_l3mdev(sk);
-       inet_bind_bucket_for_each(tb2, &head2->chain)
-               if (check_bind2_bucket_match_nulladdr(tb2, net, port, l3mdev, sk))
-                       break;
-
-       if (tb2 && check_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok,
-                                        reuseport_ok))
-               return true;
-
-       return false;
+       return sk2 != NULL;
 }
 
 /*
@@ -274,20 +191,16 @@ static int inet_csk_bind_conflict(const struct sock *sk, int port,
  * inet_bind_hashbucket lock held.
  */
 static struct inet_bind_hashbucket *
-inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret,
-                       struct inet_bind2_bucket **tb2_ret,
-                       struct inet_bind2_hashbucket **head2_ret, int *port_ret)
+inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *port_ret)
 {
        struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
-       struct inet_bind2_hashbucket *head2;
+       int port = 0;
        struct inet_bind_hashbucket *head;
        struct net *net = sock_net(sk);
+       bool relax = false;
        int i, low, high, attempt_half;
-       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
        u32 remaining, offset;
-       bool relax = false;
-       int port = 0;
        int l3mdev;
 
        l3mdev = inet_sk_bound_l3mdev(sk);
@@ -326,12 +239,10 @@ other_parity_scan:
                head = &hinfo->bhash[inet_bhashfn(net, port,
                                                  hinfo->bhash_size)];
                spin_lock_bh(&head->lock);
-               tb2 = inet_bind2_bucket_find(hinfo, net, port, l3mdev, sk,
-                                            &head2);
                inet_bind_bucket_for_each(tb, &head->chain)
-                       if (check_bind_bucket_match(tb, net, port, l3mdev)) {
-                               if (!inet_csk_bind_conflict(sk, port, tb, tb2,
-                                                           relax, false))
+                       if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
+                           tb->port == port) {
+                               if (!inet_csk_bind_conflict(sk, tb, relax, false))
                                        goto success;
                                goto next_port;
                        }
@@ -361,8 +272,6 @@ next_port:
 success:
        *port_ret = port;
        *tb_ret = tb;
-       *tb2_ret = tb2;
-       *head2_ret = head2;
        return head;
 }
 
@@ -458,81 +367,54 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
 {
        bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
        struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
-       bool bhash_created = false, bhash2_created = false;
-       struct inet_bind2_bucket *tb2 = NULL;
-       struct inet_bind2_hashbucket *head2;
-       struct inet_bind_bucket *tb = NULL;
+       int ret = 1, port = snum;
        struct inet_bind_hashbucket *head;
        struct net *net = sock_net(sk);
-       int ret = 1, port = snum;
-       bool found_port = false;
+       struct inet_bind_bucket *tb = NULL;
        int l3mdev;
 
        l3mdev = inet_sk_bound_l3mdev(sk);
 
        if (!port) {
-               head = inet_csk_find_open_port(sk, &tb, &tb2, &head2, &port);
+               head = inet_csk_find_open_port(sk, &tb, &port);
                if (!head)
                        return ret;
-               if (tb && tb2)
-                       goto success;
-               found_port = true;
-       } else {
-               head = &hinfo->bhash[inet_bhashfn(net, port,
-                                                 hinfo->bhash_size)];
-               spin_lock_bh(&head->lock);
-               inet_bind_bucket_for_each(tb, &head->chain)
-                       if (check_bind_bucket_match(tb, net, port, l3mdev))
-                               break;
-
-               tb2 = inet_bind2_bucket_find(hinfo, net, port, l3mdev, sk,
-                                            &head2);
-       }
-
-       if (!tb) {
-               tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, net,
-                                            head, port, l3mdev);
                if (!tb)
-                       goto fail_unlock;
-               bhash_created = true;
-       }
-
-       if (!tb2) {
-               tb2 = inet_bind2_bucket_create(hinfo->bind2_bucket_cachep,
-                                              net, head2, port, l3mdev, sk);
-               if (!tb2)
-                       goto fail_unlock;
-               bhash2_created = true;
+                       goto tb_not_found;
+               goto success;
        }
-
-       /* If we had to find an open port, we already checked for conflicts */
-       if (!found_port && !hlist_empty(&tb->owners)) {
+       head = &hinfo->bhash[inet_bhashfn(net, port,
+                                         hinfo->bhash_size)];
+       spin_lock_bh(&head->lock);
+       inet_bind_bucket_for_each(tb, &head->chain)
+               if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
+                   tb->port == port)
+                       goto tb_found;
+tb_not_found:
+       tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
+                                    net, head, port, l3mdev);
+       if (!tb)
+               goto fail_unlock;
+tb_found:
+       if (!hlist_empty(&tb->owners)) {
                if (sk->sk_reuse == SK_FORCE_REUSE)
                        goto success;
 
                if ((tb->fastreuse > 0 && reuse) ||
                    sk_reuseport_match(tb, sk))
                        goto success;
-               if (inet_csk_bind_conflict(sk, port, tb, tb2, true, true))
+               if (inet_csk_bind_conflict(sk, tb, true, true))
                        goto fail_unlock;
        }
 success:
        inet_csk_update_fastreuse(tb, sk);
 
        if (!inet_csk(sk)->icsk_bind_hash)
-               inet_bind_hash(sk, tb, tb2, port);
+               inet_bind_hash(sk, tb, port);
        WARN_ON(inet_csk(sk)->icsk_bind_hash != tb);
-       WARN_ON(inet_csk(sk)->icsk_bind2_hash != tb2);
        ret = 0;
 
 fail_unlock:
-       if (ret) {
-               if (bhash_created)
-                       inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
-               if (bhash2_created)
-                       inet_bind2_bucket_destroy(hinfo->bind2_bucket_cachep,
-                                                 tb2);
-       }
        spin_unlock_bh(&head->lock);
        return ret;
 }
@@ -1079,7 +961,6 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
 
                inet_sk_set_state(newsk, TCP_SYN_RECV);
                newicsk->icsk_bind_hash = NULL;
-               newicsk->icsk_bind2_hash = NULL;
 
                inet_sk(newsk)->inet_dport = inet_rsk(req)->ir_rmt_port;
                inet_sk(newsk)->inet_num = inet_rsk(req)->ir_num;
index 545f91b..b9d995b 100644 (file)
@@ -81,41 +81,6 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
        return tb;
 }
 
-struct inet_bind2_bucket *inet_bind2_bucket_create(struct kmem_cache *cachep,
-                                                  struct net *net,
-                                                  struct inet_bind2_hashbucket *head,
-                                                  const unsigned short port,
-                                                  int l3mdev,
-                                                  const struct sock *sk)
-{
-       struct inet_bind2_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
-
-       if (tb) {
-               write_pnet(&tb->ib_net, net);
-               tb->l3mdev    = l3mdev;
-               tb->port      = port;
-#if IS_ENABLED(CONFIG_IPV6)
-               if (sk->sk_family == AF_INET6)
-                       tb->v6_rcv_saddr = sk->sk_v6_rcv_saddr;
-               else
-#endif
-                       tb->rcv_saddr = sk->sk_rcv_saddr;
-               INIT_HLIST_HEAD(&tb->owners);
-               hlist_add_head(&tb->node, &head->chain);
-       }
-       return tb;
-}
-
-static bool bind2_bucket_addr_match(struct inet_bind2_bucket *tb2, struct sock *sk)
-{
-#if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == AF_INET6)
-               return ipv6_addr_equal(&tb2->v6_rcv_saddr,
-                                      &sk->sk_v6_rcv_saddr);
-#endif
-       return tb2->rcv_saddr == sk->sk_rcv_saddr;
-}
-
 /*
  * Caller must hold hashbucket lock for this tb with local BH disabled
  */
@@ -127,25 +92,12 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket
        }
 }
 
-/* Caller must hold the lock for the corresponding hashbucket in the bhash table
- * with local BH disabled
- */
-void inet_bind2_bucket_destroy(struct kmem_cache *cachep, struct inet_bind2_bucket *tb)
-{
-       if (hlist_empty(&tb->owners)) {
-               __hlist_del(&tb->node);
-               kmem_cache_free(cachep, tb);
-       }
-}
-
 void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
-                   struct inet_bind2_bucket *tb2, const unsigned short snum)
+                   const unsigned short snum)
 {
        inet_sk(sk)->inet_num = snum;
        sk_add_bind_node(sk, &tb->owners);
        inet_csk(sk)->icsk_bind_hash = tb;
-       sk_add_bind2_node(sk, &tb2->owners);
-       inet_csk(sk)->icsk_bind2_hash = tb2;
 }
 
 /*
@@ -157,7 +109,6 @@ static void __inet_put_port(struct sock *sk)
        const int bhash = inet_bhashfn(sock_net(sk), inet_sk(sk)->inet_num,
                        hashinfo->bhash_size);
        struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
-       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
 
        spin_lock(&head->lock);
@@ -166,13 +117,6 @@ static void __inet_put_port(struct sock *sk)
        inet_csk(sk)->icsk_bind_hash = NULL;
        inet_sk(sk)->inet_num = 0;
        inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
-
-       if (inet_csk(sk)->icsk_bind2_hash) {
-               tb2 = inet_csk(sk)->icsk_bind2_hash;
-               __sk_del_bind2_node(sk);
-               inet_csk(sk)->icsk_bind2_hash = NULL;
-               inet_bind2_bucket_destroy(hashinfo->bind2_bucket_cachep, tb2);
-       }
        spin_unlock(&head->lock);
 }
 
@@ -189,19 +133,14 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
        struct inet_hashinfo *table = sk->sk_prot->h.hashinfo;
        unsigned short port = inet_sk(child)->inet_num;
        const int bhash = inet_bhashfn(sock_net(sk), port,
-                                      table->bhash_size);
+                       table->bhash_size);
        struct inet_bind_hashbucket *head = &table->bhash[bhash];
-       struct inet_bind2_hashbucket *head_bhash2;
-       bool created_inet_bind_bucket = false;
-       struct net *net = sock_net(sk);
-       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
        int l3mdev;
 
        spin_lock(&head->lock);
        tb = inet_csk(sk)->icsk_bind_hash;
-       tb2 = inet_csk(sk)->icsk_bind2_hash;
-       if (unlikely(!tb || !tb2)) {
+       if (unlikely(!tb)) {
                spin_unlock(&head->lock);
                return -ENOENT;
        }
@@ -214,45 +153,25 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
                 * as that of the child socket. We have to look up or
                 * create a new bind bucket for the child here. */
                inet_bind_bucket_for_each(tb, &head->chain) {
-                       if (check_bind_bucket_match(tb, net, port, l3mdev))
+                       if (net_eq(ib_net(tb), sock_net(sk)) &&
+                           tb->l3mdev == l3mdev && tb->port == port)
                                break;
                }
                if (!tb) {
                        tb = inet_bind_bucket_create(table->bind_bucket_cachep,
-                                                    net, head, port, l3mdev);
+                                                    sock_net(sk), head, port,
+                                                    l3mdev);
                        if (!tb) {
                                spin_unlock(&head->lock);
                                return -ENOMEM;
                        }
-                       created_inet_bind_bucket = true;
                }
                inet_csk_update_fastreuse(tb, child);
-
-               goto bhash2_find;
-       } else if (!bind2_bucket_addr_match(tb2, child)) {
-               l3mdev = inet_sk_bound_l3mdev(sk);
-
-bhash2_find:
-               tb2 = inet_bind2_bucket_find(table, net, port, l3mdev, child,
-                                            &head_bhash2);
-               if (!tb2) {
-                       tb2 = inet_bind2_bucket_create(table->bind2_bucket_cachep,
-                                                      net, head_bhash2, port,
-                                                      l3mdev, child);
-                       if (!tb2)
-                               goto error;
-               }
        }
-       inet_bind_hash(child, tb, tb2, port);
+       inet_bind_hash(child, tb, port);
        spin_unlock(&head->lock);
 
        return 0;
-
-error:
-       if (created_inet_bind_bucket)
-               inet_bind_bucket_destroy(table->bind_bucket_cachep, tb);
-       spin_unlock(&head->lock);
-       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(__inet_inherit_port);
 
@@ -756,76 +675,6 @@ void inet_unhash(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(inet_unhash);
 
-static bool check_bind2_bucket_match(struct inet_bind2_bucket *tb,
-                                    struct net *net, unsigned short port,
-                                    int l3mdev, struct sock *sk)
-{
-#if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == AF_INET6)
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev &&
-                       ipv6_addr_equal(&tb->v6_rcv_saddr, &sk->sk_v6_rcv_saddr);
-       else
-#endif
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev && tb->rcv_saddr == sk->sk_rcv_saddr;
-}
-
-bool check_bind2_bucket_match_nulladdr(struct inet_bind2_bucket *tb,
-                                      struct net *net, const unsigned short port,
-                                      int l3mdev, const struct sock *sk)
-{
-#if IS_ENABLED(CONFIG_IPV6)
-       struct in6_addr nulladdr = {};
-
-       if (sk->sk_family == AF_INET6)
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev &&
-                       ipv6_addr_equal(&tb->v6_rcv_saddr, &nulladdr);
-       else
-#endif
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev && tb->rcv_saddr == 0;
-}
-
-static struct inet_bind2_hashbucket *
-inet_bhashfn_portaddr(struct inet_hashinfo *hinfo, const struct sock *sk,
-                     const struct net *net, unsigned short port)
-{
-       u32 hash;
-
-#if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == AF_INET6)
-               hash = ipv6_portaddr_hash(net, &sk->sk_v6_rcv_saddr, port);
-       else
-#endif
-               hash = ipv4_portaddr_hash(net, sk->sk_rcv_saddr, port);
-       return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)];
-}
-
-/* This should only be called when the spinlock for the socket's corresponding
- * bind_hashbucket is held
- */
-struct inet_bind2_bucket *
-inet_bind2_bucket_find(struct inet_hashinfo *hinfo, struct net *net,
-                      const unsigned short port, int l3mdev, struct sock *sk,
-                      struct inet_bind2_hashbucket **head)
-{
-       struct inet_bind2_bucket *bhash2 = NULL;
-       struct inet_bind2_hashbucket *h;
-
-       h = inet_bhashfn_portaddr(hinfo, sk, net, port);
-       inet_bind_bucket_for_each(bhash2, &h->chain) {
-               if (check_bind2_bucket_match(bhash2, net, port, l3mdev, sk))
-                       break;
-       }
-
-       if (head)
-               *head = h;
-
-       return bhash2;
-}
-
 /* RFC 6056 3.3.4.  Algorithm 4: Double-Hash Port Selection Algorithm
  * Note that we use 32bit integers (vs RFC 'short integers')
  * because 2^16 is not a multiple of num_ephemeral and this
@@ -846,13 +695,10 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
 {
        struct inet_hashinfo *hinfo = death_row->hashinfo;
        struct inet_timewait_sock *tw = NULL;
-       struct inet_bind2_hashbucket *head2;
        struct inet_bind_hashbucket *head;
        int port = inet_sk(sk)->inet_num;
        struct net *net = sock_net(sk);
-       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
-       bool tb_created = false;
        u32 remaining, offset;
        int ret, i, low, high;
        int l3mdev;
@@ -909,7 +755,8 @@ other_parity_scan:
                 * the established check is already unique enough.
                 */
                inet_bind_bucket_for_each(tb, &head->chain) {
-                       if (check_bind_bucket_match(tb, net, port, l3mdev)) {
+                       if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
+                           tb->port == port) {
                                if (tb->fastreuse >= 0 ||
                                    tb->fastreuseport >= 0)
                                        goto next_port;
@@ -927,7 +774,6 @@ other_parity_scan:
                        spin_unlock_bh(&head->lock);
                        return -ENOMEM;
                }
-               tb_created = true;
                tb->fastreuse = -1;
                tb->fastreuseport = -1;
                goto ok;
@@ -943,17 +789,6 @@ next_port:
        return -EADDRNOTAVAIL;
 
 ok:
-       /* Find the corresponding tb2 bucket since we need to
-        * add the socket to the bhash2 table as well
-        */
-       tb2 = inet_bind2_bucket_find(hinfo, net, port, l3mdev, sk, &head2);
-       if (!tb2) {
-               tb2 = inet_bind2_bucket_create(hinfo->bind2_bucket_cachep, net,
-                                              head2, port, l3mdev, sk);
-               if (!tb2)
-                       goto error;
-       }
-
        /* Here we want to add a little bit of randomness to the next source
         * port that will be chosen. We use a max() with a random here so that
         * on low contention the randomness is maximal and on high contention
@@ -963,7 +798,7 @@ ok:
        WRITE_ONCE(table_perturb[index], READ_ONCE(table_perturb[index]) + i + 2);
 
        /* Head lock still held and bh's disabled */
-       inet_bind_hash(sk, tb, tb2, port);
+       inet_bind_hash(sk, tb, port);
        if (sk_unhashed(sk)) {
                inet_sk(sk)->inet_sport = htons(port);
                inet_ehash_nolisten(sk, (struct sock *)tw, NULL);
@@ -975,12 +810,6 @@ ok:
                inet_twsk_deschedule_put(tw);
        local_bh_enable();
        return 0;
-
-error:
-       if (tb_created)
-               inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
-       spin_unlock_bh(&head->lock);
-       return -ENOMEM;
 }
 
 /*
index 3b9cd48..5c58e21 100644 (file)
@@ -524,7 +524,6 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
        int tunnel_hlen;
        int version;
        int nhoff;
-       int thoff;
 
        tun_info = skb_tunnel_info(skb);
        if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
@@ -558,10 +557,16 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
            (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
                truncate = true;
 
-       thoff = skb_transport_header(skb) - skb_mac_header(skb);
-       if (skb->protocol == htons(ETH_P_IPV6) &&
-           (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
-               truncate = true;
+       if (skb->protocol == htons(ETH_P_IPV6)) {
+               int thoff;
+
+               if (skb_transport_header_was_set(skb))
+                       thoff = skb_transport_header(skb) - skb_mac_header(skb);
+               else
+                       thoff = nhoff + sizeof(struct ipv6hdr);
+               if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
+                       truncate = true;
+       }
 
        if (version == 1) {
                erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
index 1a43ca7..3c6101d 100644 (file)
@@ -319,12 +319,16 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
                pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n",
                         sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port));
 
+               if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
+                       return 0;
+
                tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id;
                chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id);
 
-               if (!inet_addr_valid_or_nonlocal(net, inet_sk(sk),
-                                                addr->sin_addr.s_addr,
-                                                chk_addr_ret))
+               if (chk_addr_ret == RTN_MULTICAST ||
+                   chk_addr_ret == RTN_BROADCAST ||
+                   (chk_addr_ret != RTN_LOCAL &&
+                    !inet_can_nonlocal_bind(net, isk)))
                        return -EADDRNOTAVAIL;
 
 #if IS_ENABLED(CONFIG_IPV6)
index 9984d23..028513d 100644 (file)
@@ -4604,12 +4604,6 @@ void __init tcp_init(void)
                                  SLAB_HWCACHE_ALIGN | SLAB_PANIC |
                                  SLAB_ACCOUNT,
                                  NULL);
-       tcp_hashinfo.bind2_bucket_cachep =
-               kmem_cache_create("tcp_bind2_bucket",
-                                 sizeof(struct inet_bind2_bucket), 0,
-                                 SLAB_HWCACHE_ALIGN | SLAB_PANIC |
-                                 SLAB_ACCOUNT,
-                                 NULL);
 
        /* Size and allocate the main established and bind bucket
         * hash tables.
@@ -4632,9 +4626,8 @@ void __init tcp_init(void)
        if (inet_ehash_locks_alloc(&tcp_hashinfo))
                panic("TCP: failed to alloc ehash_locks");
        tcp_hashinfo.bhash =
-               alloc_large_system_hash("TCP bind bhash tables",
-                                       sizeof(struct inet_bind_hashbucket) +
-                                       sizeof(struct inet_bind2_hashbucket),
+               alloc_large_system_hash("TCP bind",
+                                       sizeof(struct inet_bind_hashbucket),
                                        tcp_hashinfo.ehash_mask + 1,
                                        17, /* one slot per 128 KB of memory */
                                        0,
@@ -4643,12 +4636,9 @@ void __init tcp_init(void)
                                        0,
                                        64 * 1024);
        tcp_hashinfo.bhash_size = 1U << tcp_hashinfo.bhash_size;
-       tcp_hashinfo.bhash2 =
-               (struct inet_bind2_hashbucket *)(tcp_hashinfo.bhash + tcp_hashinfo.bhash_size);
        for (i = 0; i < tcp_hashinfo.bhash_size; i++) {
                spin_lock_init(&tcp_hashinfo.bhash[i].lock);
                INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
-               INIT_HLIST_HEAD(&tcp_hashinfo.bhash2[i].chain);
        }
 
 
index be3947e..0d3f68b 100644 (file)
@@ -611,9 +611,6 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
                return 0;
        }
 
-       if (inet_csk_has_ulp(sk))
-               return -EINVAL;
-
        if (sk->sk_family == AF_INET6) {
                if (tcp_bpf_assert_proto_ops(psock->sk_proto))
                        return -EINVAL;
index 4e37f7c..a9051df 100644 (file)
@@ -939,7 +939,6 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        __be16 proto;
        __u32 mtu;
        int nhoff;
-       int thoff;
 
        if (!pskb_inet_may_pull(skb))
                goto tx_err;
@@ -960,10 +959,16 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
            (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
                truncate = true;
 
-       thoff = skb_transport_header(skb) - skb_mac_header(skb);
-       if (skb->protocol == htons(ETH_P_IPV6) &&
-           (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
-               truncate = true;
+       if (skb->protocol == htons(ETH_P_IPV6)) {
+               int thoff;
+
+               if (skb_transport_header_was_set(skb))
+                       thoff = skb_transport_header(skb) - skb_mac_header(skb);
+               else
+                       thoff = nhoff + sizeof(struct ipv6hdr);
+               if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
+                       truncate = true;
+       }
 
        if (skb_cow_head(skb, dev->needed_headroom ?: t->hlen))
                goto tx_err;
index 7873bd1..a8e2425 100644 (file)
 #include <net/netfilter/nf_tables_offload.h>
 #include <net/netfilter/nf_dup_netdev.h>
 
-static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev)
+#define NF_RECURSION_LIMIT     2
+
+static DEFINE_PER_CPU(u8, nf_dup_skb_recursion);
+
+static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev,
+                               enum nf_dev_hooks hook)
 {
-       if (skb_mac_header_was_set(skb))
+       if (__this_cpu_read(nf_dup_skb_recursion) > NF_RECURSION_LIMIT)
+               goto err;
+
+       if (hook == NF_NETDEV_INGRESS && skb_mac_header_was_set(skb)) {
+               if (skb_cow_head(skb, skb->mac_len))
+                       goto err;
+
                skb_push(skb, skb->mac_len);
+       }
 
        skb->dev = dev;
        skb_clear_tstamp(skb);
+       __this_cpu_inc(nf_dup_skb_recursion);
        dev_queue_xmit(skb);
+       __this_cpu_dec(nf_dup_skb_recursion);
+       return;
+err:
+       kfree_skb(skb);
 }
 
 void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif)
@@ -33,7 +50,7 @@ void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif)
                return;
        }
 
-       nf_do_netdev_egress(pkt->skb, dev);
+       nf_do_netdev_egress(pkt->skb, dev, nft_hook(pkt));
 }
 EXPORT_SYMBOL_GPL(nf_fwd_netdev_egress);
 
@@ -48,7 +65,7 @@ void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
 
        skb = skb_clone(pkt->skb, GFP_ATOMIC);
        if (skb)
-               nf_do_netdev_egress(skb, dev);
+               nf_do_netdev_egress(skb, dev, nft_hook(pkt));
 }
 EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);
 
index af15102..f466af4 100644 (file)
@@ -614,7 +614,7 @@ static void __net_exit cttimeout_net_exit(struct net *net)
 
        nf_ct_untimeout(net, NULL);
 
-       list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, head) {
+       list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, free_head) {
                list_del(&cur->free_head);
 
                if (refcount_dec_and_test(&cur->refcnt))
index ac48592..55d2d49 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
+#include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/static_key.h>
 #include <net/dst.h>
@@ -32,8 +33,6 @@
 #define NFT_META_SECS_PER_DAY          86400
 #define NFT_META_DAYS_PER_WEEK         7
 
-static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
-
 static u8 nft_meta_weekday(void)
 {
        time64_t secs = ktime_get_real_seconds();
@@ -271,13 +270,6 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
        return true;
 }
 
-static noinline u32 nft_prandom_u32(void)
-{
-       struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);
-
-       return prandom_u32_state(state);
-}
-
 #ifdef CONFIG_IP_ROUTE_CLASSID
 static noinline bool
 nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
@@ -389,7 +381,7 @@ void nft_meta_get_eval(const struct nft_expr *expr,
                break;
 #endif
        case NFT_META_PRANDOM:
-               *dest = nft_prandom_u32();
+               *dest = get_random_u32();
                break;
 #ifdef CONFIG_XFRM
        case NFT_META_SECPATH:
@@ -518,7 +510,6 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
                len = IFNAMSIZ;
                break;
        case NFT_META_PRANDOM:
-               prandom_init_once(&nft_prandom_state);
                len = sizeof(u32);
                break;
 #ifdef CONFIG_XFRM
index 81b40c6..45d3dc9 100644 (file)
@@ -9,12 +9,11 @@
 #include <linux/netlink.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter/nf_tables.h>
+#include <linux/random.h>
 #include <linux/static_key.h>
 #include <net/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables_core.h>
 
-static DEFINE_PER_CPU(struct rnd_state, nft_numgen_prandom_state);
-
 struct nft_ng_inc {
        u8                      dreg;
        u32                     modulus;
@@ -135,12 +134,9 @@ struct nft_ng_random {
        u32                     offset;
 };
 
-static u32 nft_ng_random_gen(struct nft_ng_random *priv)
+static u32 nft_ng_random_gen(const struct nft_ng_random *priv)
 {
-       struct rnd_state *state = this_cpu_ptr(&nft_numgen_prandom_state);
-
-       return reciprocal_scale(prandom_u32_state(state), priv->modulus) +
-              priv->offset;
+       return reciprocal_scale(get_random_u32(), priv->modulus) + priv->offset;
 }
 
 static void nft_ng_random_eval(const struct nft_expr *expr,
@@ -168,8 +164,6 @@ static int nft_ng_random_init(const struct nft_ctx *ctx,
        if (priv->offset + priv->modulus - 1 < priv->offset)
                return -EOVERFLOW;
 
-       prandom_init_once(&nft_numgen_prandom_state);
-
        return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
                                        NULL, NFT_DATA_VALUE, sizeof(u32));
 }
index 372bf54..e20d1a9 100644 (file)
@@ -407,7 +407,7 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
        if (flags & IP6_FH_F_FRAG) {
                if (frag_off) {
                        key->ip.frag = OVS_FRAG_TYPE_LATER;
-                       key->ip.proto = nexthdr;
+                       key->ip.proto = NEXTHDR_FRAGMENT;
                        return 0;
                }
                key->ip.frag = OVS_FRAG_TYPE_FIRST;
index ed4ccef..5449ed1 100644 (file)
@@ -1146,9 +1146,9 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
        struct tc_netem_rate rate;
        struct tc_netem_slot slot;
 
-       qopt.latency = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->latency),
+       qopt.latency = min_t(psched_time_t, PSCHED_NS2TICKS(q->latency),
                             UINT_MAX);
-       qopt.jitter = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->jitter),
+       qopt.jitter = min_t(psched_time_t, PSCHED_NS2TICKS(q->jitter),
                            UINT_MAX);
        qopt.limit = q->limit;
        qopt.loss = q->loss;
index e2c6eca..b6781ad 100644 (file)
@@ -651,6 +651,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
        new->cl_discrtry = clnt->cl_discrtry;
        new->cl_chatty = clnt->cl_chatty;
        new->cl_principal = clnt->cl_principal;
+       new->cl_max_connect = clnt->cl_max_connect;
        return new;
 
 out_err:
index 3f4542e..434e70e 100644 (file)
@@ -109,10 +109,9 @@ static void __net_exit tipc_exit_net(struct net *net)
        struct tipc_net *tn = tipc_net(net);
 
        tipc_detach_loopback(net);
+       tipc_net_stop(net);
        /* Make sure the tipc_net_finalize_work() finished */
        cancel_work_sync(&tn->work);
-       tipc_net_stop(net);
-
        tipc_bcast_stop(net);
        tipc_nametbl_stop(net);
        tipc_sk_rht_destroy(net);
index da17641..2ffede4 100644 (file)
@@ -921,6 +921,8 @@ static void tls_update(struct sock *sk, struct proto *p,
 {
        struct tls_context *ctx;
 
+       WARN_ON_ONCE(sk->sk_prot == p);
+
        ctx = tls_get_ctx(sk);
        if (likely(ctx)) {
                ctx->sk_write_space = write_space;
index 19ac872..0900238 100644 (file)
@@ -538,12 +538,6 @@ static int xsk_generic_xmit(struct sock *sk)
                        goto out;
                }
 
-               skb = xsk_build_skb(xs, &desc);
-               if (IS_ERR(skb)) {
-                       err = PTR_ERR(skb);
-                       goto out;
-               }
-
                /* This is the backpressure mechanism for the Tx path.
                 * Reserve space in the completion queue and only proceed
                 * if there is space in it. This avoids having to implement
@@ -552,11 +546,19 @@ static int xsk_generic_xmit(struct sock *sk)
                spin_lock_irqsave(&xs->pool->cq_lock, flags);
                if (xskq_prod_reserve(xs->pool->cq)) {
                        spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
-                       kfree_skb(skb);
                        goto out;
                }
                spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
 
+               skb = xsk_build_skb(xs, &desc);
+               if (IS_ERR(skb)) {
+                       err = PTR_ERR(skb);
+                       spin_lock_irqsave(&xs->pool->cq_lock, flags);
+                       xskq_prod_cancel(xs->pool->cq);
+                       spin_unlock_irqrestore(&xs->pool->cq_lock, flags);
+                       goto out;
+               }
+
                err = __dev_direct_xmit(skb, xs->queue_id);
                if  (err == NETDEV_TX_BUSY) {
                        /* Tell user-space to retry the send */
index 24d3cf1..01ee6c8 100644 (file)
@@ -21,6 +21,7 @@
 #define BACKTRACE_DEPTH 16
 #define MAX_SYMBOL_LEN 4096
 struct fprobe sample_probe;
+static unsigned long nhit;
 
 static char symbol[MAX_SYMBOL_LEN] = "kernel_clone";
 module_param_string(symbol, symbol, sizeof(symbol), 0644);
@@ -28,6 +29,8 @@ static char nosymbol[MAX_SYMBOL_LEN] = "";
 module_param_string(nosymbol, nosymbol, sizeof(nosymbol), 0644);
 static bool stackdump = true;
 module_param(stackdump, bool, 0644);
+static bool use_trace = false;
+module_param(use_trace, bool, 0644);
 
 static void show_backtrace(void)
 {
@@ -40,7 +43,15 @@ static void show_backtrace(void)
 
 static void sample_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs)
 {
-       pr_info("Enter <%pS> ip = 0x%p\n", (void *)ip, (void *)ip);
+       if (use_trace)
+               /*
+                * This is just an example, no kernel code should call
+                * trace_printk() except when actively debugging.
+                */
+               trace_printk("Enter <%pS> ip = 0x%p\n", (void *)ip, (void *)ip);
+       else
+               pr_info("Enter <%pS> ip = 0x%p\n", (void *)ip, (void *)ip);
+       nhit++;
        if (stackdump)
                show_backtrace();
 }
@@ -49,8 +60,17 @@ static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_r
 {
        unsigned long rip = instruction_pointer(regs);
 
-       pr_info("Return from <%pS> ip = 0x%p to rip = 0x%p (%pS)\n",
-               (void *)ip, (void *)ip, (void *)rip, (void *)rip);
+       if (use_trace)
+               /*
+                * This is just an example, no kernel code should call
+                * trace_printk() except when actively debugging.
+                */
+               trace_printk("Return from <%pS> ip = 0x%p to rip = 0x%p (%pS)\n",
+                       (void *)ip, (void *)ip, (void *)rip, (void *)rip);
+       else
+               pr_info("Return from <%pS> ip = 0x%p to rip = 0x%p (%pS)\n",
+                       (void *)ip, (void *)ip, (void *)rip, (void *)rip);
+       nhit++;
        if (stackdump)
                show_backtrace();
 }
@@ -112,7 +132,8 @@ static void __exit fprobe_exit(void)
 {
        unregister_fprobe(&sample_probe);
 
-       pr_info("fprobe at %s unregistered\n", symbol);
+       pr_info("fprobe at %s unregistered. %ld times hit, %ld times missed\n",
+               symbol, nhit, sample_probe.nmissed);
 }
 
 module_init(fprobe_init)
index 0e6268d..94ed98d 100755 (executable)
@@ -95,17 +95,25 @@ __faddr2line() {
        local print_warnings=$4
 
        local sym_name=${func_addr%+*}
-       local offset=${func_addr#*+}
-       offset=${offset%/*}
+       local func_offset=${func_addr#*+}
+       func_offset=${func_offset%/*}
        local user_size=
+       local file_type
+       local is_vmlinux=0
        [[ $func_addr =~ "/" ]] && user_size=${func_addr#*/}
 
-       if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then
+       if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then
                warn "bad func+offset $func_addr"
                DONE=1
                return
        fi
 
+       # vmlinux uses absolute addresses in the section table rather than
+       # section offsets.
+       local file_type=$(${READELF} --file-header $objfile |
+               ${AWK} '$1 == "Type:" { print $2; exit }')
+       [[ $file_type = "EXEC" ]] && is_vmlinux=1
+
        # Go through each of the object's symbols which match the func name.
        # In rare cases there might be duplicates, in which case we print all
        # matches.
@@ -114,9 +122,11 @@ __faddr2line() {
                local sym_addr=0x${fields[1]}
                local sym_elf_size=${fields[2]}
                local sym_sec=${fields[6]}
+               local sec_size
+               local sec_name
 
                # Get the section size:
-               local sec_size=$(${READELF} --section-headers --wide $objfile |
+               sec_size=$(${READELF} --section-headers --wide $objfile |
                        sed 's/\[ /\[/' |
                        ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }')
 
@@ -126,6 +136,17 @@ __faddr2line() {
                        return
                fi
 
+               # Get the section name:
+               sec_name=$(${READELF} --section-headers --wide $objfile |
+                       sed 's/\[ /\[/' |
+                       ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }')
+
+               if [[ -z $sec_name ]]; then
+                       warn "bad section name: section: $sym_sec"
+                       DONE=1
+                       return
+               fi
+
                # Calculate the symbol size.
                #
                # Unfortunately we can't use the ELF size, because kallsyms
@@ -174,10 +195,10 @@ __faddr2line() {
 
                sym_size=0x$(printf %x $sym_size)
 
-               # Calculate the section address from user-supplied offset:
-               local addr=$(($sym_addr + $offset))
+               # Calculate the address from user-supplied offset:
+               local addr=$(($sym_addr + $func_offset))
                if [[ -z $addr ]] || [[ $addr = 0 ]]; then
-                       warn "bad address: $sym_addr + $offset"
+                       warn "bad address: $sym_addr + $func_offset"
                        DONE=1
                        return
                fi
@@ -191,9 +212,9 @@ __faddr2line() {
                fi
 
                # Make sure the provided offset is within the symbol's range:
-               if [[ $offset -gt $sym_size ]]; then
+               if [[ $func_offset -gt $sym_size ]]; then
                        [[ $print_warnings = 1 ]] &&
-                               echo "skipping $sym_name address at $addr due to size mismatch ($offset > $sym_size)"
+                               echo "skipping $sym_name address at $addr due to size mismatch ($func_offset > $sym_size)"
                        continue
                fi
 
@@ -202,11 +223,13 @@ __faddr2line() {
                [[ $FIRST = 0 ]] && echo
                FIRST=0
 
-               echo "$sym_name+$offset/$sym_size:"
+               echo "$sym_name+$func_offset/$sym_size:"
 
                # Pass section address to addr2line and strip absolute paths
                # from the output:
-               local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;")
+               local args="--functions --pretty-print --inlines --exe=$objfile"
+               [[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name"
+               local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;")
                [[ -z $output ]] && continue
 
                # Default output (non --list):
index beceb89..1bbd533 100644 (file)
@@ -2600,8 +2600,9 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
                                }
                        }
                        rc = selinux_add_opt(token, arg, mnt_opts);
+                       kfree(arg);
+                       arg = NULL;
                        if (unlikely(rc)) {
-                               kfree(arg);
                                goto free_opt;
                        }
                } else {
@@ -2792,17 +2793,13 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
                                          struct fs_parameter *param)
 {
        struct fs_parse_result result;
-       int opt, rc;
+       int opt;
 
        opt = fs_parse(fc, selinux_fs_parameters, param, &result);
        if (opt < 0)
                return opt;
 
-       rc = selinux_add_opt(opt, param->string, &fc->security);
-       if (!rc)
-               param->string = NULL;
-
-       return rc;
+       return selinux_add_opt(opt, param->string, &fc->security);
 }
 
 /* inode security operations */
index 15dc716..8cfdaee 100644 (file)
@@ -431,33 +431,17 @@ static const struct snd_malloc_ops snd_dma_iram_ops = {
  */
 static void *snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
-       void *p;
-
-       p = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
-#ifdef CONFIG_X86
-       if (p && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
-               set_memory_wc((unsigned long)p, PAGE_ALIGN(size) >> PAGE_SHIFT);
-#endif
-       return p;
+       return dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
 }
 
 static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
 {
-#ifdef CONFIG_X86
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
-               set_memory_wb((unsigned long)dmab->area,
-                             PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
-#endif
        dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 }
 
 static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab,
                            struct vm_area_struct *area)
 {
-#ifdef CONFIG_X86
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
-               area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
-#endif
        return dma_mmap_coherent(dmab->dev.dev, area,
                                 dmab->area, dmab->addr, dmab->bytes);
 }
@@ -471,10 +455,6 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
 /*
  * Write-combined pages
  */
-#ifdef CONFIG_X86
-/* On x86, share the same ops as the standard dev ops */
-#define snd_dma_wc_ops snd_dma_dev_ops
-#else /* CONFIG_X86 */
 static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
@@ -497,7 +477,6 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
        .free = snd_dma_wc_free,
        .mmap = snd_dma_wc_mmap,
 };
-#endif /* CONFIG_X86 */
 
 #ifdef CONFIG_SND_DMA_SGBUF
 static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
index 3f35972..161a971 100644 (file)
@@ -119,21 +119,18 @@ static int i915_component_master_match(struct device *dev, int subcomponent,
 /* check whether Intel graphics is present and reachable */
 static int i915_gfx_present(struct pci_dev *hdac_pci)
 {
-       unsigned int class = PCI_BASE_CLASS_DISPLAY << 16;
        struct pci_dev *display_dev = NULL;
-       bool match = false;
 
-       do {
-               display_dev = pci_get_class(class, display_dev);
-
-               if (display_dev && display_dev->vendor == PCI_VENDOR_ID_INTEL &&
+       for_each_pci_dev(display_dev) {
+               if (display_dev->vendor == PCI_VENDOR_ID_INTEL &&
+                   (display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
                    connectivity_check(display_dev, hdac_pci)) {
                        pci_dev_put(display_dev);
-                       match = true;
+                       return true;
                }
-       } while (!match && display_dev);
+       }
 
-       return match;
+       return false;
 }
 
 /**
index a8fe017..ec9cbb2 100644 (file)
@@ -196,6 +196,12 @@ static const struct config_entry config_table[] = {
                                        DMI_MATCH(DMI_SYS_VENDOR, "Google"),
                                }
                        },
+                       {
+                               .ident = "UP-WHL",
+                               .matches = {
+                                       DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+                               }
+                       },
                        {}
                }
        },
@@ -358,6 +364,12 @@ static const struct config_entry config_table[] = {
                                        DMI_MATCH(DMI_SYS_VENDOR, "Google"),
                                }
                        },
+                       {
+                               .ident = "UPX-TGL",
+                               .matches = {
+                                       DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+                               }
+                       },
                        {}
                }
        },
index 4063da3..9db5ccd 100644 (file)
@@ -55,8 +55,8 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
 
                /* find max number of channels based on format_configuration */
                if (fmt_configs->fmt_count) {
-                       dev_dbg(dev, "%s: found %d format definitions\n",
-                               __func__, fmt_configs->fmt_count);
+                       dev_dbg(dev, "found %d format definitions\n",
+                               fmt_configs->fmt_count);
 
                        for (i = 0; i < fmt_configs->fmt_count; i++) {
                                struct wav_fmt_ext *fmt_ext;
@@ -66,9 +66,9 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
                                if (fmt_ext->fmt.channels > max_ch)
                                        max_ch = fmt_ext->fmt.channels;
                        }
-                       dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch);
+                       dev_dbg(dev, "max channels found %d\n", max_ch);
                } else {
-                       dev_dbg(dev, "%s: No format information found\n", __func__);
+                       dev_dbg(dev, "No format information found\n");
                }
 
                if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
@@ -95,17 +95,16 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
                        }
 
                        if (dmic_geo > 0) {
-                               dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo);
+                               dev_dbg(dev, "Array with %d dmics\n", dmic_geo);
                        }
                        if (max_ch > dmic_geo) {
-                               dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n",
-                                       __func__, max_ch, dmic_geo);
+                               dev_dbg(dev, "max channels %d exceed dmic number %d\n",
+                                       max_ch, dmic_geo);
                        }
                }
        }
 
-       dev_dbg(dev, "%s: dmic number %d max_ch %d\n",
-               __func__, dmic_geo, max_ch);
+       dev_dbg(dev, "dmic number %d max_ch %d\n", dmic_geo, max_ch);
 
        return dmic_geo;
 }
index cd1db94..7c6b1fe 100644 (file)
@@ -819,7 +819,7 @@ static void set_pin_targets(struct hda_codec *codec,
                snd_hda_set_pin_ctl_cache(codec, cfg->nid, cfg->val);
 }
 
-static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
+void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth)
 {
        const char *modelname = codec->fixup_name;
 
@@ -829,7 +829,7 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
                if (++depth > 10)
                        break;
                if (fix->chained_before)
-                       apply_fixup(codec, fix->chain_id, action, depth + 1);
+                       __snd_hda_apply_fixup(codec, fix->chain_id, action, depth + 1);
 
                switch (fix->type) {
                case HDA_FIXUP_PINS:
@@ -870,6 +870,7 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
                id = fix->chain_id;
        }
 }
+EXPORT_SYMBOL_GPL(__snd_hda_apply_fixup);
 
 /**
  * snd_hda_apply_fixup - Apply the fixup chain with the given action
@@ -879,7 +880,7 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
 void snd_hda_apply_fixup(struct hda_codec *codec, int action)
 {
        if (codec->fixup_list)
-               apply_fixup(codec, codec->fixup_id, action, 0);
+               __snd_hda_apply_fixup(codec, codec->fixup_id, action, 0);
 }
 EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
 
index aca5926..682dca2 100644 (file)
@@ -348,6 +348,7 @@ void snd_hda_apply_verbs(struct hda_codec *codec);
 void snd_hda_apply_pincfgs(struct hda_codec *codec,
                           const struct hda_pintbl *cfg);
 void snd_hda_apply_fixup(struct hda_codec *codec, int action);
+void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
 void snd_hda_pick_fixup(struct hda_codec *codec,
                        const struct hda_model_fixup *models,
                        const struct snd_pci_quirk *quirk,
index 1248d1a..3e541a4 100644 (file)
@@ -1079,11 +1079,11 @@ static int patch_conexant_auto(struct hda_codec *codec)
        if (err < 0)
                goto error;
 
-       err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+       err = cx_auto_parse_beep(codec);
        if (err < 0)
                goto error;
 
-       err = cx_auto_parse_beep(codec);
+       err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
        if (err < 0)
                goto error;
 
index b0f9541..cee69fa 100644 (file)
@@ -2634,6 +2634,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
@@ -7004,6 +7005,7 @@ enum {
        ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS,
        ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
        ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
+       ALC298_FIXUP_LENOVO_C940_DUET7,
        ALC287_FIXUP_13S_GEN2_SPEAKERS,
        ALC256_FIXUP_SET_COEF_DEFAULTS,
        ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
@@ -7022,6 +7024,23 @@ enum {
        ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE,
 };
 
+/* A special fixup for Lenovo C940 and Yoga Duet 7;
+ * both have the very same PCI SSID, and we need to apply different fixups
+ * depending on the codec ID
+ */
+static void alc298_fixup_lenovo_c940_duet7(struct hda_codec *codec,
+                                          const struct hda_fixup *fix,
+                                          int action)
+{
+       int id;
+
+       if (codec->core.vendor_id == 0x10ec0298)
+               id = ALC298_FIXUP_LENOVO_SPK_VOLUME; /* C940 */
+       else
+               id = ALC287_FIXUP_YOGA7_14ITL_SPEAKERS; /* Duet 7 */
+       __snd_hda_apply_fixup(codec, id, action, 0);
+}
+
 static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_GPIO2] = {
                .type = HDA_FIXUP_FUNC,
@@ -8721,6 +8740,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MODE,
        },
+       [ALC298_FIXUP_LENOVO_C940_DUET7] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc298_fixup_lenovo_c940_duet7,
+       },
        [ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -9022,6 +9045,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
                      ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation",
                      ALC285_FIXUP_HP_GPIO_AMP_INIT),
+       SND_PCI_QUIRK(0x103c, 0x8787, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
@@ -9187,6 +9211,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x7716, "Clevo NS50PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -9273,7 +9298,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
        SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
        SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
-       SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
+       SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
        SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
        SND_PCI_QUIRK(0x17aa, 0x3820, "Yoga Duet 7 13ITL6", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
        SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
@@ -10737,6 +10762,7 @@ enum {
        ALC668_FIXUP_MIC_DET_COEF,
        ALC897_FIXUP_LENOVO_HEADSET_MIC,
        ALC897_FIXUP_HEADSET_MIC_PIN,
+       ALC897_FIXUP_HP_HSMIC_VERB,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -11156,6 +11182,13 @@ static const struct hda_fixup alc662_fixups[] = {
                .chained = true,
                .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
        },
+       [ALC897_FIXUP_HP_HSMIC_VERB] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+       },
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -11181,6 +11214,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+       SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
        SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
        SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
        SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
index a05304f..aea7fae 100644 (file)
@@ -518,11 +518,11 @@ static int via_parse_auto_config(struct hda_codec *codec)
        if (err < 0)
                return err;
 
-       err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
+       err = auto_parse_beep(codec);
        if (err < 0)
                return err;
 
-       err = auto_parse_beep(codec);
+       err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
        if (err < 0)
                return err;
 
index b7b6f38..6eb7d93 100644 (file)
@@ -637,10 +637,10 @@ static int snd_get_meter_comp_index(struct snd_us16x08_meter_store *store)
                }
        } else {
                /* skip channels with no compressor active */
-               while (!store->comp_store->val[
+               while (store->comp_index <= SND_US16X08_MAX_CHANNELS
+                       && !store->comp_store->val[
                        COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
-                       [store->comp_index - 1]
-                       && store->comp_index <= SND_US16X08_MAX_CHANNELS) {
+                       [store->comp_index - 1]) {
                        store->comp_index++;
                }
                ret = store->comp_index++;
index 0d828e3..ab95fb3 100644 (file)
@@ -33,6 +33,8 @@
 #include <drm/intel_lpe_audio.h>
 #include "intel_hdmi_audio.h"
 
+#define INTEL_HDMI_AUDIO_SUSPEND_DELAY_MS  5000
+
 #define for_each_pipe(card_ctx, pipe) \
        for ((pipe) = 0; (pipe) < (card_ctx)->num_pipes; (pipe)++)
 #define for_each_port(card_ctx, port) \
@@ -1066,7 +1068,9 @@ static int had_pcm_open(struct snd_pcm_substream *substream)
        intelhaddata = snd_pcm_substream_chip(substream);
        runtime = substream->runtime;
 
-       pm_runtime_get_sync(intelhaddata->dev);
+       retval = pm_runtime_resume_and_get(intelhaddata->dev);
+       if (retval < 0)
+               return retval;
 
        /* set the runtime hw parameter with local snd_pcm_hardware struct */
        runtime->hw = had_pcm_hardware;
@@ -1534,8 +1538,12 @@ static void had_audio_wq(struct work_struct *work)
                container_of(work, struct snd_intelhad, hdmi_audio_wq);
        struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data;
        struct intel_hdmi_lpe_audio_port_pdata *ppdata = &pdata->port[ctx->port];
+       int ret;
+
+       ret = pm_runtime_resume_and_get(ctx->dev);
+       if (ret < 0)
+               return;
 
-       pm_runtime_get_sync(ctx->dev);
        mutex_lock(&ctx->mutex);
        if (ppdata->pipe < 0) {
                dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG : port = %d\n",
@@ -1802,8 +1810,11 @@ static int __hdmi_lpe_audio_probe(struct platform_device *pdev)
        pdata->notify_audio_lpe = notify_audio_lpe;
        spin_unlock_irq(&pdata->lpe_audio_slock);
 
+       pm_runtime_set_autosuspend_delay(&pdev->dev, INTEL_HDMI_AUDIO_SUSPEND_DELAY_MS);
        pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
        pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_idle(&pdev->dev);
 
        dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__);
        for_each_port(card_ctx, port) {
index e09d690..8aa0d27 100644 (file)
@@ -36,7 +36,7 @@
 #define MIDR_VARIANT(midr)     \
        (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
 #define MIDR_IMPLEMENTOR_SHIFT 24
-#define MIDR_IMPLEMENTOR_MASK  (0xff << MIDR_IMPLEMENTOR_SHIFT)
+#define MIDR_IMPLEMENTOR_MASK  (0xffU << MIDR_IMPLEMENTOR_SHIFT)
 #define MIDR_IMPLEMENTOR(midr) \
        (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
 
 
 #define APPLE_CPU_PART_M1_ICESTORM     0x022
 #define APPLE_CPU_PART_M1_FIRESTORM    0x023
+#define APPLE_CPU_PART_M1_ICESTORM_PRO 0x024
+#define APPLE_CPU_PART_M1_FIRESTORM_PRO        0x025
+#define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028
+#define APPLE_CPU_PART_M1_FIRESTORM_MAX        0x029
 
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
 #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
 #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
+#define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
+#define MIDR_APPLE_M1_FIRESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO)
+#define MIDR_APPLE_M1_ICESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX)
+#define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
 #define MIDR_FUJITSU_ERRATUM_010001            MIDR_FUJITSU_A64FX
 
 #ifndef __ASSEMBLY__
 
-#include "sysreg.h"
+#include <asm/sysreg.h>
 
 #define read_cpuid(reg)                        read_sysreg_s(SYS_ ## reg)
 
index 73e643a..e17de69 100644 (file)
 #define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 #define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
+#define X86_BUG_MMIO_STALE_DATA                X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 403e83b..d27e058 100644 (file)
                                                 * Not susceptible to
                                                 * TSX Async Abort (TAA) vulnerabilities.
                                                 */
+#define ARCH_CAP_SBDR_SSDP_NO          BIT(13) /*
+                                                * Not susceptible to SBDR and SSDP
+                                                * variants of Processor MMIO stale data
+                                                * vulnerabilities.
+                                                */
+#define ARCH_CAP_FBSDP_NO              BIT(14) /*
+                                                * Not susceptible to FBSDP variant of
+                                                * Processor MMIO stale data
+                                                * vulnerabilities.
+                                                */
+#define ARCH_CAP_PSDP_NO               BIT(15) /*
+                                                * Not susceptible to PSDP variant of
+                                                * Processor MMIO stale data
+                                                * vulnerabilities.
+                                                */
+#define ARCH_CAP_FB_CLEAR              BIT(17) /*
+                                                * VERW clears CPU fill buffer
+                                                * even on MDS_NO CPUs.
+                                                */
+#define ARCH_CAP_FB_CLEAR_CTRL         BIT(18) /*
+                                                * MSR_IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]
+                                                * bit available to control VERW
+                                                * behavior.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*
 #define MSR_IA32_MCU_OPT_CTRL          0x00000123
 #define RNGDS_MITG_DIS                 BIT(0)  /* SRBDS support */
 #define RTM_ALLOW                      BIT(1)  /* TSX development mode */
+#define FB_CLEAR_DIS                   BIT(3)  /* CPU Fill buffer clear disable */
 
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
index bf6e960..2161480 100644 (file)
@@ -428,11 +428,12 @@ struct kvm_sync_regs {
        struct kvm_vcpu_events events;
 };
 
-#define KVM_X86_QUIRK_LINT0_REENABLED     (1 << 0)
-#define KVM_X86_QUIRK_CD_NW_CLEARED       (1 << 1)
-#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE     (1 << 2)
-#define KVM_X86_QUIRK_OUT_7E_INC_RIP      (1 << 3)
-#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
+#define KVM_X86_QUIRK_LINT0_REENABLED          (1 << 0)
+#define KVM_X86_QUIRK_CD_NW_CLEARED            (1 << 1)
+#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE          (1 << 2)
+#define KVM_X86_QUIRK_OUT_7E_INC_RIP           (1 << 3)
+#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT     (1 << 4)
+#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN       (1 << 5)
 
 #define KVM_STATE_NESTED_FORMAT_VMX    0
 #define KVM_STATE_NESTED_FORMAT_SVM    1
index 6491fa8..15b940e 100644 (file)
@@ -143,6 +143,12 @@ struct unwind_hint {
        .popsection
 .endm
 
+.macro STACK_FRAME_NON_STANDARD_FP func:req
+#ifdef CONFIG_FRAME_POINTER
+       STACK_FRAME_NON_STANDARD \func
+#endif
+.endm
+
 .macro ANNOTATE_NOENDBR
 .Lhere_\@:
        .pushsection .discard.noendbr
index e998764..a5e06dc 100644 (file)
@@ -272,6 +272,15 @@ struct prctl_mm_map {
 # define PR_SCHED_CORE_SCOPE_THREAD_GROUP      1
 # define PR_SCHED_CORE_SCOPE_PROCESS_GROUP     2
 
+/* arm64 Scalable Matrix Extension controls */
+/* Flag values must be in sync with SVE versions */
+#define PR_SME_SET_VL                  63      /* set task vector length */
+# define PR_SME_SET_VL_ONEXEC          (1 << 18) /* defer effect until exec */
+#define PR_SME_GET_VL                  64      /* get task vector length */
+/* Bits common to PR_SME_SET_VL and PR_SME_GET_VL */
+# define PR_SME_VL_LEN_MASK            0xffff
+# define PR_SME_VL_INHERIT             (1 << 17) /* inherit across exec */
+
 #define PR_SET_VMA             0x53564d41
 # define PR_SET_VMA_ANON_NAME          0
 
index c1d5867..952f352 100644 (file)
@@ -149,23 +149,30 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
                        int fd, group_fd, *evsel_fd;
 
                        evsel_fd = FD(evsel, idx, thread);
-                       if (evsel_fd == NULL)
-                               return -EINVAL;
+                       if (evsel_fd == NULL) {
+                               err = -EINVAL;
+                               goto out;
+                       }
 
                        err = get_group_fd(evsel, idx, thread, &group_fd);
                        if (err < 0)
-                               return err;
+                               goto out;
 
                        fd = sys_perf_event_open(&evsel->attr,
                                                 threads->map[thread].pid,
                                                 cpu, group_fd, 0);
 
-                       if (fd < 0)
-                               return -errno;
+                       if (fd < 0) {
+                               err = -errno;
+                               goto out;
+                       }
 
                        *evsel_fd = fd;
                }
        }
+out:
+       if (err)
+               perf_evsel__close(evsel);
 
        return err;
 }
index d1ebb55..6f921db 100644 (file)
@@ -151,11 +151,21 @@ static int detect_ioctl(void)
 static int detect_share(int wp_cnt, int bp_cnt)
 {
        struct perf_event_attr attr;
-       int i, fd[wp_cnt + bp_cnt], ret;
+       int i, *fd = NULL, ret = -1;
+
+       if (wp_cnt + bp_cnt == 0)
+               return 0;
+
+       fd = malloc(sizeof(int) * (wp_cnt + bp_cnt));
+       if (!fd)
+               return -1;
 
        for (i = 0; i < wp_cnt; i++) {
                fd[i] = wp_event((void *)&the_var, &attr);
-               TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
+               if (fd[i] == -1) {
+                       pr_err("failed to create wp\n");
+                       goto out;
+               }
        }
 
        for (; i < (bp_cnt + wp_cnt); i++) {
@@ -166,9 +176,11 @@ static int detect_share(int wp_cnt, int bp_cnt)
 
        ret = i != (bp_cnt + wp_cnt);
 
+out:
        while (i--)
                close(fd[i]);
 
+       free(fd);
        return ret;
 }
 
index d54c537..5c0032f 100644 (file)
@@ -97,6 +97,8 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
        ret |= test(ctx, "2.2 > 2.2", 0);
        ret |= test(ctx, "2.2 < 1.1", 0);
        ret |= test(ctx, "1.1 > 2.2", 0);
+       ret |= test(ctx, "1.1e10 < 1.1e100", 1);
+       ret |= test(ctx, "1.1e2 > 1.1e-2", 1);
 
        if (ret) {
                expr__ctx_free(ctx);
diff --git a/tools/perf/tests/shell/lib/perf_csv_output_lint.py b/tools/perf/tests/shell/lib/perf_csv_output_lint.py
deleted file mode 100644 (file)
index 714f283..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/python
-# SPDX-License-Identifier: GPL-2.0
-
-import argparse
-import sys
-
-# Basic sanity check of perf CSV output as specified in the man page.
-# Currently just checks the number of fields per line in output.
-
-ap = argparse.ArgumentParser()
-ap.add_argument('--no-args', action='store_true')
-ap.add_argument('--interval', action='store_true')
-ap.add_argument('--system-wide-no-aggr', action='store_true')
-ap.add_argument('--system-wide', action='store_true')
-ap.add_argument('--event', action='store_true')
-ap.add_argument('--per-core', action='store_true')
-ap.add_argument('--per-thread', action='store_true')
-ap.add_argument('--per-die', action='store_true')
-ap.add_argument('--per-node', action='store_true')
-ap.add_argument('--per-socket', action='store_true')
-ap.add_argument('--separator', default=',', nargs='?')
-args = ap.parse_args()
-
-Lines = sys.stdin.readlines()
-
-def check_csv_output(exp):
-  for line in Lines:
-    if 'failed' not in line:
-      count = line.count(args.separator)
-      if count != exp:
-        sys.stdout.write(''.join(Lines))
-        raise RuntimeError(f'wrong number of fields. expected {exp} in {line}')
-
-try:
-  if args.no_args or args.system_wide or args.event:
-    expected_items = 6
-  elif args.interval or args.per_thread or args.system_wide_no_aggr:
-    expected_items = 7
-  elif args.per_core or args.per_socket or args.per_node or args.per_die:
-    expected_items = 8
-  else:
-    ap.print_help()
-    raise RuntimeError('No checking option specified')
-  check_csv_output(expected_items)
-
-except:
-  sys.stdout.write('Test failed for input: ' + ''.join(Lines))
-  raise
index 983220e..38c26f3 100755 (executable)
@@ -6,20 +6,41 @@
 
 set -e
 
-pythonchecker=$(dirname $0)/lib/perf_csv_output_lint.py
-if [ "x$PYTHON" == "x" ]
-then
-       if which python3 > /dev/null
-       then
-               PYTHON=python3
-       elif which python > /dev/null
-       then
-               PYTHON=python
-       else
-               echo Skipping test, python not detected please set environment variable PYTHON.
-               exit 2
-       fi
-fi
+function commachecker()
+{
+       local -i cnt=0 exp=0
+
+       case "$1"
+       in "--no-args")         exp=6
+       ;; "--system-wide")     exp=6
+       ;; "--event")           exp=6
+       ;; "--interval")        exp=7
+       ;; "--per-thread")      exp=7
+       ;; "--system-wide-no-aggr")     exp=7
+                               [ $(uname -m) = "s390x" ] && exp=6
+       ;; "--per-core")        exp=8
+       ;; "--per-socket")      exp=8
+       ;; "--per-node")        exp=8
+       ;; "--per-die")         exp=8
+       esac
+
+       while read line
+       do
+               # Check for lines beginning with Failed
+               x=${line:0:6}
+               [ "$x" = "Failed" ] && continue
+
+               # Count the number of commas
+               x=$(echo $line | tr -d -c ',')
+               cnt="${#x}"
+               # echo $line $cnt
+               [ "$cnt" -ne "$exp" ] && {
+                       echo "wrong number of fields. expected $exp in $line" 1>&2
+                       exit 1;
+               }
+       done
+       return 0
+}
 
 # Return true if perf_event_paranoid is > $1 and not running as root.
 function ParanoidAndNotRoot()
@@ -30,7 +51,7 @@ function ParanoidAndNotRoot()
 check_no_args()
 {
        echo -n "Checking CSV output: no args "
-       perf stat -x, true 2>&1 | $PYTHON $pythonchecker --no-args
+       perf stat -x, true 2>&1 | commachecker --no-args
        echo "[Success]"
 }
 
@@ -42,7 +63,7 @@ check_system_wide()
                echo "[Skip] paranoid and not root"
                return
        fi
-       perf stat -x, -a true 2>&1 | $PYTHON $pythonchecker --system-wide
+       perf stat -x, -a true 2>&1 | commachecker --system-wide
        echo "[Success]"
 }
 
@@ -55,14 +76,14 @@ check_system_wide_no_aggr()
                return
        fi
        echo -n "Checking CSV output: system wide no aggregation "
-       perf stat -x, -A -a --no-merge true 2>&1 | $PYTHON $pythonchecker --system-wide-no-aggr
+       perf stat -x, -A -a --no-merge true 2>&1 | commachecker --system-wide-no-aggr
        echo "[Success]"
 }
 
 check_interval()
 {
        echo -n "Checking CSV output: interval "
-       perf stat -x, -I 1000 true 2>&1 | $PYTHON $pythonchecker --interval
+       perf stat -x, -I 1000 true 2>&1 | commachecker --interval
        echo "[Success]"
 }
 
@@ -70,7 +91,7 @@ check_interval()
 check_event()
 {
        echo -n "Checking CSV output: event "
-       perf stat -x, -e cpu-clock true 2>&1 | $PYTHON $pythonchecker --event
+       perf stat -x, -e cpu-clock true 2>&1 | commachecker --event
        echo "[Success]"
 }
 
@@ -82,7 +103,7 @@ check_per_core()
                echo "[Skip] paranoid and not root"
                return
        fi
-       perf stat -x, --per-core -a true 2>&1 | $PYTHON $pythonchecker --per-core
+       perf stat -x, --per-core -a true 2>&1 | commachecker --per-core
        echo "[Success]"
 }
 
@@ -94,7 +115,7 @@ check_per_thread()
                echo "[Skip] paranoid and not root"
                return
        fi
-       perf stat -x, --per-thread -a true 2>&1 | $PYTHON $pythonchecker --per-thread
+       perf stat -x, --per-thread -a true 2>&1 | commachecker --per-thread
        echo "[Success]"
 }
 
@@ -106,7 +127,7 @@ check_per_die()
                echo "[Skip] paranoid and not root"
                return
        fi
-       perf stat -x, --per-die -a true 2>&1 | $PYTHON $pythonchecker --per-die
+       perf stat -x, --per-die -a true 2>&1 | commachecker --per-die
        echo "[Success]"
 }
 
@@ -118,7 +139,7 @@ check_per_node()
                echo "[Skip] paranoid and not root"
                return
        fi
-       perf stat -x, --per-node -a true 2>&1 | $PYTHON $pythonchecker --per-node
+       perf stat -x, --per-node -a true 2>&1 | commachecker --per-node
        echo "[Success]"
 }
 
@@ -130,7 +151,7 @@ check_per_socket()
                echo "[Skip] paranoid and not root"
                return
        fi
-       perf stat -x, --per-socket -a true 2>&1 | $PYTHON $pythonchecker --per-socket
+       perf stat -x, --per-socket -a true 2>&1 | commachecker --per-socket
        echo "[Success]"
 }
 
index 6ffbb27..ec108d4 100755 (executable)
@@ -43,7 +43,7 @@ CFLAGS="-g -O0 -fno-inline -fno-omit-frame-pointer"
 cc $CFLAGS $TEST_PROGRAM_SOURCE -o $TEST_PROGRAM || exit 1
 
 # Add a 1 second delay to skip samples that are not in the leaf() function
-perf record -o $PERF_DATA --call-graph fp -e cycles//u -D 1000 -- $TEST_PROGRAM 2> /dev/null &
+perf record -o $PERF_DATA --call-graph fp -e cycles//u -D 1000 --user-callchains -- $TEST_PROGRAM 2> /dev/null &
 PID=$!
 
 echo " + Recording (PID=$PID)..."
index d23a9e3..0b4f61b 100644 (file)
@@ -115,7 +115,7 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map)
         * physical_package_id will be set to -1. Hence skip this
         * test if physical_package_id returns -1 for cpu from perf_cpu_map.
         */
-       if (strncmp(session->header.env.arch, "powerpc", 7)) {
+       if (!strncmp(session->header.env.arch, "ppc64le", 7)) {
                if (cpu__get_socket_id(perf_cpu_map__cpu(map, 0)) == -1)
                        return TEST_SKIP;
        }
index 6f85f5d..17311ad 100644 (file)
@@ -50,6 +50,9 @@ struct linger {
 struct msghdr {
        void            *msg_name;      /* ptr to socket address structure */
        int             msg_namelen;    /* size of socket address structure */
+
+       int             msg_inq;        /* output, data left in socket */
+
        struct iov_iter msg_iter;       /* data */
 
        /*
@@ -62,8 +65,9 @@ struct msghdr {
                void __user     *msg_control_user;
        };
        bool            msg_control_is_user : 1;
-       __kernel_size_t msg_controllen; /* ancillary data buffer length */
+       bool            msg_get_inq : 1;/* return INQ after receive */
        unsigned int    msg_flags;      /* flags on received message */
+       __kernel_size_t msg_controllen; /* ancillary data buffer length */
        struct kiocb    *msg_iocb;      /* ptr to iocb for async requests */
 };
 
@@ -434,6 +438,7 @@ extern struct file *do_accept(struct file *file, unsigned file_flags,
 extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
                         int __user *upeer_addrlen, int flags);
 extern int __sys_socket(int family, int type, int protocol);
+extern struct file *__sys_socket_file(int family, int type, int protocol);
 extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
 extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr,
                              int addrlen, int file_flags);
index 1a80151..d040406 100644 (file)
@@ -387,26 +387,16 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq,
        return arm_spe_deliver_synth_event(spe, speq, event, &sample);
 }
 
-#define SPE_MEM_TYPE   (ARM_SPE_L1D_ACCESS | ARM_SPE_L1D_MISS | \
-                        ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS | \
-                        ARM_SPE_REMOTE_ACCESS)
-
-static bool arm_spe__is_memory_event(enum arm_spe_sample_type type)
-{
-       if (type & SPE_MEM_TYPE)
-               return true;
-
-       return false;
-}
-
 static u64 arm_spe__synth_data_source(const struct arm_spe_record *record)
 {
        union perf_mem_data_src data_src = { 0 };
 
        if (record->op == ARM_SPE_LD)
                data_src.mem_op = PERF_MEM_OP_LOAD;
-       else
+       else if (record->op == ARM_SPE_ST)
                data_src.mem_op = PERF_MEM_OP_STORE;
+       else
+               return 0;
 
        if (record->type & (ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS)) {
                data_src.mem_lvl = PERF_MEM_LVL_L3;
@@ -510,7 +500,11 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
                        return err;
        }
 
-       if (spe->sample_memory && arm_spe__is_memory_event(record->type)) {
+       /*
+        * When data_src is zero it means the record is not a memory operation,
+        * skip to synthesize memory sample for this case.
+        */
+       if (spe->sample_memory && data_src) {
                err = arm_spe__synth_mem_sample(speq, spe->memory_id, data_src);
                if (err)
                        return err;
index 0a13eb2..4dc8edb 100644 (file)
@@ -91,7 +91,7 @@ static int literal(yyscan_t scanner)
 }
 %}
 
-number         ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)
+number         ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)?
 
 sch            [-,=]
 spec           \\{sch}
index ee8fcfa..8f7baea 100644 (file)
@@ -1372,6 +1372,7 @@ static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu,
 
        *out_evlist = NULL;
        if (!metric_no_merge || hashmap__size(ids->ids) == 0) {
+               bool added_event = false;
                int i;
                /*
                 * We may fail to share events between metrics because a tool
@@ -1393,8 +1394,16 @@ static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu,
                                if (!tmp)
                                        return -ENOMEM;
                                ids__insert(ids->ids, tmp);
+                               added_event = true;
                        }
                }
+               if (!added_event && hashmap__size(ids->ids) == 0) {
+                       char *tmp = strdup("duration_time");
+
+                       if (!tmp)
+                               return -ENOMEM;
+                       ids__insert(ids->ids, tmp);
+               }
        }
        ret = metricgroup__build_event_string(&events, ids, modifier,
                                              has_constraint);
index 3762269..6e5b8cc 100644 (file)
@@ -174,7 +174,7 @@ static int elf_section_address_and_offset(int fd, const char *name, u64 *address
        Elf *elf;
        GElf_Ehdr ehdr;
        GElf_Shdr shdr;
-       int ret;
+       int ret = -1;
 
        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
        if (elf == NULL)
index 83ef55e..2974b44 100644 (file)
@@ -121,24 +121,24 @@ static void kprobe_multi_link_api_subtest(void)
 })
 
        GET_ADDR("bpf_fentry_test1", addrs[0]);
-       GET_ADDR("bpf_fentry_test2", addrs[1]);
-       GET_ADDR("bpf_fentry_test3", addrs[2]);
-       GET_ADDR("bpf_fentry_test4", addrs[3]);
-       GET_ADDR("bpf_fentry_test5", addrs[4]);
-       GET_ADDR("bpf_fentry_test6", addrs[5]);
-       GET_ADDR("bpf_fentry_test7", addrs[6]);
+       GET_ADDR("bpf_fentry_test3", addrs[1]);
+       GET_ADDR("bpf_fentry_test4", addrs[2]);
+       GET_ADDR("bpf_fentry_test5", addrs[3]);
+       GET_ADDR("bpf_fentry_test6", addrs[4]);
+       GET_ADDR("bpf_fentry_test7", addrs[5]);
+       GET_ADDR("bpf_fentry_test2", addrs[6]);
        GET_ADDR("bpf_fentry_test8", addrs[7]);
 
 #undef GET_ADDR
 
-       cookies[0] = 1;
-       cookies[1] = 2;
-       cookies[2] = 3;
-       cookies[3] = 4;
-       cookies[4] = 5;
-       cookies[5] = 6;
-       cookies[6] = 7;
-       cookies[7] = 8;
+       cookies[0] = 1; /* bpf_fentry_test1 */
+       cookies[1] = 2; /* bpf_fentry_test3 */
+       cookies[2] = 3; /* bpf_fentry_test4 */
+       cookies[3] = 4; /* bpf_fentry_test5 */
+       cookies[4] = 5; /* bpf_fentry_test6 */
+       cookies[5] = 6; /* bpf_fentry_test7 */
+       cookies[6] = 7; /* bpf_fentry_test2 */
+       cookies[7] = 8; /* bpf_fentry_test8 */
 
        opts.kprobe_multi.addrs = (const unsigned long *) &addrs;
        opts.kprobe_multi.cnt = ARRAY_SIZE(addrs);
@@ -149,14 +149,14 @@ static void kprobe_multi_link_api_subtest(void)
        if (!ASSERT_GE(link1_fd, 0, "link1_fd"))
                goto cleanup;
 
-       cookies[0] = 8;
-       cookies[1] = 7;
-       cookies[2] = 6;
-       cookies[3] = 5;
-       cookies[4] = 4;
-       cookies[5] = 3;
-       cookies[6] = 2;
-       cookies[7] = 1;
+       cookies[0] = 8; /* bpf_fentry_test1 */
+       cookies[1] = 7; /* bpf_fentry_test3 */
+       cookies[2] = 6; /* bpf_fentry_test4 */
+       cookies[3] = 5; /* bpf_fentry_test5 */
+       cookies[4] = 4; /* bpf_fentry_test6 */
+       cookies[5] = 3; /* bpf_fentry_test7 */
+       cookies[6] = 2; /* bpf_fentry_test2 */
+       cookies[7] = 1; /* bpf_fentry_test8 */
 
        opts.kprobe_multi.flags = BPF_F_KPROBE_MULTI_RETURN;
        prog_fd = bpf_program__fd(skel->progs.test_kretprobe);
@@ -181,12 +181,12 @@ static void kprobe_multi_attach_api_subtest(void)
        struct kprobe_multi *skel = NULL;
        const char *syms[8] = {
                "bpf_fentry_test1",
-               "bpf_fentry_test2",
                "bpf_fentry_test3",
                "bpf_fentry_test4",
                "bpf_fentry_test5",
                "bpf_fentry_test6",
                "bpf_fentry_test7",
+               "bpf_fentry_test2",
                "bpf_fentry_test8",
        };
        __u64 cookies[8];
@@ -198,14 +198,14 @@ static void kprobe_multi_attach_api_subtest(void)
        skel->bss->pid = getpid();
        skel->bss->test_cookie = true;
 
-       cookies[0] = 1;
-       cookies[1] = 2;
-       cookies[2] = 3;
-       cookies[3] = 4;
-       cookies[4] = 5;
-       cookies[5] = 6;
-       cookies[6] = 7;
-       cookies[7] = 8;
+       cookies[0] = 1; /* bpf_fentry_test1 */
+       cookies[1] = 2; /* bpf_fentry_test3 */
+       cookies[2] = 3; /* bpf_fentry_test4 */
+       cookies[3] = 4; /* bpf_fentry_test5 */
+       cookies[4] = 5; /* bpf_fentry_test6 */
+       cookies[5] = 6; /* bpf_fentry_test7 */
+       cookies[6] = 7; /* bpf_fentry_test2 */
+       cookies[7] = 8; /* bpf_fentry_test8 */
 
        opts.syms = syms;
        opts.cnt = ARRAY_SIZE(syms);
@@ -216,14 +216,14 @@ static void kprobe_multi_attach_api_subtest(void)
        if (!ASSERT_OK_PTR(link1, "bpf_program__attach_kprobe_multi_opts"))
                goto cleanup;
 
-       cookies[0] = 8;
-       cookies[1] = 7;
-       cookies[2] = 6;
-       cookies[3] = 5;
-       cookies[4] = 4;
-       cookies[5] = 3;
-       cookies[6] = 2;
-       cookies[7] = 1;
+       cookies[0] = 8; /* bpf_fentry_test1 */
+       cookies[1] = 7; /* bpf_fentry_test3 */
+       cookies[2] = 6; /* bpf_fentry_test4 */
+       cookies[3] = 5; /* bpf_fentry_test5 */
+       cookies[4] = 4; /* bpf_fentry_test6 */
+       cookies[5] = 3; /* bpf_fentry_test7 */
+       cookies[6] = 2; /* bpf_fentry_test2 */
+       cookies[7] = 1; /* bpf_fentry_test8 */
 
        opts.retprobe = true;
 
index 586dc52..5b93d5d 100644 (file)
@@ -364,6 +364,9 @@ static int get_syms(char ***symsp, size_t *cntp)
                        continue;
                if (!strncmp(name, "rcu_", 4))
                        continue;
+               if (!strncmp(name, "__ftrace_invalid_address__",
+                            sizeof("__ftrace_invalid_address__") - 1))
+                       continue;
                err = hashmap__add(map, name, NULL);
                if (err) {
                        free(name);
index c4da87e..19c7088 100644 (file)
@@ -831,6 +831,59 @@ out:
        bpf_object__close(obj);
 }
 
+#include "tailcall_bpf2bpf6.skel.h"
+
+/* Tail call counting works even when there is data on stack which is
+ * not aligned to 8 bytes.
+ */
+static void test_tailcall_bpf2bpf_6(void)
+{
+       struct tailcall_bpf2bpf6 *obj;
+       int err, map_fd, prog_fd, main_fd, data_fd, i, val;
+       LIBBPF_OPTS(bpf_test_run_opts, topts,
+               .data_in = &pkt_v4,
+               .data_size_in = sizeof(pkt_v4),
+               .repeat = 1,
+       );
+
+       obj = tailcall_bpf2bpf6__open_and_load();
+       if (!ASSERT_OK_PTR(obj, "open and load"))
+               return;
+
+       main_fd = bpf_program__fd(obj->progs.entry);
+       if (!ASSERT_GE(main_fd, 0, "entry prog fd"))
+               goto out;
+
+       map_fd = bpf_map__fd(obj->maps.jmp_table);
+       if (!ASSERT_GE(map_fd, 0, "jmp_table map fd"))
+               goto out;
+
+       prog_fd = bpf_program__fd(obj->progs.classifier_0);
+       if (!ASSERT_GE(prog_fd, 0, "classifier_0 prog fd"))
+               goto out;
+
+       i = 0;
+       err = bpf_map_update_elem(map_fd, &i, &prog_fd, BPF_ANY);
+       if (!ASSERT_OK(err, "jmp_table map update"))
+               goto out;
+
+       err = bpf_prog_test_run_opts(main_fd, &topts);
+       ASSERT_OK(err, "entry prog test run");
+       ASSERT_EQ(topts.retval, 0, "tailcall retval");
+
+       data_fd = bpf_map__fd(obj->maps.bss);
+       if (!ASSERT_GE(map_fd, 0, "bss map fd"))
+               goto out;
+
+       i = 0;
+       err = bpf_map_lookup_elem(data_fd, &i, &val);
+       ASSERT_OK(err, "bss map lookup");
+       ASSERT_EQ(val, 1, "done flag is set");
+
+out:
+       tailcall_bpf2bpf6__destroy(obj);
+}
+
 void test_tailcalls(void)
 {
        if (test__start_subtest("tailcall_1"))
@@ -855,4 +908,6 @@ void test_tailcalls(void)
                test_tailcall_bpf2bpf_4(false);
        if (test__start_subtest("tailcall_bpf2bpf_5"))
                test_tailcall_bpf2bpf_4(true);
+       if (test__start_subtest("tailcall_bpf2bpf_6"))
+               test_tailcall_bpf2bpf_6();
 }
index 93510f4..08f95a8 100644 (file)
@@ -54,21 +54,21 @@ static void kprobe_multi_check(void *ctx, bool is_return)
 
        if (is_return) {
                SET(kretprobe_test1_result, &bpf_fentry_test1, 8);
-               SET(kretprobe_test2_result, &bpf_fentry_test2, 7);
-               SET(kretprobe_test3_result, &bpf_fentry_test3, 6);
-               SET(kretprobe_test4_result, &bpf_fentry_test4, 5);
-               SET(kretprobe_test5_result, &bpf_fentry_test5, 4);
-               SET(kretprobe_test6_result, &bpf_fentry_test6, 3);
-               SET(kretprobe_test7_result, &bpf_fentry_test7, 2);
+               SET(kretprobe_test2_result, &bpf_fentry_test2, 2);
+               SET(kretprobe_test3_result, &bpf_fentry_test3, 7);
+               SET(kretprobe_test4_result, &bpf_fentry_test4, 6);
+               SET(kretprobe_test5_result, &bpf_fentry_test5, 5);
+               SET(kretprobe_test6_result, &bpf_fentry_test6, 4);
+               SET(kretprobe_test7_result, &bpf_fentry_test7, 3);
                SET(kretprobe_test8_result, &bpf_fentry_test8, 1);
        } else {
                SET(kprobe_test1_result, &bpf_fentry_test1, 1);
-               SET(kprobe_test2_result, &bpf_fentry_test2, 2);
-               SET(kprobe_test3_result, &bpf_fentry_test3, 3);
-               SET(kprobe_test4_result, &bpf_fentry_test4, 4);
-               SET(kprobe_test5_result, &bpf_fentry_test5, 5);
-               SET(kprobe_test6_result, &bpf_fentry_test6, 6);
-               SET(kprobe_test7_result, &bpf_fentry_test7, 7);
+               SET(kprobe_test2_result, &bpf_fentry_test2, 7);
+               SET(kprobe_test3_result, &bpf_fentry_test3, 2);
+               SET(kprobe_test4_result, &bpf_fentry_test4, 3);
+               SET(kprobe_test5_result, &bpf_fentry_test5, 4);
+               SET(kprobe_test6_result, &bpf_fentry_test6, 5);
+               SET(kprobe_test7_result, &bpf_fentry_test7, 6);
                SET(kprobe_test8_result, &bpf_fentry_test8, 8);
        }
 
diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c
new file mode 100644 (file)
index 0000000..41ce83d
--- /dev/null
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+#define __unused __attribute__((unused))
+
+struct {
+       __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
+       __uint(max_entries, 1);
+       __uint(key_size, sizeof(__u32));
+       __uint(value_size, sizeof(__u32));
+} jmp_table SEC(".maps");
+
+int done = 0;
+
+SEC("tc")
+int classifier_0(struct __sk_buff *skb __unused)
+{
+       done = 1;
+       return 0;
+}
+
+static __noinline
+int subprog_tail(struct __sk_buff *skb)
+{
+       /* Don't propagate the constant to the caller */
+       volatile int ret = 1;
+
+       bpf_tail_call_static(skb, &jmp_table, 0);
+       return ret;
+}
+
+SEC("tc")
+int entry(struct __sk_buff *skb)
+{
+       /* Have data on stack which size is not a multiple of 8 */
+       volatile char arr[1] = {};
+
+       return subprog_tail(skb);
+}
+
+char __license[] SEC("license") = "GPL";
index aa8e8b5..cd8c5ec 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS += -I../../../../usr/include/
+CFLAGS += -I../../../../include/
 
 TEST_GEN_PROGS := dma_map_benchmark
 
index c3b3c09..5c997f1 100644 (file)
@@ -10,8 +10,8 @@
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-#include <linux/map_benchmark.h>
 #include <linux/types.h>
+#include <linux/map_benchmark.h>
 
 #define NSEC_PER_MSEC  1000000L
 
index 81470a9..22423c8 100644 (file)
@@ -37,11 +37,38 @@ ifeq ($(ARCH),riscv)
        UNAME_M := riscv
 endif
 
-LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/rbtree.c lib/sparsebit.c lib/test_util.c lib/guest_modes.c lib/perf_test_util.c
-LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
-LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handlers.S lib/aarch64/spinlock.c lib/aarch64/gic.c lib/aarch64/gic_v3.c lib/aarch64/vgic.c
-LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c
-LIBKVM_riscv = lib/riscv/processor.c lib/riscv/ucall.c
+LIBKVM += lib/assert.c
+LIBKVM += lib/elf.c
+LIBKVM += lib/guest_modes.c
+LIBKVM += lib/io.c
+LIBKVM += lib/kvm_util.c
+LIBKVM += lib/perf_test_util.c
+LIBKVM += lib/rbtree.c
+LIBKVM += lib/sparsebit.c
+LIBKVM += lib/test_util.c
+
+LIBKVM_x86_64 += lib/x86_64/apic.c
+LIBKVM_x86_64 += lib/x86_64/handlers.S
+LIBKVM_x86_64 += lib/x86_64/perf_test_util.c
+LIBKVM_x86_64 += lib/x86_64/processor.c
+LIBKVM_x86_64 += lib/x86_64/svm.c
+LIBKVM_x86_64 += lib/x86_64/ucall.c
+LIBKVM_x86_64 += lib/x86_64/vmx.c
+
+LIBKVM_aarch64 += lib/aarch64/gic.c
+LIBKVM_aarch64 += lib/aarch64/gic_v3.c
+LIBKVM_aarch64 += lib/aarch64/handlers.S
+LIBKVM_aarch64 += lib/aarch64/processor.c
+LIBKVM_aarch64 += lib/aarch64/spinlock.c
+LIBKVM_aarch64 += lib/aarch64/ucall.c
+LIBKVM_aarch64 += lib/aarch64/vgic.c
+
+LIBKVM_s390x += lib/s390x/diag318_test_handler.c
+LIBKVM_s390x += lib/s390x/processor.c
+LIBKVM_s390x += lib/s390x/ucall.c
+
+LIBKVM_riscv += lib/riscv/processor.c
+LIBKVM_riscv += lib/riscv/ucall.c
 
 TEST_GEN_PROGS_x86_64 = x86_64/cpuid_test
 TEST_GEN_PROGS_x86_64 += x86_64/cr4_cpuid_sync_test
@@ -173,12 +200,13 @@ LDFLAGS += -pthread $(no-pie-option) $(pgste-option)
 # $(TEST_GEN_PROGS) starts with $(OUTPUT)/
 include ../lib.mk
 
-STATIC_LIBS := $(OUTPUT)/libkvm.a
 LIBKVM_C := $(filter %.c,$(LIBKVM))
 LIBKVM_S := $(filter %.S,$(LIBKVM))
 LIBKVM_C_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_C))
 LIBKVM_S_OBJ := $(patsubst %.S, $(OUTPUT)/%.o, $(LIBKVM_S))
-EXTRA_CLEAN += $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ) $(STATIC_LIBS) cscope.*
+LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ)
+
+EXTRA_CLEAN += $(LIBKVM_OBJS) cscope.*
 
 x := $(shell mkdir -p $(sort $(dir $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ))))
 $(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c
@@ -187,13 +215,8 @@ $(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c
 $(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S
        $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
 
-LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ)
-$(OUTPUT)/libkvm.a: $(LIBKVM_OBJS)
-       $(AR) crs $@ $^
-
 x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
-all: $(STATIC_LIBS)
-$(TEST_GEN_PROGS): $(STATIC_LIBS)
+$(TEST_GEN_PROGS): $(LIBKVM_OBJS)
 
 cscope: include_paths = $(LINUX_TOOL_INCLUDE) $(LINUX_HDR_PATH) include lib ..
 cscope:
index 7b47ae4..d60a34c 100644 (file)
@@ -336,8 +336,8 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 static void help(char *name)
 {
        puts("");
-       printf("usage: %s [-h] [-i iterations] [-p offset] [-g]"
-              "[-m mode] [-b vcpu bytes] [-v vcpus] [-o] [-s mem type]"
+       printf("usage: %s [-h] [-i iterations] [-p offset] [-g] "
+              "[-m mode] [-n] [-b vcpu bytes] [-v vcpus] [-o] [-s mem type]"
               "[-x memslots]\n", name);
        puts("");
        printf(" -i: specify iteration counts (default: %"PRIu64")\n",
@@ -351,6 +351,7 @@ static void help(char *name)
        printf(" -p: specify guest physical test memory offset\n"
               "     Warning: a low offset can conflict with the loaded test code.\n");
        guest_modes_help();
+       printf(" -n: Run the vCPUs in nested mode (L2)\n");
        printf(" -b: specify the size of the memory region which should be\n"
               "     dirtied by each vCPU. e.g. 10M or 3G.\n"
               "     (default: 1G)\n");
@@ -387,7 +388,7 @@ int main(int argc, char *argv[])
 
        guest_modes_append_default();
 
-       while ((opt = getopt(argc, argv, "ghi:p:m:b:f:v:os:x:")) != -1) {
+       while ((opt = getopt(argc, argv, "ghi:p:m:nb:f:v:os:x:")) != -1) {
                switch (opt) {
                case 'g':
                        dirty_log_manual_caps = 0;
@@ -401,6 +402,9 @@ int main(int argc, char *argv[])
                case 'm':
                        guest_modes_cmdline(optarg);
                        break;
+               case 'n':
+                       perf_test_args.nested = true;
+                       break;
                case 'b':
                        guest_percpu_mem_size = parse_size(optarg);
                        break;
index a86f953..d822cb6 100644 (file)
@@ -30,10 +30,15 @@ struct perf_test_vcpu_args {
 
 struct perf_test_args {
        struct kvm_vm *vm;
+       /* The starting address and size of the guest test region. */
        uint64_t gpa;
+       uint64_t size;
        uint64_t guest_page_size;
        int wr_fract;
 
+       /* Run vCPUs in L2 instead of L1, if the architecture supports it. */
+       bool nested;
+
        struct perf_test_vcpu_args vcpu_args[KVM_MAX_VCPUS];
 };
 
@@ -49,5 +54,9 @@ void perf_test_set_wr_fract(struct kvm_vm *vm, int wr_fract);
 
 void perf_test_start_vcpu_threads(int vcpus, void (*vcpu_fn)(struct perf_test_vcpu_args *));
 void perf_test_join_vcpu_threads(int vcpus);
+void perf_test_guest_code(uint32_t vcpu_id);
+
+uint64_t perf_test_nested_pages(int nr_vcpus);
+void perf_test_setup_nested(struct kvm_vm *vm, int nr_vcpus);
 
 #endif /* SELFTEST_KVM_PERF_TEST_UTIL_H */
index d0d51ad..6ce1854 100644 (file)
@@ -482,13 +482,23 @@ void vcpu_set_hv_cpuid(struct kvm_vm *vm, uint32_t vcpuid);
 struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vm *vm, uint32_t vcpuid);
 void vm_xsave_req_perm(int bit);
 
-enum x86_page_size {
-       X86_PAGE_SIZE_4K = 0,
-       X86_PAGE_SIZE_2M,
-       X86_PAGE_SIZE_1G,
+enum pg_level {
+       PG_LEVEL_NONE,
+       PG_LEVEL_4K,
+       PG_LEVEL_2M,
+       PG_LEVEL_1G,
+       PG_LEVEL_512G,
+       PG_LEVEL_NUM
 };
-void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
-                  enum x86_page_size page_size);
+
+#define PG_LEVEL_SHIFT(_level) ((_level - 1) * 9 + 12)
+#define PG_LEVEL_SIZE(_level) (1ull << PG_LEVEL_SHIFT(_level))
+
+#define PG_SIZE_4K PG_LEVEL_SIZE(PG_LEVEL_4K)
+#define PG_SIZE_2M PG_LEVEL_SIZE(PG_LEVEL_2M)
+#define PG_SIZE_1G PG_LEVEL_SIZE(PG_LEVEL_1G)
+
+void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level);
 
 /*
  * Basic CPU control in CR0
@@ -505,9 +515,6 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
 #define X86_CR0_CD          (1UL<<30) /* Cache Disable */
 #define X86_CR0_PG          (1UL<<31) /* Paging */
 
-/* VMX_EPT_VPID_CAP bits */
-#define VMX_EPT_VPID_CAP_AD_BITS       (1ULL << 21)
-
 #define XSTATE_XTILE_CFG_BIT           17
 #define XSTATE_XTILE_DATA_BIT          18
 
index 583ceb0..cc3604f 100644 (file)
@@ -96,6 +96,9 @@
 #define VMX_MISC_PREEMPTION_TIMER_RATE_MASK    0x0000001f
 #define VMX_MISC_SAVE_EFER_LMA                 0x00000020
 
+#define VMX_EPT_VPID_CAP_1G_PAGES              0x00020000
+#define VMX_EPT_VPID_CAP_AD_BITS               0x00200000
+
 #define EXIT_REASON_FAILED_VMENTRY     0x80000000
 #define EXIT_REASON_EXCEPTION_NMI      0
 #define EXIT_REASON_EXTERNAL_INTERRUPT 1
@@ -606,6 +609,7 @@ bool load_vmcs(struct vmx_pages *vmx);
 
 bool nested_vmx_supported(void);
 void nested_vmx_check_supported(void);
+bool ept_1g_pages_supported(void);
 
 void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
                   uint64_t nested_paddr, uint64_t paddr);
@@ -613,6 +617,8 @@ void nested_map(struct vmx_pages *vmx, struct kvm_vm *vm,
                 uint64_t nested_paddr, uint64_t paddr, uint64_t size);
 void nested_map_memslot(struct vmx_pages *vmx, struct kvm_vm *vm,
                        uint32_t memslot);
+void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm,
+                           uint64_t addr, uint64_t size);
 void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
                  uint32_t eptp_memslot);
 void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm);
index 722df3a..f989ff9 100644 (file)
@@ -40,7 +40,7 @@ static bool all_vcpu_threads_running;
  * Continuously write to the first 8 bytes of each page in the
  * specified region.
  */
-static void guest_code(uint32_t vcpu_id)
+void perf_test_guest_code(uint32_t vcpu_id)
 {
        struct perf_test_args *pta = &perf_test_args;
        struct perf_test_vcpu_args *vcpu_args = &pta->vcpu_args[vcpu_id];
@@ -108,8 +108,9 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
 {
        struct perf_test_args *pta = &perf_test_args;
        struct kvm_vm *vm;
-       uint64_t guest_num_pages;
+       uint64_t guest_num_pages, slot0_pages = DEFAULT_GUEST_PHY_PAGES;
        uint64_t backing_src_pagesz = get_backing_src_pagesz(backing_src);
+       uint64_t region_end_gfn;
        int i;
 
        pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
@@ -134,34 +135,54 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
                    "Guest memory cannot be evenly divided into %d slots.",
                    slots);
 
+       /*
+        * If using nested, allocate extra pages for the nested page tables and
+        * in-memory data structures.
+        */
+       if (pta->nested)
+               slot0_pages += perf_test_nested_pages(vcpus);
+
        /*
         * Pass guest_num_pages to populate the page tables for test memory.
         * The memory is also added to memslot 0, but that's a benign side
         * effect as KVM allows aliasing HVAs in meslots.
         */
-       vm = vm_create_with_vcpus(mode, vcpus, DEFAULT_GUEST_PHY_PAGES,
-                                 guest_num_pages, 0, guest_code, NULL);
+       vm = vm_create_with_vcpus(mode, vcpus, slot0_pages, guest_num_pages, 0,
+                                 perf_test_guest_code, NULL);
 
        pta->vm = vm;
 
+       /* Put the test region at the top guest physical memory. */
+       region_end_gfn = vm_get_max_gfn(vm) + 1;
+
+#ifdef __x86_64__
+       /*
+        * When running vCPUs in L2, restrict the test region to 48 bits to
+        * avoid needing 5-level page tables to identity map L2.
+        */
+       if (pta->nested)
+               region_end_gfn = min(region_end_gfn, (1UL << 48) / pta->guest_page_size);
+#endif
        /*
         * If there should be more memory in the guest test region than there
         * can be pages in the guest, it will definitely cause problems.
         */
-       TEST_ASSERT(guest_num_pages < vm_get_max_gfn(vm),
+       TEST_ASSERT(guest_num_pages < region_end_gfn,
                    "Requested more guest memory than address space allows.\n"
                    "    guest pages: %" PRIx64 " max gfn: %" PRIx64
                    " vcpus: %d wss: %" PRIx64 "]\n",
-                   guest_num_pages, vm_get_max_gfn(vm), vcpus,
+                   guest_num_pages, region_end_gfn - 1, vcpus,
                    vcpu_memory_bytes);
 
-       pta->gpa = (vm_get_max_gfn(vm) - guest_num_pages) * pta->guest_page_size;
+       pta->gpa = (region_end_gfn - guest_num_pages) * pta->guest_page_size;
        pta->gpa = align_down(pta->gpa, backing_src_pagesz);
 #ifdef __s390x__
        /* Align to 1M (segment size) */
        pta->gpa = align_down(pta->gpa, 1 << 20);
 #endif
-       pr_info("guest physical test memory offset: 0x%lx\n", pta->gpa);
+       pta->size = guest_num_pages * pta->guest_page_size;
+       pr_info("guest physical test memory: [0x%lx, 0x%lx)\n",
+               pta->gpa, pta->gpa + pta->size);
 
        /* Add extra memory slots for testing */
        for (i = 0; i < slots; i++) {
@@ -178,6 +199,11 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
 
        perf_test_setup_vcpus(vm, vcpus, vcpu_memory_bytes, partition_vcpu_memory_access);
 
+       if (pta->nested) {
+               pr_info("Configuring vCPUs to run in L2 (nested).\n");
+               perf_test_setup_nested(vm, vcpus);
+       }
+
        ucall_init(vm, NULL);
 
        /* Export the shared variables to the guest. */
@@ -198,6 +224,17 @@ void perf_test_set_wr_fract(struct kvm_vm *vm, int wr_fract)
        sync_global_to_guest(vm, perf_test_args);
 }
 
+uint64_t __weak perf_test_nested_pages(int nr_vcpus)
+{
+       return 0;
+}
+
+void __weak perf_test_setup_nested(struct kvm_vm *vm, int nr_vcpus)
+{
+       pr_info("%s() not support on this architecture, skipping.\n", __func__);
+       exit(KSFT_SKIP);
+}
+
 static void *vcpu_thread_main(void *data)
 {
        struct vcpu_thread *vcpu = data;
diff --git a/tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c b/tools/testing/selftests/kvm/lib/x86_64/perf_test_util.c
new file mode 100644 (file)
index 0000000..e258524
--- /dev/null
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * x86_64-specific extensions to perf_test_util.c.
+ *
+ * Copyright (C) 2022, Google, Inc.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "perf_test_util.h"
+#include "../kvm_util_internal.h"
+#include "processor.h"
+#include "vmx.h"
+
+void perf_test_l2_guest_code(uint64_t vcpu_id)
+{
+       perf_test_guest_code(vcpu_id);
+       vmcall();
+}
+
+extern char perf_test_l2_guest_entry[];
+__asm__(
+"perf_test_l2_guest_entry:"
+"      mov (%rsp), %rdi;"
+"      call perf_test_l2_guest_code;"
+"      ud2;"
+);
+
+static void perf_test_l1_guest_code(struct vmx_pages *vmx, uint64_t vcpu_id)
+{
+#define L2_GUEST_STACK_SIZE 64
+       unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+       unsigned long *rsp;
+
+       GUEST_ASSERT(vmx->vmcs_gpa);
+       GUEST_ASSERT(prepare_for_vmx_operation(vmx));
+       GUEST_ASSERT(load_vmcs(vmx));
+       GUEST_ASSERT(ept_1g_pages_supported());
+
+       rsp = &l2_guest_stack[L2_GUEST_STACK_SIZE - 1];
+       *rsp = vcpu_id;
+       prepare_vmcs(vmx, perf_test_l2_guest_entry, rsp);
+
+       GUEST_ASSERT(!vmlaunch());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+       GUEST_DONE();
+}
+
+uint64_t perf_test_nested_pages(int nr_vcpus)
+{
+       /*
+        * 513 page tables is enough to identity-map 256 TiB of L2 with 1G
+        * pages and 4-level paging, plus a few pages per-vCPU for data
+        * structures such as the VMCS.
+        */
+       return 513 + 10 * nr_vcpus;
+}
+
+void perf_test_setup_ept(struct vmx_pages *vmx, struct kvm_vm *vm)
+{
+       uint64_t start, end;
+
+       prepare_eptp(vmx, vm, 0);
+
+       /*
+        * Identity map the first 4G and the test region with 1G pages so that
+        * KVM can shadow the EPT12 with the maximum huge page size supported
+        * by the backing source.
+        */
+       nested_identity_map_1g(vmx, vm, 0, 0x100000000ULL);
+
+       start = align_down(perf_test_args.gpa, PG_SIZE_1G);
+       end = align_up(perf_test_args.gpa + perf_test_args.size, PG_SIZE_1G);
+       nested_identity_map_1g(vmx, vm, start, end - start);
+}
+
+void perf_test_setup_nested(struct kvm_vm *vm, int nr_vcpus)
+{
+       struct vmx_pages *vmx, *vmx0 = NULL;
+       struct kvm_regs regs;
+       vm_vaddr_t vmx_gva;
+       int vcpu_id;
+
+       nested_vmx_check_supported();
+
+       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
+               vmx = vcpu_alloc_vmx(vm, &vmx_gva);
+
+               if (vcpu_id == 0) {
+                       perf_test_setup_ept(vmx, vm);
+                       vmx0 = vmx;
+               } else {
+                       /* Share the same EPT table across all vCPUs. */
+                       vmx->eptp = vmx0->eptp;
+                       vmx->eptp_hva = vmx0->eptp_hva;
+                       vmx->eptp_gpa = vmx0->eptp_gpa;
+               }
+
+               /*
+                * Override the vCPU to run perf_test_l1_guest_code() which will
+                * bounce it into L2 before calling perf_test_guest_code().
+                */
+               vcpu_regs_get(vm, vcpu_id, &regs);
+               regs.rip = (unsigned long) perf_test_l1_guest_code;
+               vcpu_regs_set(vm, vcpu_id, &regs);
+               vcpu_args_set(vm, vcpu_id, 2, vmx_gva, vcpu_id);
+       }
+}
index 33ea5e9..ead7011 100644 (file)
@@ -158,7 +158,7 @@ static void *virt_get_pte(struct kvm_vm *vm, uint64_t pt_pfn, uint64_t vaddr,
                          int level)
 {
        uint64_t *page_table = addr_gpa2hva(vm, pt_pfn << vm->page_shift);
-       int index = vaddr >> (vm->page_shift + level * 9) & 0x1ffu;
+       int index = (vaddr >> PG_LEVEL_SHIFT(level)) & 0x1ffu;
 
        return &page_table[index];
 }
@@ -167,14 +167,14 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *vm,
                                       uint64_t pt_pfn,
                                       uint64_t vaddr,
                                       uint64_t paddr,
-                                      int level,
-                                      enum x86_page_size page_size)
+                                      int current_level,
+                                      int target_level)
 {
-       uint64_t *pte = virt_get_pte(vm, pt_pfn, vaddr, level);
+       uint64_t *pte = virt_get_pte(vm, pt_pfn, vaddr, current_level);
 
        if (!(*pte & PTE_PRESENT_MASK)) {
                *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK;
-               if (level == page_size)
+               if (current_level == target_level)
                        *pte |= PTE_LARGE_MASK | (paddr & PHYSICAL_PAGE_MASK);
                else
                        *pte |= vm_alloc_page_table(vm) & PHYSICAL_PAGE_MASK;
@@ -184,20 +184,19 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *vm,
                 * a hugepage at this level, and that there isn't a hugepage at
                 * this level.
                 */
-               TEST_ASSERT(level != page_size,
+               TEST_ASSERT(current_level != target_level,
                            "Cannot create hugepage at level: %u, vaddr: 0x%lx\n",
-                           page_size, vaddr);
+                           current_level, vaddr);
                TEST_ASSERT(!(*pte & PTE_LARGE_MASK),
                            "Cannot create page table at level: %u, vaddr: 0x%lx\n",
-                           level, vaddr);
+                           current_level, vaddr);
        }
        return pte;
 }
 
-void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
-                  enum x86_page_size page_size)
+void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level)
 {
-       const uint64_t pg_size = 1ull << ((page_size * 9) + 12);
+       const uint64_t pg_size = PG_LEVEL_SIZE(level);
        uint64_t *pml4e, *pdpe, *pde;
        uint64_t *pte;
 
@@ -222,20 +221,20 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
         * early if a hugepage was created.
         */
        pml4e = virt_create_upper_pte(vm, vm->pgd >> vm->page_shift,
-                                     vaddr, paddr, 3, page_size);
+                                     vaddr, paddr, PG_LEVEL_512G, level);
        if (*pml4e & PTE_LARGE_MASK)
                return;
 
-       pdpe = virt_create_upper_pte(vm, PTE_GET_PFN(*pml4e), vaddr, paddr, 2, page_size);
+       pdpe = virt_create_upper_pte(vm, PTE_GET_PFN(*pml4e), vaddr, paddr, PG_LEVEL_1G, level);
        if (*pdpe & PTE_LARGE_MASK)
                return;
 
-       pde = virt_create_upper_pte(vm, PTE_GET_PFN(*pdpe), vaddr, paddr, 1, page_size);
+       pde = virt_create_upper_pte(vm, PTE_GET_PFN(*pdpe), vaddr, paddr, PG_LEVEL_2M, level);
        if (*pde & PTE_LARGE_MASK)
                return;
 
        /* Fill in page table entry. */
-       pte = virt_get_pte(vm, PTE_GET_PFN(*pde), vaddr, 0);
+       pte = virt_get_pte(vm, PTE_GET_PFN(*pde), vaddr, PG_LEVEL_4K);
        TEST_ASSERT(!(*pte & PTE_PRESENT_MASK),
                    "PTE already present for 4k page at vaddr: 0x%lx\n", vaddr);
        *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK);
@@ -243,7 +242,7 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
 
 void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
 {
-       __virt_pg_map(vm, vaddr, paddr, X86_PAGE_SIZE_4K);
+       __virt_pg_map(vm, vaddr, paddr, PG_LEVEL_4K);
 }
 
 static uint64_t *_vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid,
index d089d8b..b77a01d 100644 (file)
@@ -198,6 +198,16 @@ bool load_vmcs(struct vmx_pages *vmx)
        return true;
 }
 
+static bool ept_vpid_cap_supported(uint64_t mask)
+{
+       return rdmsr(MSR_IA32_VMX_EPT_VPID_CAP) & mask;
+}
+
+bool ept_1g_pages_supported(void)
+{
+       return ept_vpid_cap_supported(VMX_EPT_VPID_CAP_1G_PAGES);
+}
+
 /*
  * Initialize the control fields to the most basic settings possible.
  */
@@ -215,7 +225,7 @@ static inline void init_vmcs_control_fields(struct vmx_pages *vmx)
                struct eptPageTablePointer eptp = {
                        .memory_type = VMX_BASIC_MEM_TYPE_WB,
                        .page_walk_length = 3, /* + 1 */
-                       .ad_enabled = !!(rdmsr(MSR_IA32_VMX_EPT_VPID_CAP) & VMX_EPT_VPID_CAP_AD_BITS),
+                       .ad_enabled = ept_vpid_cap_supported(VMX_EPT_VPID_CAP_AD_BITS),
                        .address = vmx->eptp_gpa >> PAGE_SHIFT_4K,
                };
 
@@ -392,80 +402,93 @@ void nested_vmx_check_supported(void)
        }
 }
 
-void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
-                  uint64_t nested_paddr, uint64_t paddr)
+static void nested_create_pte(struct kvm_vm *vm,
+                             struct eptPageTableEntry *pte,
+                             uint64_t nested_paddr,
+                             uint64_t paddr,
+                             int current_level,
+                             int target_level)
+{
+       if (!pte->readable) {
+               pte->writable = true;
+               pte->readable = true;
+               pte->executable = true;
+               pte->page_size = (current_level == target_level);
+               if (pte->page_size)
+                       pte->address = paddr >> vm->page_shift;
+               else
+                       pte->address = vm_alloc_page_table(vm) >> vm->page_shift;
+       } else {
+               /*
+                * Entry already present.  Assert that the caller doesn't want
+                * a hugepage at this level, and that there isn't a hugepage at
+                * this level.
+                */
+               TEST_ASSERT(current_level != target_level,
+                           "Cannot create hugepage at level: %u, nested_paddr: 0x%lx\n",
+                           current_level, nested_paddr);
+               TEST_ASSERT(!pte->page_size,
+                           "Cannot create page table at level: %u, nested_paddr: 0x%lx\n",
+                           current_level, nested_paddr);
+       }
+}
+
+
+void __nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
+                    uint64_t nested_paddr, uint64_t paddr, int target_level)
 {
-       uint16_t index[4];
-       struct eptPageTableEntry *pml4e;
+       const uint64_t page_size = PG_LEVEL_SIZE(target_level);
+       struct eptPageTableEntry *pt = vmx->eptp_hva, *pte;
+       uint16_t index;
 
        TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
                    "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
 
-       TEST_ASSERT((nested_paddr % vm->page_size) == 0,
+       TEST_ASSERT((nested_paddr >> 48) == 0,
+                   "Nested physical address 0x%lx requires 5-level paging",
+                   nested_paddr);
+       TEST_ASSERT((nested_paddr % page_size) == 0,
                    "Nested physical address not on page boundary,\n"
-                   "  nested_paddr: 0x%lx vm->page_size: 0x%x",
-                   nested_paddr, vm->page_size);
+                   "  nested_paddr: 0x%lx page_size: 0x%lx",
+                   nested_paddr, page_size);
        TEST_ASSERT((nested_paddr >> vm->page_shift) <= vm->max_gfn,
                    "Physical address beyond beyond maximum supported,\n"
                    "  nested_paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
                    paddr, vm->max_gfn, vm->page_size);
-       TEST_ASSERT((paddr % vm->page_size) == 0,
+       TEST_ASSERT((paddr % page_size) == 0,
                    "Physical address not on page boundary,\n"
-                   "  paddr: 0x%lx vm->page_size: 0x%x",
-                   paddr, vm->page_size);
+                   "  paddr: 0x%lx page_size: 0x%lx",
+                   paddr, page_size);
        TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
                    "Physical address beyond beyond maximum supported,\n"
                    "  paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
                    paddr, vm->max_gfn, vm->page_size);
 
-       index[0] = (nested_paddr >> 12) & 0x1ffu;
-       index[1] = (nested_paddr >> 21) & 0x1ffu;
-       index[2] = (nested_paddr >> 30) & 0x1ffu;
-       index[3] = (nested_paddr >> 39) & 0x1ffu;
-
-       /* Allocate page directory pointer table if not present. */
-       pml4e = vmx->eptp_hva;
-       if (!pml4e[index[3]].readable) {
-               pml4e[index[3]].address = vm_alloc_page_table(vm) >> vm->page_shift;
-               pml4e[index[3]].writable = true;
-               pml4e[index[3]].readable = true;
-               pml4e[index[3]].executable = true;
-       }
+       for (int level = PG_LEVEL_512G; level >= PG_LEVEL_4K; level--) {
+               index = (nested_paddr >> PG_LEVEL_SHIFT(level)) & 0x1ffu;
+               pte = &pt[index];
 
-       /* Allocate page directory table if not present. */
-       struct eptPageTableEntry *pdpe;
-       pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
-       if (!pdpe[index[2]].readable) {
-               pdpe[index[2]].address = vm_alloc_page_table(vm) >> vm->page_shift;
-               pdpe[index[2]].writable = true;
-               pdpe[index[2]].readable = true;
-               pdpe[index[2]].executable = true;
-       }
+               nested_create_pte(vm, pte, nested_paddr, paddr, level, target_level);
 
-       /* Allocate page table if not present. */
-       struct eptPageTableEntry *pde;
-       pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
-       if (!pde[index[1]].readable) {
-               pde[index[1]].address = vm_alloc_page_table(vm) >> vm->page_shift;
-               pde[index[1]].writable = true;
-               pde[index[1]].readable = true;
-               pde[index[1]].executable = true;
-       }
+               if (pte->page_size)
+                       break;
 
-       /* Fill in page table entry. */
-       struct eptPageTableEntry *pte;
-       pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
-       pte[index[0]].address = paddr >> vm->page_shift;
-       pte[index[0]].writable = true;
-       pte[index[0]].readable = true;
-       pte[index[0]].executable = true;
+               pt = addr_gpa2hva(vm, pte->address * vm->page_size);
+       }
 
        /*
         * For now mark these as accessed and dirty because the only
         * testcase we have needs that.  Can be reconsidered later.
         */
-       pte[index[0]].accessed = true;
-       pte[index[0]].dirty = true;
+       pte->accessed = true;
+       pte->dirty = true;
+
+}
+
+void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
+                  uint64_t nested_paddr, uint64_t paddr)
+{
+       __nested_pg_map(vmx, vm, nested_paddr, paddr, PG_LEVEL_4K);
 }
 
 /*
@@ -476,7 +499,7 @@ void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
  *   nested_paddr - Nested guest physical address to map
  *   paddr - VM Physical Address
  *   size - The size of the range to map
- *   eptp_memslot - Memory region slot for new virtual translation tables
+ *   level - The level at which to map the range
  *
  * Output Args: None
  *
@@ -485,22 +508,29 @@ void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
  * Within the VM given by vm, creates a nested guest translation for the
  * page range starting at nested_paddr to the page range starting at paddr.
  */
-void nested_map(struct vmx_pages *vmx, struct kvm_vm *vm,
-               uint64_t nested_paddr, uint64_t paddr, uint64_t size)
+void __nested_map(struct vmx_pages *vmx, struct kvm_vm *vm,
+                 uint64_t nested_paddr, uint64_t paddr, uint64_t size,
+                 int level)
 {
-       size_t page_size = vm->page_size;
+       size_t page_size = PG_LEVEL_SIZE(level);
        size_t npages = size / page_size;
 
        TEST_ASSERT(nested_paddr + size > nested_paddr, "Vaddr overflow");
        TEST_ASSERT(paddr + size > paddr, "Paddr overflow");
 
        while (npages--) {
-               nested_pg_map(vmx, vm, nested_paddr, paddr);
+               __nested_pg_map(vmx, vm, nested_paddr, paddr, level);
                nested_paddr += page_size;
                paddr += page_size;
        }
 }
 
+void nested_map(struct vmx_pages *vmx, struct kvm_vm *vm,
+               uint64_t nested_paddr, uint64_t paddr, uint64_t size)
+{
+       __nested_map(vmx, vm, nested_paddr, paddr, size, PG_LEVEL_4K);
+}
+
 /* Prepare an identity extended page table that maps all the
  * physical pages in VM.
  */
@@ -525,6 +555,13 @@ void nested_map_memslot(struct vmx_pages *vmx, struct kvm_vm *vm,
        }
 }
 
+/* Identity map a region with 1GiB Pages. */
+void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm,
+                           uint64_t addr, uint64_t size)
+{
+       __nested_map(vmx, vm, addr, addr, size, PG_LEVEL_1G);
+}
+
 void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
                  uint32_t eptp_memslot)
 {
index 3875c4b..15f046e 100644 (file)
@@ -244,7 +244,7 @@ int main(int argc, char *argv[])
 #ifdef __x86_64__
                /* Identity map memory in the guest using 1gb pages. */
                for (i = 0; i < slot_size; i += size_1gb)
-                       __virt_pg_map(vm, gpa + i, gpa + i, X86_PAGE_SIZE_1G);
+                       __virt_pg_map(vm, gpa + i, gpa + i, PG_LEVEL_1G);
 #else
                for (i = 0; i < slot_size; i += vm_get_page_size(vm))
                        virt_pg_map(vm, gpa + i, gpa + i);
index da2325f..bdecd53 100644 (file)
@@ -35,7 +35,7 @@ static void mmu_role_test(u32 *cpuid_reg, u32 evil_cpuid_val)
        run = vcpu_state(vm, VCPU_ID);
 
        /* Map 1gb page without a backing memlot. */
-       __virt_pg_map(vm, MMIO_GPA, MMIO_GPA, X86_PAGE_SIZE_1G);
+       __virt_pg_map(vm, MMIO_GPA, MMIO_GPA, PG_LEVEL_1G);
 
        r = _vcpu_run(vm, VCPU_ID);
 
index 2a2d240..1a5cc3c 100644 (file)
@@ -7,10 +7,31 @@ else ifneq ($(filter -%,$(LLVM)),)
 LLVM_SUFFIX := $(LLVM)
 endif
 
-CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
+CLANG_TARGET_FLAGS_arm          := arm-linux-gnueabi
+CLANG_TARGET_FLAGS_arm64        := aarch64-linux-gnu
+CLANG_TARGET_FLAGS_hexagon      := hexagon-linux-musl
+CLANG_TARGET_FLAGS_m68k         := m68k-linux-gnu
+CLANG_TARGET_FLAGS_mips         := mipsel-linux-gnu
+CLANG_TARGET_FLAGS_powerpc      := powerpc64le-linux-gnu
+CLANG_TARGET_FLAGS_riscv        := riscv64-linux-gnu
+CLANG_TARGET_FLAGS_s390         := s390x-linux-gnu
+CLANG_TARGET_FLAGS_x86          := x86_64-linux-gnu
+CLANG_TARGET_FLAGS              := $(CLANG_TARGET_FLAGS_$(ARCH))
+
+ifeq ($(CROSS_COMPILE),)
+ifeq ($(CLANG_TARGET_FLAGS),)
+$(error Specify CROSS_COMPILE or add '--target=' option to lib.mk
+else
+CLANG_FLAGS     += --target=$(CLANG_TARGET_FLAGS)
+endif # CLANG_TARGET_FLAGS
+else
+CLANG_FLAGS     += --target=$(notdir $(CROSS_COMPILE:%-=%))
+endif # CROSS_COMPILE
+
+CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as
 else
 CC := $(CROSS_COMPILE)gcc
-endif
+endif # LLVM
 
 ifeq (0,$(MAKELEVEL))
     ifeq ($(OUTPUT),)
index b984f8c..a29f796 100644 (file)
@@ -37,4 +37,3 @@ gro
 ioam6_parser
 toeplitz
 cmsg_sender
-bind_bhash_test
index 464df13..7ea54af 100644 (file)
@@ -59,7 +59,6 @@ TEST_GEN_FILES += toeplitz
 TEST_GEN_FILES += cmsg_sender
 TEST_GEN_FILES += stress_reuseport_listen
 TEST_PROGS += test_vxlan_vnifiltering.sh
-TEST_GEN_FILES += bind_bhash_test
 
 TEST_FILES := settings
 
@@ -70,5 +69,4 @@ include bpf/Makefile
 
 $(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
 $(OUTPUT)/tcp_mmap: LDLIBS += -lpthread
-$(OUTPUT)/bind_bhash_test: LDLIBS += -lpthread
 $(OUTPUT)/tcp_inq: LDLIBS += -lpthread
diff --git a/tools/testing/selftests/net/bind_bhash_test.c b/tools/testing/selftests/net/bind_bhash_test.c
deleted file mode 100644 (file)
index 252e737..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This times how long it takes to bind to a port when the port already
- * has multiple sockets in its bhash table.
- *
- * In the setup(), we populate the port's bhash table with
- * MAX_THREADS * MAX_CONNECTIONS number of entries.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <netdb.h>
-#include <pthread.h>
-
-#define MAX_THREADS 600
-#define MAX_CONNECTIONS 40
-
-static const char *bind_addr = "::1";
-static const char *port;
-
-static int fd_array[MAX_THREADS][MAX_CONNECTIONS];
-
-static int bind_socket(int opt, const char *addr)
-{
-       struct addrinfo *res, hint = {};
-       int sock_fd, reuse = 1, err;
-
-       sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
-       if (sock_fd < 0) {
-               perror("socket fd err");
-               return -1;
-       }
-
-       hint.ai_family = AF_INET6;
-       hint.ai_socktype = SOCK_STREAM;
-
-       err = getaddrinfo(addr, port, &hint, &res);
-       if (err) {
-               perror("getaddrinfo failed");
-               return -1;
-       }
-
-       if (opt) {
-               err = setsockopt(sock_fd, SOL_SOCKET, opt, &reuse, sizeof(reuse));
-               if (err) {
-                       perror("setsockopt failed");
-                       return -1;
-               }
-       }
-
-       err = bind(sock_fd, res->ai_addr, res->ai_addrlen);
-       if (err) {
-               perror("failed to bind to port");
-               return -1;
-       }
-
-       return sock_fd;
-}
-
-static void *setup(void *arg)
-{
-       int sock_fd, i;
-       int *array = (int *)arg;
-
-       for (i = 0; i < MAX_CONNECTIONS; i++) {
-               sock_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, bind_addr);
-               if (sock_fd < 0)
-                       return NULL;
-               array[i] = sock_fd;
-       }
-
-       return NULL;
-}
-
-int main(int argc, const char *argv[])
-{
-       int listener_fd, sock_fd, i, j;
-       pthread_t tid[MAX_THREADS];
-       clock_t begin, end;
-
-       if (argc != 2) {
-               printf("Usage: listener <port>\n");
-               return -1;
-       }
-
-       port = argv[1];
-
-       listener_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, bind_addr);
-       if (listen(listener_fd, 100) < 0) {
-               perror("listen failed");
-               return -1;
-       }
-
-       /* Set up threads to populate the bhash table entry for the port */
-       for (i = 0; i < MAX_THREADS; i++)
-               pthread_create(&tid[i], NULL, setup, fd_array[i]);
-
-       for (i = 0; i < MAX_THREADS; i++)
-               pthread_join(tid[i], NULL);
-
-       begin = clock();
-
-       /* Bind to the same port on a different address */
-       sock_fd  = bind_socket(0, "2001:0db8:0:f101::1");
-
-       end = clock();
-
-       printf("time spent = %f\n", (double)(end - begin) / CLOCKS_PER_SEC);
-
-       /* clean up */
-       close(sock_fd);
-       close(listener_fd);
-       for (i = 0; i < MAX_THREADS; i++) {
-               for (j = 0; i < MAX_THREADS; i++)
-                       close(fd_array[i][j]);
-       }
-
-       return 0;
-}
index 54701c8..03b5867 100755 (executable)
@@ -70,6 +70,10 @@ NSB_LO_IP6=2001:db8:2::2
 NL_IP=172.17.1.1
 NL_IP6=2001:db8:4::1
 
+# multicast and broadcast addresses
+MCAST_IP=224.0.0.1
+BCAST_IP=255.255.255.255
+
 MD5_PW=abc123
 MD5_WRONG_PW=abc1234
 
@@ -308,6 +312,9 @@ addr2str()
        127.0.0.1) echo "loopback";;
        ::1) echo "IPv6 loopback";;
 
+       ${BCAST_IP}) echo "broadcast";;
+       ${MCAST_IP}) echo "multicast";;
+
        ${NSA_IP})      echo "ns-A IP";;
        ${NSA_IP6})     echo "ns-A IPv6";;
        ${NSA_LO_IP})   echo "ns-A loopback IP";;
@@ -1793,12 +1800,33 @@ ipv4_addr_bind_novrf()
        done
 
        #
-       # raw socket with nonlocal bind
+       # tests for nonlocal bind
        #
        a=${NL_IP}
        log_start
-       run_cmd nettest -s -R -P icmp -f -l ${a} -I ${NSA_DEV} -b
-       log_test_addr ${a} $? 0 "Raw socket bind to nonlocal address after device bind"
+       run_cmd nettest -s -R -f -l ${a} -b
+       log_test_addr ${a} $? 0 "Raw socket bind to nonlocal address"
+
+       log_start
+       run_cmd nettest -s -f -l ${a} -b
+       log_test_addr ${a} $? 0 "TCP socket bind to nonlocal address"
+
+       log_start
+       run_cmd nettest -s -D -P icmp -f -l ${a} -b
+       log_test_addr ${a} $? 0 "ICMP socket bind to nonlocal address"
+
+       #
+       # check that ICMP sockets cannot bind to broadcast and multicast addresses
+       #
+       a=${BCAST_IP}
+       log_start
+       run_cmd nettest -s -D -P icmp -l ${a} -b
+       log_test_addr ${a} $? 1 "ICMP socket bind to broadcast address"
+
+       a=${MCAST_IP}
+       log_start
+       run_cmd nettest -s -D -P icmp -l ${a} -b
+       log_test_addr ${a} $? 1 "ICMP socket bind to multicast address"
 
        #
        # tcp sockets
@@ -1850,13 +1878,34 @@ ipv4_addr_bind_vrf()
        log_test_addr ${a} $? 1 "Raw socket bind to out of scope address after VRF bind"
 
        #
-       # raw socket with nonlocal bind
+       # tests for nonlocal bind
        #
        a=${NL_IP}
        log_start
-       run_cmd nettest -s -R -P icmp -f -l ${a} -I ${VRF} -b
+       run_cmd nettest -s -R -f -l ${a} -I ${VRF} -b
        log_test_addr ${a} $? 0 "Raw socket bind to nonlocal address after VRF bind"
 
+       log_start
+       run_cmd nettest -s -f -l ${a} -I ${VRF} -b
+       log_test_addr ${a} $? 0 "TCP socket bind to nonlocal address after VRF bind"
+
+       log_start
+       run_cmd nettest -s -D -P icmp -f -l ${a} -I ${VRF} -b
+       log_test_addr ${a} $? 0 "ICMP socket bind to nonlocal address after VRF bind"
+
+       #
+       # check that ICMP sockets cannot bind to broadcast and multicast addresses
+       #
+       a=${BCAST_IP}
+       log_start
+       run_cmd nettest -s -D -P icmp -l ${a} -I ${VRF} -b
+       log_test_addr ${a} $? 1 "ICMP socket bind to broadcast address after VRF bind"
+
+       a=${MCAST_IP}
+       log_start
+       run_cmd nettest -s -D -P icmp -l ${a} -I ${VRF} -b
+       log_test_addr ${a} $? 1 "ICMP socket bind to multicast address after VRF bind"
+
        #
        # tcp sockets
        #
@@ -1889,10 +1938,12 @@ ipv4_addr_bind()
 
        log_subsection "No VRF"
        setup
+       set_sysctl net.ipv4.ping_group_range='0 2147483647' 2>/dev/null
        ipv4_addr_bind_novrf
 
        log_subsection "With VRF"
        setup "yes"
+       set_sysctl net.ipv4.ping_group_range='0 2147483647' 2>/dev/null
        ipv4_addr_bind_vrf
 }
 
index b35010c..a699187 100755 (executable)
@@ -31,7 +31,7 @@ BUGS="flush_remove_add reload"
 
 # List of possible paths to pktgen script from kernel tree for performance tests
 PKTGEN_SCRIPT_PATHS="
-       ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
+       ../../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
        pktgen/pktgen_bench_xmit_mode_netif_receive.sh"
 
 # Definition of set types:
index 6bb36ca..a309876 100644 (file)
@@ -209,7 +209,7 @@ int main(int argc, char **argv)
        if (write)
                gup.gup_flags |= FOLL_WRITE;
 
-       gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR);
+       gup_fd = open(GUP_TEST_FILE, O_RDWR);
        if (gup_fd == -1) {
                switch (errno) {
                case EACCES:
@@ -224,7 +224,7 @@ int main(int argc, char **argv)
                        printf("check if CONFIG_GUP_TEST is enabled in kernel config\n");
                        break;
                default:
-                       perror("failed to open /sys/kernel/debug/gup_test");
+                       perror("failed to open " GUP_TEST_FILE);
                        break;
                }
                exit(KSFT_SKIP);
index 2fcf243..f5e4e0b 100644 (file)
@@ -54,6 +54,7 @@ static int ksm_write_sysfs(const char *file_path, unsigned long val)
        }
        if (fprintf(f, "%lu", val) < 0) {
                perror("fprintf");
+               fclose(f);
                return 1;
        }
        fclose(f);
@@ -72,6 +73,7 @@ static int ksm_read_sysfs(const char *file_path, unsigned long *val)
        }
        if (fscanf(f, "%lu", val) != 1) {
                perror("fscanf");
+               fclose(f);
                return 1;
        }
        fclose(f);
index 44c4767..a49df89 100644 (file)
@@ -3328,9 +3328,11 @@ bool kvm_vcpu_block(struct kvm_vcpu *vcpu)
 
        vcpu->stat.generic.blocking = 1;
 
+       preempt_disable();
        kvm_arch_vcpu_blocking(vcpu);
-
        prepare_to_rcuwait(wait);
+       preempt_enable();
+
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
 
@@ -3340,9 +3342,11 @@ bool kvm_vcpu_block(struct kvm_vcpu *vcpu)
                waited = true;
                schedule();
        }
-       finish_rcuwait(wait);
 
+       preempt_disable();
+       finish_rcuwait(wait);
        kvm_arch_vcpu_unblocking(vcpu);
+       preempt_enable();
 
        vcpu->stat.generic.blocking = 0;