Merge tag 'hwmon-for-v5.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groec...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Mar 2020 20:47:06 +0000 (14:47 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Mar 2020 20:47:06 +0000 (14:47 -0600)
Pull hwmon fixes from Guenter Roeck:
 "Fix an error return in the adt7462 driver, bad voltage limits reported
  by the xdpe12284 driver, and a broken documentation reference in the
  adm1177 driver documentation"

* tag 'hwmon-for-v5.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (adt7462) Fix an error return in ADT7462_REG_VOLT()
  hwmon: (pmbus/xdpe12284) Add callback for vout limits conversion
  docs: adm1177: fix a broken reference

334 files changed:
.gitignore
CREDITS
Documentation/admin-guide/acpi/fan_performance_states.rst
Documentation/admin-guide/bootconfig.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/dev-tools/kunit/usage.rst
Documentation/driver-api/dmaengine/client.rst
Documentation/kbuild/makefiles.rst
Documentation/networking/phy.rst
Documentation/power/index.rst
Documentation/sphinx/parallel-wrapper.sh
Documentation/virt/kvm/api.rst
Documentation/x86/index.rst
MAINTAINERS
Makefile
arch/Kconfig
arch/arm/include/asm/kvm_host.h
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/virt.h
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c
arch/arm64/mm/context.c
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/ingenic/jz4780.dtsi
arch/mips/boot/dts/ingenic/x1000.dtsi
arch/mips/include/asm/sync.h
arch/mips/kernel/vpe.c
arch/mips/vdso/Makefile
arch/riscv/boot/.gitignore
arch/riscv/include/asm/csr.h
arch/riscv/kernel/head.S
arch/riscv/kernel/traps.c
arch/riscv/mm/kasan_init.c
arch/x86/include/asm/io_bitmap.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/vmx.h
arch/x86/include/asm/vmxfeatures.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/kvm.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/process.c
arch/x86/kvm/Kconfig
arch/x86/kvm/Makefile
arch/x86/kvm/emulate.c
arch/x86/kvm/irq_comm.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmutrace.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/capabilities.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/nested.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/mm/dump_pagetables.c
arch/x86/platform/efi/efi_64.c
arch/x86/xen/enlighten_pv.c
block/blk-flush.c
block/blk-mq-sched.c
block/blk-mq-tag.c
block/blk-mq-tag.h
block/blk-mq.c
block/blk-mq.h
drivers/acpi/acpi_watchdog.c
drivers/base/swnode.c
drivers/block/floppy.c
drivers/block/null_blk.h
drivers/block/null_blk_main.c
drivers/block/paride/pcd.c
drivers/cdrom/gdrom.c
drivers/cpufreq/cpufreq.c
drivers/devfreq/devfreq.c
drivers/dma-buf/dma-buf.c
drivers/dma/coh901318.c
drivers/dma/idxd/cdev.c
drivers/dma/idxd/sysfs.c
drivers/dma/imx-sdma.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/ti/k3-udma.c
drivers/firmware/efi/efi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/amd/powerplay/smu_v12_0.c
drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/display/intel_psr.h
drivers/gpu/drm/i915/gem/i915_gem_object.c
drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
drivers/gpu/drm/i915/gt/intel_gt_requests.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_perf_types.h
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_mixer.h
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/hid/hid-alps.c
drivers/hid/hid-apple.c
drivers/hid/hid-bigbenff.c
drivers/hid/hid-core.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ite.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/i2c/busses/i2c-altera.c
drivers/i2c/busses/i2c-jz4780.c
drivers/ide/ide-gd.c
drivers/macintosh/therm_windtunnel.c
drivers/md/dm-bio-record.h
drivers/md/dm-cache-target.c
drivers/md/dm-integrity.c
drivers/md/dm-mpath.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-verity-target.c
drivers/md/dm-writecache.c
drivers/md/dm-zoned-target.c
drivers/md/dm.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
drivers/net/ethernet/huawei/hinic/hinic_main.c
drivers/net/ethernet/huawei/hinic/hinic_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag.h
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/xilinx/ll_temac.h
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/marvell.c
drivers/net/phy/mscc.c
drivers/net/phy/phy-c45.c
drivers/net/phy/phy_device.c
drivers/net/slip/slip.c
drivers/net/usb/qmi_wwan.c
drivers/nvme/host/pci.c
drivers/pci/controller/pcie-brcmstb.c
drivers/perf/arm_pmu_acpi.c
drivers/perf/fsl_imx8_ddr_perf.c
drivers/platform/chrome/wilco_ec/properties.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/libfc/fc_disc.c
drivers/scsi/sd_zbc.c
drivers/scsi/sr.c
drivers/tee/amdtee/Kconfig
drivers/vhost/net.c
drivers/watchdog/wdat_wdt.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb1ops.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/ext4/super.c
fs/fat/inode.c
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/jbd2/transaction.c
fs/zonefs/Kconfig
fs/zonefs/super.c
include/acpi/actypes.h
include/drm/drm_gem_shmem_helper.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/bootconfig.h
include/linux/hid.h
include/linux/icmpv6.h
include/linux/kvm_host.h
include/linux/mm.h
include/linux/netfilter/ipset/ip_set.h
include/uapi/linux/dm-ioctl.h
init/Kconfig
init/main.c
kernel/audit.c
kernel/auditfilter.c
kernel/power/snapshot.c
kernel/sched/fair.c
kernel/signal.c
kernel/trace/Kconfig
kernel/trace/blktrace.c
kernel/trace/synth_event_gen_test.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
lib/bootconfig.c
lib/crypto/chacha20poly1305.c
mm/huge_memory.c
mm/memory.c
mm/memory_hotplug.c
mm/mprotect.c
mm/shmem.c
mm/z3fold.c
net/bridge/br_device.c
net/core/dev.c
net/core/devlink.c
net/ethtool/bitset.c
net/ethtool/bitset.h
net/ipv4/cipso_ipv4.c
net/ipv4/tcp_input.c
net/ipv6/ipv6_sockglue.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mptcp/protocol.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/nft_set_pipapo.c
net/netfilter/xt_hashlimit.c
net/netlink/genetlink.c
net/sched/act_api.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/hyperv_transport.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/nl80211.c
net/wireless/reg.c
scripts/Makefile.lib
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/bootconfig/include/linux/printk.h
tools/bootconfig/main.c
tools/bootconfig/samples/bad-mixed-kv1.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-mixed-kv2.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-samekey.bconf [new file with mode: 0644]
tools/bootconfig/test-bootconfig.sh
tools/perf/Documentation/perf-config.txt
tools/perf/arch/arm/util/cs-etm.c
tools/perf/arch/arm64/util/arm-spe.c
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
tools/perf/arch/x86/util/intel-bts.c
tools/perf/arch/x86/util/intel-pt.c
tools/perf/builtin-annotate.c
tools/perf/builtin-probe.c
tools/perf/builtin-report.c
tools/perf/builtin-top.c
tools/perf/include/bpf/pid_filter.h
tools/perf/include/bpf/stdio.h
tools/perf/include/bpf/unistd.h
tools/perf/tests/shell/lib/probe_vfs_getname.sh
tools/perf/ui/browsers/annotate.c
tools/perf/ui/gtk/annotate.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/auxtrace.c
tools/perf/util/auxtrace.h
tools/perf/util/config.c
tools/perf/util/config.h
tools/perf/util/probe-file.c
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_kernel.py
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/livepatch/Makefile
tools/testing/selftests/net/mptcp/Makefile
tools/testing/selftests/netfilter/nft_concat_range.sh
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rtc/Makefile
virt/kvm/arm/arm.c
virt/kvm/arm/trace.h

index 72ef86a..2763fce 100644 (file)
@@ -100,6 +100,10 @@ modules.order
 /include/ksym/
 /arch/*/include/generated/
 
+# Generated lkdtm tests
+/tools/testing/selftests/lkdtm/*.sh
+!/tools/testing/selftests/lkdtm/run.sh
+
 # stgit generated dirs
 patches-*
 
diff --git a/CREDITS b/CREDITS
index a97d328..032b599 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -567,6 +567,11 @@ D: Original author of Amiga FFS filesystem
 S: Orlando, Florida
 S: USA
 
+N: Paul Burton
+E: paulburton@kernel.org
+W: https://pburton.com
+D: MIPS maintainer 2018-2020
+
 N: Lennert Buytenhek
 E: kernel@wantstofly.org
 D: Original (2.4) rewrite of the ethernet bridging code
index 21d233c..98fe5c3 100644 (file)
@@ -18,7 +18,7 @@ may look as follows::
 
  $ ls -l /sys/bus/acpi/devices/INT3404:00/
  total 0
-...
+ ...
  -r--r--r-- 1 root root 4096 Dec 13 20:38 state0
  -r--r--r-- 1 root root 4096 Dec 13 20:38 state1
  -r--r--r-- 1 root root 4096 Dec 13 20:38 state10
@@ -38,7 +38,7 @@ where each of the "state*" files represents one performance state of the fan
 and contains a colon-separated list of 5 integer numbers (fields) with the
 following interpretation::
 
-control_percent:trip_point_index:speed_rpm:noise_level_mdb:power_mw
+  control_percent:trip_point_index:speed_rpm:noise_level_mdb:power_mw
 
 * ``control_percent``: The percent value to be used to set the fan speed to a
   specific level using the _FSL object (0-100).
index b342a67..cf2edcd 100644 (file)
@@ -62,6 +62,30 @@ Or more shorter, written as following::
 In both styles, same key words are automatically merged when parsing it
 at boot time. So you can append similar trees or key-values.
 
+Same-key Values
+---------------
+
+It is prohibited that two or more values or arrays share a same-key.
+For example,::
+
+ foo = bar, baz
+ foo = qux  # !ERROR! we can not re-define same key
+
+If you want to append the value to existing key as an array member,
+you can use ``+=`` operator. For example::
+
+ foo = bar, baz
+ foo += qux
+
+In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``.
+
+However, a sub-key and a value can not co-exist under a parent key.
+For example, following config is NOT allowed.::
+
+ foo = value1
+ foo.bar = value2 # !ERROR! subkey "bar" and value "value1" can NOT co-exist
+
+
 Comments
 --------
 
@@ -102,9 +126,13 @@ Boot Kernel With a Boot Config
 ==============================
 
 Since the boot configuration file is loaded with initrd, it will be added
-to the end of the initrd (initramfs) image file. The Linux kernel decodes
-the last part of the initrd image in memory to get the boot configuration
-data.
+to the end of the initrd (initramfs) image file with size, checksum and
+12-byte magic word as below.
+
+[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
+
+The Linux kernel decodes the last part of the initrd image in memory to
+get the boot configuration data.
 Because of this "piggyback" method, there is no need to change or
 update the boot loader and the kernel image itself.
 
index dbc22d6..c07815d 100644 (file)
                        dynamic table installation which will install SSDT
                        tables to /sys/firmware/acpi/tables/dynamic.
 
+       acpi_no_watchdog        [HW,ACPI,WDT]
+                       Ignore the ACPI-based watchdog interface (WDAT) and let
+                       a native driver control the watchdog device instead.
+
        acpi_rsdp=      [ACPI,EFI,KEXEC]
                        Pass the RSDP address to the kernel, mostly used
                        on machines running EFI runtime service to boot the
index 7cd56a1..607758a 100644 (file)
@@ -551,6 +551,7 @@ options to your ``.config``:
 Once the kernel is built and installed, a simple
 
 .. code-block:: bash
+
        modprobe example-test
 
 ...will run the tests.
index e5953e7..2104830 100644 (file)
@@ -151,8 +151,8 @@ The details of these operations are:
      Note that callbacks will always be invoked from the DMA
      engines tasklet, never from interrupt context.
 
-Optional: per descriptor metadata
----------------------------------
+  **Optional: per descriptor metadata**
+
   DMAengine provides two ways for metadata support.
 
   DESC_METADATA_CLIENT
@@ -199,12 +199,15 @@ Optional: per descriptor metadata
   DESC_METADATA_CLIENT
 
     - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
          construct the metadata in the client's buffer
       2. use dmaengine_desc_attach_metadata() to attach the buffer to the
          descriptor
       3. submit the transfer
+
     - DMA_DEV_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
       2. use dmaengine_desc_attach_metadata() to attach the buffer to the
          descriptor
@@ -215,6 +218,7 @@ Optional: per descriptor metadata
   DESC_METADATA_ENGINE
 
     - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
       2. use dmaengine_desc_get_metadata_ptr() to get the pointer to the
          engine's metadata area
@@ -222,7 +226,9 @@ Optional: per descriptor metadata
       4. use dmaengine_desc_set_metadata_len()  to tell the DMA engine the
          amount of data the client has placed into the metadata buffer
       5. submit the transfer
+
     - DMA_DEV_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
       2. submit the transfer
       3. on transfer completion, use dmaengine_desc_get_metadata_ptr() to get
@@ -278,8 +284,8 @@ Optional: per descriptor metadata
 
       void dma_async_issue_pending(struct dma_chan *chan);
 
-Further APIs:
--------------
+Further APIs
+------------
 
 1. Terminate APIs
 
index 0e0eb2c..6bc126a 100644 (file)
@@ -765,7 +765,7 @@ is not sufficient this sometimes needs to be explicit.
        Example::
 
                #arch/x86/boot/Makefile
-               subdir- := compressed/
+               subdir- := compressed
 
 The above assignment instructs kbuild to descend down in the
 directory compressed/ when "make clean" is executed.
@@ -1379,9 +1379,6 @@ See subsequent chapter for the syntax of the Kbuild file.
        in arch/$(ARCH)/include/(uapi/)/asm, Kbuild will automatically generate
        a wrapper of the asm-generic one.
 
-       The convention is to list one subdir per line and
-       preferably in alphabetic order.
-
 8 Kbuild Variables
 ==================
 
index 1e4735c..2561060 100644 (file)
@@ -487,8 +487,9 @@ phy_register_fixup_for_id()::
 The stubs set one of the two matching criteria, and set the other one to
 match anything.
 
-When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module,
-unregister fixup and free allocate memory are required.
+When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load
+time, the module needs to unregister the fixup and free allocated memory when
+it's unloaded.
 
 Call one of following function before unloading module::
 
index 002e427..ced8a80 100644 (file)
@@ -13,7 +13,6 @@ Power Management
     drivers-testing
     energy-model
     freezing-of-tasks
-    interface
     opp
     pci
     pm_qos_interface
index 7daf513..e54c44c 100644 (file)
@@ -30,4 +30,4 @@ if [ -n "$parallel" ] ; then
        parallel="-j$parallel"
 fi
 
-exec "$sphinx" "$parallel" "$@"
+exec "$sphinx" $parallel "$@"
index 97a72a5..ebd383f 100644 (file)
@@ -4611,35 +4611,38 @@ unpins the VPA pages and releases all the device pages that are used to
 track the secure pages by hypervisor.
 
 4.122 KVM_S390_NORMAL_RESET
+---------------------------
 
-Capability: KVM_CAP_S390_VCPU_RESETS
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: KVM_CAP_S390_VCPU_RESETS
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the cpu reset definition in the POP (Principles Of Operation).
 
 4.123 KVM_S390_INITIAL_RESET
+----------------------------
 
-Capability: none
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: none
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the initial cpu reset definition in the POP. However, the cpu is not
 put into ESA mode. This reset is a superset of the normal reset.
 
 4.124 KVM_S390_CLEAR_RESET
+--------------------------
 
-Capability: KVM_CAP_S390_VCPU_RESETS
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: KVM_CAP_S390_VCPU_RESETS
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the clear cpu reset definition in the POP. However, the cpu is not put
index a8de2fb..265d9e9 100644 (file)
@@ -19,7 +19,6 @@ x86-specific Documentation
    tlb
    mtrr
    pat
-   intel_mpx
    intel-iommu
    intel_txt
    amd-memory-encryption
index fcd79fc..68eebf3 100644 (file)
@@ -7738,7 +7738,7 @@ Hyper-V CORE AND DRIVERS
 M:     "K. Y. Srinivasan" <kys@microsoft.com>
 M:     Haiyang Zhang <haiyangz@microsoft.com>
 M:     Stephen Hemminger <sthemmin@microsoft.com>
-M:     Sasha Levin <sashal@kernel.org>
+M:     Wei Liu <wei.liu@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
 L:     linux-hyperv@vger.kernel.org
 S:     Supported
@@ -11115,14 +11115,12 @@ S:    Maintained
 F:     drivers/usb/image/microtek.*
 
 MIPS
-M:     Ralf Baechle <ralf@linux-mips.org>
-M:     Paul Burton <paulburton@kernel.org>
+M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
 L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
-T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
-S:     Supported
+S:     Maintained
 F:     Documentation/devicetree/bindings/mips/
 F:     Documentation/mips/
 F:     arch/mips/
@@ -12741,7 +12739,7 @@ M:      Tom Joseph <tjoseph@cadence.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/cdns,*.txt
-F:     drivers/pci/controller/pcie-cadence*
+F:     drivers/pci/controller/cadence/
 
 PCI DRIVER FOR FREESCALE LAYERSCAPE
 M:     Minghuan Lian <minghuan.Lian@nxp.com>
index 0914049..86035d8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -68,6 +68,7 @@ unexport GREP_OPTIONS
 #
 # If KBUILD_VERBOSE equals 0 then the above command will be hidden.
 # If KBUILD_VERBOSE equals 1 then the above command is displayed.
+# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
 #
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
@@ -1238,7 +1239,7 @@ ifneq ($(dtstree),)
 %.dtb: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
 
-PHONY += dtbs dtbs_install dt_binding_check
+PHONY += dtbs dtbs_install dtbs_check
 dtbs dtbs_check: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree)
 
@@ -1258,6 +1259,7 @@ PHONY += scripts_dtc
 scripts_dtc: scripts_basic
        $(Q)$(MAKE) $(build)=scripts/dtc
 
+PHONY += dt_binding_check
 dt_binding_check: scripts_dtc
        $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings
 
index 98de654..17fe351 100644 (file)
@@ -738,8 +738,9 @@ config HAVE_STACK_VALIDATION
 config HAVE_RELIABLE_STACKTRACE
        bool
        help
-         Architecture has a save_stack_trace_tsk_reliable() function which
-         only returns a stack trace if it can guarantee the trace is reliable.
+         Architecture has either save_stack_trace_tsk_reliable() or
+         arch_stack_walk_reliable() function which only returns a stack trace
+         if it can guarantee the trace is reliable.
 
 config HAVE_ARCH_HASH
        bool
index c3314b2..a827b4d 100644 (file)
@@ -392,9 +392,6 @@ static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {}
 
-static inline void kvm_arm_vhe_guest_enter(void) {}
-static inline void kvm_arm_vhe_guest_exit(void) {}
-
 #define KVM_BP_HARDEN_UNKNOWN          -1
 #define KVM_BP_HARDEN_WA_NEEDED                0
 #define KVM_BP_HARDEN_NOT_REQUIRED     1
index 25fec4b..a358e97 100644 (file)
@@ -32,7 +32,7 @@ static inline void gic_write_eoir(u32 irq)
        isb();
 }
 
-static inline void gic_write_dir(u32 irq)
+static __always_inline void gic_write_dir(u32 irq)
 {
        write_sysreg_s(irq, SYS_ICC_DIR_EL1);
        isb();
index 806e9dc..a4d1b5f 100644 (file)
@@ -69,7 +69,7 @@ static inline int icache_is_aliasing(void)
        return test_bit(ICACHEF_ALIASING, &__icache_flags);
 }
 
-static inline int icache_is_vpipt(void)
+static __always_inline int icache_is_vpipt(void)
 {
        return test_bit(ICACHEF_VPIPT, &__icache_flags);
 }
index 665c78e..e6cca3d 100644 (file)
@@ -145,7 +145,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page *);
 
-static inline void __flush_icache_all(void)
+static __always_inline void __flush_icache_all(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
                return;
index 92ef953..2a746b9 100644 (file)
@@ -435,13 +435,13 @@ cpuid_feature_extract_signed_field(u64 features, int field)
        return cpuid_feature_extract_signed_field_width(features, field, 4);
 }
 
-static inline unsigned int __attribute_const__
+static __always_inline unsigned int __attribute_const__
 cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
 {
        return (u64)(features << (64 - width - field)) >> (64 - width);
 }
 
-static inline unsigned int __attribute_const__
+static __always_inline unsigned int __attribute_const__
 cpuid_feature_extract_unsigned_field(u64 features, int field)
 {
        return cpuid_feature_extract_unsigned_field_width(features, field, 4);
@@ -564,7 +564,7 @@ static inline bool system_supports_mixed_endian(void)
        return val == 0x1;
 }
 
-static inline bool system_supports_fpsimd(void)
+static __always_inline bool system_supports_fpsimd(void)
 {
        return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
 }
@@ -575,13 +575,13 @@ static inline bool system_uses_ttbr0_pan(void)
                !cpus_have_const_cap(ARM64_HAS_PAN);
 }
 
-static inline bool system_supports_sve(void)
+static __always_inline bool system_supports_sve(void)
 {
        return IS_ENABLED(CONFIG_ARM64_SVE) &&
                cpus_have_const_cap(ARM64_SVE);
 }
 
-static inline bool system_supports_cnp(void)
+static __always_inline bool system_supports_cnp(void)
 {
        return IS_ENABLED(CONFIG_ARM64_CNP) &&
                cpus_have_const_cap(ARM64_HAS_CNP);
index 4e531f5..6facd13 100644 (file)
@@ -34,7 +34,7 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 }
 
 #define __raw_writel __raw_writel
-static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
 {
        asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
 }
@@ -69,7 +69,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 }
 
 #define __raw_readl __raw_readl
-static inline u32 __raw_readl(const volatile void __iomem *addr)
+static __always_inline u32 __raw_readl(const volatile void __iomem *addr)
 {
        u32 val;
        asm volatile(ALTERNATIVE("ldr %w0, [%1]",
index 688c634..f658dda 100644 (file)
@@ -36,7 +36,7 @@ void kvm_inject_undef32(struct kvm_vcpu *vcpu);
 void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
 void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
 
-static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
+static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
 {
        return !(vcpu->arch.hcr_el2 & HCR_RW);
 }
@@ -127,7 +127,7 @@ static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
        vcpu->arch.vsesr_el2 = vsesr;
 }
 
-static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
 {
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
 }
@@ -153,17 +153,17 @@ static inline void vcpu_write_elr_el1(const struct kvm_vcpu *vcpu, unsigned long
                *__vcpu_elr_el1(vcpu) = v;
 }
 
-static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
 {
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pstate;
 }
 
-static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
+static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
 {
        return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT);
 }
 
-static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
 {
        if (vcpu_mode_is_32bit(vcpu))
                return kvm_condition_valid32(vcpu);
@@ -181,13 +181,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
  * coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
  * AArch32 with banked registers.
  */
-static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
+static __always_inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
                                         u8 reg_num)
 {
        return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num];
 }
 
-static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
+static __always_inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
                                unsigned long val)
 {
        if (reg_num != 31)
@@ -264,12 +264,12 @@ static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
        return mode != PSR_MODE_EL0t;
 }
 
-static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
+static __always_inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault.esr_el2;
 }
 
-static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
 {
        u32 esr = kvm_vcpu_get_hsr(vcpu);
 
@@ -279,12 +279,12 @@ static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
        return -1;
 }
 
-static inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault.far_el2;
 }
 
-static inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
+static __always_inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
 {
        return ((phys_addr_t)vcpu->arch.fault.hpfar_el2 & HPFAR_MASK) << 8;
 }
@@ -299,7 +299,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_xVC_IMM_MASK;
 }
 
-static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV);
 }
@@ -319,17 +319,17 @@ static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF);
 }
 
-static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 {
        return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
 }
 
-static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW);
 }
 
-static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) ||
                kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */
@@ -340,18 +340,18 @@ static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM);
 }
 
-static inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
 {
        return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT);
 }
 
 /* This one is not specific to Data Abort */
-static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_IL);
 }
 
-static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
 {
        return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
 }
@@ -361,17 +361,17 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
 }
 
-static inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC;
 }
 
-static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
-static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
 {
        switch (kvm_vcpu_trap_get_fault(vcpu)) {
        case FSC_SEA:
@@ -390,7 +390,7 @@ static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
        }
 }
 
-static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
 {
        u32 esr = kvm_vcpu_get_hsr(vcpu);
        return ESR_ELx_SYS64_ISS_RT(esr);
@@ -504,7 +504,7 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
        return data;            /* Leave LE untouched */
 }
 
-static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
+static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
 {
        if (vcpu_mode_is_32bit(vcpu))
                kvm_skip_instr32(vcpu, is_wide_instr);
@@ -519,7 +519,7 @@ static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
  * Skip an instruction which has been emulated at hyp while most guest sysregs
  * are live.
  */
-static inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
+static __always_inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
 {
        *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
        vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR);
index d87aa60..57fd46a 100644 (file)
@@ -626,38 +626,6 @@ static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
 static inline void kvm_clr_pmu_events(u32 clr) {}
 #endif
 
-static inline void kvm_arm_vhe_guest_enter(void)
-{
-       local_daif_mask();
-
-       /*
-        * Having IRQs masked via PMR when entering the guest means the GIC
-        * will not signal the CPU of interrupts of lower priority, and the
-        * only way to get out will be via guest exceptions.
-        * Naturally, we want to avoid this.
-        *
-        * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
-        * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
-        */
-       pmr_sync();
-}
-
-static inline void kvm_arm_vhe_guest_exit(void)
-{
-       /*
-        * local_daif_restore() takes care to properly restore PSTATE.DAIF
-        * and the GIC PMR if the host is using IRQ priorities.
-        */
-       local_daif_restore(DAIF_PROCCTX_NOIRQ);
-
-       /*
-        * When we exit from the guest we change a number of CPU configuration
-        * parameters, such as traps.  Make sure these changes take effect
-        * before running the host or additional guests.
-        */
-       isb();
-}
-
 #define KVM_BP_HARDEN_UNKNOWN          -1
 #define KVM_BP_HARDEN_WA_NEEDED                0
 #define KVM_BP_HARDEN_NOT_REQUIRED     1
index a3a6a2b..fe57f60 100644 (file)
 #define read_sysreg_el2(r)     read_sysreg_elx(r, _EL2, _EL1)
 #define write_sysreg_el2(v,r)  write_sysreg_elx(v, r, _EL2, _EL1)
 
+/*
+ * Without an __arch_swab32(), we fall back to ___constant_swab32(), but the
+ * static inline can allow the compiler to out-of-line this. KVM always wants
+ * the macro version as its always inlined.
+ */
+#define __kvm_swab32(x)        ___constant_swab32(x)
+
 int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
index 53d846f..7857628 100644 (file)
@@ -93,7 +93,7 @@ void kvm_update_va_mask(struct alt_instr *alt,
                        __le32 *origptr, __le32 *updptr, int nr_inst);
 void kvm_compute_layout(void);
 
-static inline unsigned long __kern_hyp_va(unsigned long v)
+static __always_inline unsigned long __kern_hyp_va(unsigned long v)
 {
        asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
                                    "ror %0, %0, #1\n"
@@ -473,6 +473,7 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
 extern void *__kvm_bp_vect_base;
 extern int __kvm_harden_el2_vector_slot;
 
+/*  This is only called on a VHE system */
 static inline void *kvm_get_hyp_vector(void)
 {
        struct bp_hardening_data *data = arm64_get_bp_hardening_data();
index 0958ed6..61fd267 100644 (file)
@@ -83,7 +83,7 @@ static inline bool is_kernel_in_hyp_mode(void)
        return read_sysreg(CurrentEL) == CurrentEL_EL2;
 }
 
-static inline bool has_vhe(void)
+static __always_inline bool has_vhe(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
                return true;
index dfe8dd1..925086b 100644 (file)
@@ -625,7 +625,7 @@ static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
 }
 
 /* Switch to the guest for VHE systems running in EL2 */
-int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
+static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpu_context *host_ctxt;
        struct kvm_cpu_context *guest_ctxt;
@@ -678,7 +678,42 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
        return exit_code;
 }
-NOKPROBE_SYMBOL(kvm_vcpu_run_vhe);
+NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe);
+
+int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
+{
+       int ret;
+
+       local_daif_mask();
+
+       /*
+        * Having IRQs masked via PMR when entering the guest means the GIC
+        * will not signal the CPU of interrupts of lower priority, and the
+        * only way to get out will be via guest exceptions.
+        * Naturally, we want to avoid this.
+        *
+        * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
+        * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
+        */
+       pmr_sync();
+
+       ret = __kvm_vcpu_run_vhe(vcpu);
+
+       /*
+        * local_daif_restore() takes care to properly restore PSTATE.DAIF
+        * and the GIC PMR if the host is using IRQ priorities.
+        */
+       local_daif_restore(DAIF_PROCCTX_NOIRQ);
+
+       /*
+        * When we exit from the guest we change a number of CPU configuration
+        * parameters, such as traps.  Make sure these changes take effect
+        * before running the host or additional guests.
+        */
+       isb();
+
+       return ret;
+}
 
 /* Switch to the guest for legacy non-VHE systems */
 int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
index 29ee1fe..4f3a087 100644 (file)
@@ -69,14 +69,14 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
                u32 data = vcpu_get_reg(vcpu, rd);
                if (__is_be(vcpu)) {
                        /* guest pre-swabbed data, undo this for writel() */
-                       data = swab32(data);
+                       data = __kvm_swab32(data);
                }
                writel_relaxed(data, addr);
        } else {
                u32 data = readl_relaxed(addr);
                if (__is_be(vcpu)) {
                        /* guest expects swabbed data */
-                       data = swab32(data);
+                       data = __kvm_swab32(data);
                }
                vcpu_set_reg(vcpu, rd, data);
        }
index 8ef73e8..d89bb22 100644 (file)
@@ -260,14 +260,26 @@ asmlinkage void post_ttbr_update_workaround(void)
                        CONFIG_CAVIUM_ERRATUM_27456));
 }
 
-static int asids_init(void)
+static int asids_update_limit(void)
 {
-       asid_bits = get_cpu_asid_bits();
+       unsigned long num_available_asids = NUM_USER_ASIDS;
+
+       if (arm64_kernel_unmapped_at_el0())
+               num_available_asids /= 2;
        /*
         * Expect allocation after rollover to fail if we don't have at least
         * one more ASID than CPUs. ASID #0 is reserved for init_mm.
         */
-       WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
+       WARN_ON(num_available_asids - 1 <= num_possible_cpus());
+       pr_info("ASID allocator initialised with %lu entries\n",
+               num_available_asids);
+       return 0;
+}
+arch_initcall(asids_update_limit);
+
+static int asids_init(void)
+{
+       asid_bits = get_cpu_asid_bits();
        atomic64_set(&asid_generation, ASID_FIRST_VERSION);
        asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*asid_map),
                           GFP_KERNEL);
@@ -282,8 +294,6 @@ static int asids_init(void)
         */
        if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0))
                set_kpti_asid_bits();
-
-       pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
        return 0;
 }
 early_initcall(asids_init);
index 5accda2..a3301ba 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4740-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 
 / {
        #address-cells = <1>;
                #clock-cells = <1>;
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4740-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4740_CLK_RTC>;
-               clock-names = "rtc";
-       };
-
        tcu: timer@10002000 {
                compatible = "ingenic,jz4740-tcu", "simple-mfd";
                reg = <0x10002000 0x1000>;
 
                interrupt-parent = <&intc>;
                interrupts = <23 22 21>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4740-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
index f928329..bb89653 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4780-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/dma/jz4780-dma.h>
 
 / {
 
                interrupt-parent = <&intc>;
                interrupts = <27 26 25>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4780-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
                status = "disabled";
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4780-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4780_CLK_RTCLK>;
-               clock-names = "rtc";
-       };
-
        nemc: nemc@13410000 {
                compatible = "ingenic,jz4780-nemc";
                reg = <0x13410000 0x10000>;
index 4994c69..147f7d5 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/clock/x1000-cgu.h>
 #include <dt-bindings/dma/x1000-dma.h>
 
@@ -72,7 +73,7 @@
                        compatible = "ingenic,x1000-watchdog", "ingenic,jz4780-watchdog";
                        reg = <0x0 0x10>;
 
-                       clocks = <&cgu X1000_CLK_RTCLK>;
+                       clocks = <&tcu TCU_CLK_WDT>;
                        clock-names = "wdt";
                };
        };
        i2c0: i2c-controller@10050000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10050000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c1: i2c-controller@10051000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10051000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c2: i2c-controller@10052000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10052000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
index 7c6a109..aabd097 100644 (file)
  * effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use
  * optimized memory barrier primitives."). Here we specify that the affected
  * sync instructions should be emitted twice.
+ * Note that this expression is evaluated by the assembler (not the compiler),
+ * and that the assembler evaluates '==' as 0 or -1, not 0 or 1.
  */
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-# define __SYNC_rpt(type)      (1 + (type == __SYNC_wmb))
+# define __SYNC_rpt(type)      (1 - (type == __SYNC_wmb))
 #else
 # define __SYNC_rpt(type)      1
 #endif
index 6176b9a..d0d832a 100644 (file)
@@ -134,7 +134,7 @@ void release_vpe(struct vpe *v)
 {
        list_del(&v->list);
        if (v->load_addr)
-               release_progmem(v);
+               release_progmem(v->load_addr);
        kfree(v);
 }
 
index aa89a41..d7fe840 100644 (file)
@@ -33,6 +33,7 @@ endif
 cflags-vdso := $(ccflags-vdso) \
        $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
        -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+       -mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \
        -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
        $(call cc-option, -fno-asynchronous-unwind-tables) \
        $(call cc-option, -fno-stack-protector)
@@ -51,6 +52,8 @@ endif
 
 CFLAGS_REMOVE_vgettimeofday.o = -pg
 
+DISABLE_VDSO := n
+
 #
 # For the pre-R6 code in arch/mips/vdso/vdso.h for locating
 # the base address of VDSO, the linker will emit a R_MIPS_PC32
@@ -64,11 +67,24 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
 ifndef CONFIG_CPU_MIPSR6
   ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
     $(warning MIPS VDSO requires binutils >= 2.25)
-    obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
-    ccflags-vdso += -DDISABLE_MIPS_VDSO
+    DISABLE_VDSO := y
   endif
 endif
 
+#
+# GCC (at least up to version 9.2) appears to emit function calls that make use
+# of the GOT when targeting microMIPS, which we can't use in the VDSO due to
+# the lack of relocations. As such, we disable the VDSO for microMIPS builds.
+#
+ifdef CONFIG_CPU_MICROMIPS
+  DISABLE_VDSO := y
+endif
+
+ifeq ($(DISABLE_VDSO),y)
+  obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
+  ccflags-vdso += -DDISABLE_MIPS_VDSO
+endif
+
 # VDSO linker flags.
 VDSO_LDFLAGS := \
        -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
@@ -81,12 +97,18 @@ GCOV_PROFILE := n
 UBSAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
+# Check that we don't have PIC 'jalr t9' calls left
+quiet_cmd_vdso_mips_check = VDSOCHK $@
+      cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
+                      then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
+                            rm -f $@; /bin/false); fi
+
 #
 # Shared build commands.
 #
 
 quiet_cmd_vdsold_and_vdso_check = LD      $@
-      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
+      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check); $(cmd_vdso_mips_check)
 
 quiet_cmd_vdsold = VDSO    $@
       cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
index 8dab0bb..8a45a37 100644 (file)
@@ -1,2 +1,4 @@
 Image
 Image.gz
+loader
+loader.lds
index 435b655..8e18d2c 100644 (file)
 #define EXC_LOAD_PAGE_FAULT    13
 #define EXC_STORE_PAGE_FAULT   15
 
+/* PMP configuration */
+#define PMP_R                  0x01
+#define PMP_W                  0x02
+#define PMP_X                  0x04
+#define PMP_A                  0x18
+#define PMP_A_TOR              0x08
+#define PMP_A_NA4              0x10
+#define PMP_A_NAPOT            0x18
+#define PMP_L                  0x80
+
 /* symbolic CSR names: */
 #define CSR_CYCLE              0xc00
 #define CSR_TIME               0xc01
 #define CSR_MCAUSE             0x342
 #define CSR_MTVAL              0x343
 #define CSR_MIP                        0x344
+#define CSR_PMPCFG0            0x3a0
+#define CSR_PMPADDR0           0x3b0
 #define CSR_MHARTID            0xf14
 
 #ifdef CONFIG_RISCV_M_MODE
index 271860f..85f2073 100644 (file)
@@ -58,6 +58,12 @@ _start_kernel:
        /* Reset all registers except ra, a0, a1 */
        call reset_regs
 
+       /* Setup a PMP to permit access to all of memory. */
+       li a0, -1
+       csrw CSR_PMPADDR0, a0
+       li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
+       csrw CSR_PMPCFG0, a0
+
        /*
         * The hartid in a0 is expected later on, and we have no firmware
         * to hand it to us.
index f4cad51..ffb3d94 100644 (file)
@@ -156,6 +156,6 @@ void __init trap_init(void)
        csr_write(CSR_SCRATCH, 0);
        /* Set the exception vector address */
        csr_write(CSR_TVEC, &handle_exception);
-       /* Enable all interrupts */
-       csr_write(CSR_IE, -1);
+       /* Enable interrupts */
+       csr_write(CSR_IE, IE_SIE | IE_EIE);
 }
index f0cc860..ec0ca90 100644 (file)
@@ -19,18 +19,20 @@ asmlinkage void __init kasan_early_init(void)
        for (i = 0; i < PTRS_PER_PTE; ++i)
                set_pte(kasan_early_shadow_pte + i,
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       PAGE_KERNEL));
+                              PAGE_KERNEL));
 
        for (i = 0; i < PTRS_PER_PMD; ++i)
                set_pmd(kasan_early_shadow_pmd + i,
-                pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pmd(PFN_DOWN
+                               (__pa((uintptr_t) kasan_early_shadow_pte)),
+                               __pgprot(_PAGE_TABLE)));
 
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        /* init for swapper_pg_dir */
        pgd = pgd_offset_k(KASAN_SHADOW_START);
@@ -38,37 +40,43 @@ asmlinkage void __init kasan_early_init(void)
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
 }
 
 static void __init populate(void *start, void *end)
 {
-       unsigned long i;
+       unsigned long i, offset;
        unsigned long vaddr = (unsigned long)start & PAGE_MASK;
        unsigned long vend = PAGE_ALIGN((unsigned long)end);
        unsigned long n_pages = (vend - vaddr) / PAGE_SIZE;
+       unsigned long n_ptes =
+           ((n_pages + PTRS_PER_PTE) & -PTRS_PER_PTE) / PTRS_PER_PTE;
        unsigned long n_pmds =
-               (n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 :
-                                               n_pages / PTRS_PER_PTE;
+           ((n_ptes + PTRS_PER_PMD) & -PTRS_PER_PMD) / PTRS_PER_PMD;
+
+       pte_t *pte =
+           memblock_alloc(n_ptes * PTRS_PER_PTE * sizeof(pte_t), PAGE_SIZE);
+       pmd_t *pmd =
+           memblock_alloc(n_pmds * PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
        pgd_t *pgd = pgd_offset_k(vaddr);
-       pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE);
-       pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
 
        for (i = 0; i < n_pages; i++) {
                phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
-
-               set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
+               set_pte(&pte[i], pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
        }
 
-       for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD)
-               set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))),
+       for (i = 0, offset = 0; i < n_ptes; i++, offset += PTRS_PER_PTE)
+               set_pmd(&pmd[i],
+                       pfn_pmd(PFN_DOWN(__pa(&pte[offset])),
                                __pgprot(_PAGE_TABLE)));
 
-       for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE)
-               set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))),
+       for (i = 0, offset = 0; i < n_pmds; i++, offset += PTRS_PER_PMD)
+               set_pgd(&pgd[i],
+                       pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
                                __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
@@ -81,7 +89,8 @@ void __init kasan_init(void)
        unsigned long i;
 
        kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
-                       (void *)kasan_mem_to_shadow((void *)VMALLOC_END));
+                                   (void *)kasan_mem_to_shadow((void *)
+                                                               VMALLOC_END));
 
        for_each_memblock(memory, reg) {
                void *start = (void *)__va(reg->base);
@@ -90,14 +99,14 @@ void __init kasan_init(void)
                if (start >= end)
                        break;
 
-               populate(kasan_mem_to_shadow(start),
-                        kasan_mem_to_shadow(end));
+               populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end));
        };
 
        for (i = 0; i < PTRS_PER_PTE; i++)
                set_pte(&kasan_early_shadow_pte[i],
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED)));
+                              __pgprot(_PAGE_PRESENT | _PAGE_READ |
+                                       _PAGE_ACCESSED)));
 
        memset(kasan_early_shadow_page, 0, PAGE_SIZE);
        init_task.kasan_depth = 0;
index 02c6ef8..07344d8 100644 (file)
@@ -19,7 +19,14 @@ struct task_struct;
 void io_bitmap_share(struct task_struct *tsk);
 void io_bitmap_exit(void);
 
-void tss_update_io_bitmap(void);
+void native_tss_update_io_bitmap(void);
+
+#ifdef CONFIG_PARAVIRT_XXL
+#include <asm/paravirt.h>
+#else
+#define tss_update_io_bitmap native_tss_update_io_bitmap
+#endif
+
 #else
 static inline void io_bitmap_share(struct task_struct *tsk) { }
 static inline void io_bitmap_exit(void) { }
index 03946eb..2a8f2bd 100644 (file)
@@ -292,6 +292,14 @@ enum x86emul_mode {
 #define X86EMUL_SMM_MASK             (1 << 6)
 #define X86EMUL_SMM_INSIDE_NMI_MASK  (1 << 7)
 
+/*
+ * fastop functions are declared as taking a never-defined fastop parameter,
+ * so they can't be called from C directly.
+ */
+struct fastop;
+
+typedef void (*fastop_t)(struct fastop *);
+
 struct x86_emulate_ctxt {
        const struct x86_emulate_ops *ops;
 
@@ -324,7 +332,10 @@ struct x86_emulate_ctxt {
        struct operand src;
        struct operand src2;
        struct operand dst;
-       int (*execute)(struct x86_emulate_ctxt *ctxt);
+       union {
+               int (*execute)(struct x86_emulate_ctxt *ctxt);
+               fastop_t fop;
+       };
        int (*check_perm)(struct x86_emulate_ctxt *ctxt);
        /*
         * The following six fields are cleared together,
index 40a0c0f..98959e8 100644 (file)
@@ -1122,6 +1122,7 @@ struct kvm_x86_ops {
        int (*handle_exit)(struct kvm_vcpu *vcpu,
                enum exit_fastpath_completion exit_fastpath);
        int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+       void (*update_emulated_instruction)(struct kvm_vcpu *vcpu);
        void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
        u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
        void (*patch_hypercall)(struct kvm_vcpu *vcpu,
@@ -1146,7 +1147,7 @@ struct kvm_x86_ops {
        void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
        void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
        void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
-       void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
+       int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
        int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
        int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
        int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);
index 86e7317..694d8da 100644 (file)
@@ -295,6 +295,13 @@ static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
        PVOP_VCALL3(cpu.write_idt_entry, dt, entry, g);
 }
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+static inline void tss_update_io_bitmap(void)
+{
+       PVOP_VCALL0(cpu.update_io_bitmap);
+}
+#endif
+
 static inline void paravirt_activate_mm(struct mm_struct *prev,
                                        struct mm_struct *next)
 {
index 8481296..732f62e 100644 (file)
@@ -140,6 +140,10 @@ struct pv_cpu_ops {
 
        void (*load_sp0)(unsigned long sp0);
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+       void (*update_io_bitmap)(void);
+#endif
+
        void (*wbinvd)(void);
 
        /* cpuid emulation, mostly so that caps bits can be disabled */
index 2a85287..8521af3 100644 (file)
@@ -72,7 +72,7 @@
 #define SECONDARY_EXEC_MODE_BASED_EPT_EXEC     VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC)
 #define SECONDARY_EXEC_PT_USE_GPA              VMCS_CONTROL_BIT(PT_USE_GPA)
 #define SECONDARY_EXEC_TSC_SCALING              VMCS_CONTROL_BIT(TSC_SCALING)
-#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE   0x04000000
+#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE   VMCS_CONTROL_BIT(USR_WAIT_PAUSE)
 
 #define PIN_BASED_EXT_INTR_MASK                 VMCS_CONTROL_BIT(INTR_EXITING)
 #define PIN_BASED_NMI_EXITING                   VMCS_CONTROL_BIT(NMI_EXITING)
index a50e4a0..9915990 100644 (file)
@@ -81,6 +81,7 @@
 #define VMX_FEATURE_MODE_BASED_EPT_EXEC        ( 2*32+ 22) /* "ept_mode_based_exec" Enable separate EPT EXEC bits for supervisor vs. user */
 #define VMX_FEATURE_PT_USE_GPA         ( 2*32+ 24) /* "" Processor Trace logs GPAs */
 #define VMX_FEATURE_TSC_SCALING                ( 2*32+ 25) /* Scale hardware TSC when read in guest */
+#define VMX_FEATURE_USR_WAIT_PAUSE     ( 2*32+ 26) /* Enable TPAUSE, UMONITOR, UMWAIT in guest */
 #define VMX_FEATURE_ENCLV_EXITING      ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */
 
 #endif /* _ASM_X86_VMXFEATURES_H */
index 503d3f4..3f3f780 100644 (file)
@@ -390,6 +390,7 @@ struct kvm_sync_regs {
 #define KVM_STATE_NESTED_GUEST_MODE    0x00000001
 #define KVM_STATE_NESTED_RUN_PENDING   0x00000002
 #define KVM_STATE_NESTED_EVMCS         0x00000004
+#define KVM_STATE_NESTED_MTF_PENDING   0x00000008
 
 #define KVM_STATE_NESTED_SMM_GUEST_MODE        0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON     0x00000002
index 52c9bfb..4cdb123 100644 (file)
@@ -445,7 +445,7 @@ static __always_inline void setup_pku(struct cpuinfo_x86 *c)
         * cpuid bit to be set.  We need to ensure that we
         * update that bit in this CPU's "cpu_info".
         */
-       get_cpu_cap(c);
+       set_cpu_cap(c, X86_FEATURE_OSPKE);
 }
 
 #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
index d817f25..6efe041 100644 (file)
@@ -425,7 +425,29 @@ static void __init sev_map_percpu_data(void)
        }
 }
 
+static bool pv_tlb_flush_supported(void)
+{
+       return (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
+               !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+               kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
+}
+
+static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask);
+
 #ifdef CONFIG_SMP
+
+static bool pv_ipi_supported(void)
+{
+       return kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI);
+}
+
+static bool pv_sched_yield_supported(void)
+{
+       return (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
+               !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
+}
+
 #define KVM_IPI_CLUSTER_SIZE   (2 * BITS_PER_LONG)
 
 static void __send_ipi_mask(const struct cpumask *mask, int vector)
@@ -490,12 +512,12 @@ static void kvm_send_ipi_mask(const struct cpumask *mask, int vector)
 static void kvm_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
 {
        unsigned int this_cpu = smp_processor_id();
-       struct cpumask new_mask;
+       struct cpumask *new_mask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
        const struct cpumask *local_mask;
 
-       cpumask_copy(&new_mask, mask);
-       cpumask_clear_cpu(this_cpu, &new_mask);
-       local_mask = &new_mask;
+       cpumask_copy(new_mask, mask);
+       cpumask_clear_cpu(this_cpu, new_mask);
+       local_mask = new_mask;
        __send_ipi_mask(local_mask, vector);
 }
 
@@ -575,7 +597,6 @@ static void __init kvm_apf_trap_init(void)
        update_intr_gate(X86_TRAP_PF, async_page_fault);
 }
 
-static DEFINE_PER_CPU(cpumask_var_t, __pv_tlb_mask);
 
 static void kvm_flush_tlb_others(const struct cpumask *cpumask,
                        const struct flush_tlb_info *info)
@@ -583,7 +604,7 @@ static void kvm_flush_tlb_others(const struct cpumask *cpumask,
        u8 state;
        int cpu;
        struct kvm_steal_time *src;
-       struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_tlb_mask);
+       struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
 
        cpumask_copy(flushmask, cpumask);
        /*
@@ -619,11 +640,10 @@ static void __init kvm_guest_init(void)
                pv_ops.time.steal_clock = kvm_steal_clock;
        }
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_tlb_flush_supported()) {
                pv_ops.mmu.flush_tlb_others = kvm_flush_tlb_others;
                pv_ops.mmu.tlb_remove_table = tlb_remove_table;
+               pr_info("KVM setup pv remote TLB flush\n");
        }
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
@@ -632,9 +652,7 @@ static void __init kvm_guest_init(void)
 #ifdef CONFIG_SMP
        smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus;
        smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
-       if (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_sched_yield_supported()) {
                smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi;
                pr_info("KVM setup pv sched yield\n");
        }
@@ -700,7 +718,7 @@ static uint32_t __init kvm_detect(void)
 static void __init kvm_apic_init(void)
 {
 #if defined(CONFIG_SMP)
-       if (kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI))
+       if (pv_ipi_supported())
                kvm_setup_pv_ipi();
 #endif
 }
@@ -732,26 +750,31 @@ static __init int activate_jump_labels(void)
 }
 arch_initcall(activate_jump_labels);
 
-static __init int kvm_setup_pv_tlb_flush(void)
+static __init int kvm_alloc_cpumask(void)
 {
        int cpu;
+       bool alloc = false;
 
        if (!kvm_para_available() || nopv)
                return 0;
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_tlb_flush_supported())
+               alloc = true;
+
+#if defined(CONFIG_SMP)
+       if (pv_ipi_supported())
+               alloc = true;
+#endif
+
+       if (alloc)
                for_each_possible_cpu(cpu) {
-                       zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu),
+                       zalloc_cpumask_var_node(per_cpu_ptr(&__pv_cpu_mask, cpu),
                                GFP_KERNEL, cpu_to_node(cpu));
                }
-               pr_info("KVM setup pv remote TLB flush\n");
-       }
 
        return 0;
 }
-arch_initcall(kvm_setup_pv_tlb_flush);
+arch_initcall(kvm_alloc_cpumask);
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
 
index 789f5e4..c131ba4 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/timer.h>
 #include <asm/special_insns.h>
 #include <asm/tlb.h>
+#include <asm/io_bitmap.h>
 
 /*
  * nop stub, which must not clobber anything *including the stack* to
@@ -341,6 +342,10 @@ struct paravirt_patch_template pv_ops = {
        .cpu.iret               = native_iret,
        .cpu.swapgs             = native_swapgs,
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+       .cpu.update_io_bitmap   = native_tss_update_io_bitmap,
+#endif
+
        .cpu.start_context_switch       = paravirt_nop,
        .cpu.end_context_switch         = paravirt_nop,
 
index 839b524..3053c85 100644 (file)
@@ -374,7 +374,7 @@ static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
 /**
  * tss_update_io_bitmap - Update I/O bitmap before exiting to usermode
  */
-void tss_update_io_bitmap(void)
+void native_tss_update_io_bitmap(void)
 {
        struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
        struct thread_struct *t = &current->thread;
index 991019d..1bb4927 100644 (file)
@@ -59,6 +59,19 @@ config KVM
 
          If unsure, say N.
 
+config KVM_WERROR
+       bool "Compile KVM with -Werror"
+       # KASAN may cause the build to fail due to larger frames
+       default y if X86_64 && !KASAN
+       # We use the dependency on !COMPILE_TEST to not be enabled
+       # blindly in allmodconfig or allyesconfig configurations
+       depends on (X86_64 && !KASAN) || !COMPILE_TEST
+       depends on EXPERT
+       help
+         Add -Werror to the build flags for (and only for) i915.ko.
+
+         If in doubt, say "N".
+
 config KVM_INTEL
        tristate "KVM for Intel (and compatible) processors support"
        depends on KVM && IA32_FEAT_CTL
index b19ef42..e553f0f 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 ccflags-y += -Iarch/x86/kvm
+ccflags-$(CONFIG_KVM_WERROR) += -Werror
 
 KVM := ../../../virt/kvm
 
index ddbc619..dd19fb3 100644 (file)
 #define NR_FASTOP (ilog2(sizeof(ulong)) + 1)
 #define FASTOP_SIZE 8
 
-/*
- * fastop functions have a special calling convention:
- *
- * dst:    rax        (in/out)
- * src:    rdx        (in/out)
- * src2:   rcx        (in)
- * flags:  rflags     (in/out)
- * ex:     rsi        (in:fastop pointer, out:zero if exception)
- *
- * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
- * different operand sizes can be reached by calculation, rather than a jump
- * table (which would be bigger than the code).
- *
- * fastop functions are declared as taking a never-defined fastop parameter,
- * so they can't be called from C directly.
- */
-
-struct fastop;
-
 struct opcode {
        u64 flags : 56;
        u64 intercept : 8;
@@ -311,8 +292,19 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
 #define ON64(x)
 #endif
 
-typedef void (*fastop_t)(struct fastop *);
-
+/*
+ * fastop functions have a special calling convention:
+ *
+ * dst:    rax        (in/out)
+ * src:    rdx        (in/out)
+ * src2:   rcx        (in)
+ * flags:  rflags     (in/out)
+ * ex:     rsi        (in:fastop pointer, out:zero if exception)
+ *
+ * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
+ * different operand sizes can be reached by calculation, rather than a jump
+ * table (which would be bigger than the code).
+ */
 static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
 
 #define __FOP_FUNC(name) \
@@ -5683,7 +5675,7 @@ special_insn:
 
        if (ctxt->execute) {
                if (ctxt->d & Fastop)
-                       rc = fastop(ctxt, (fastop_t)ctxt->execute);
+                       rc = fastop(ctxt, ctxt->fop);
                else
                        rc = ctxt->execute(ctxt);
                if (rc != X86EMUL_CONTINUE)
index 79afa0b..c47d2ac 100644 (file)
@@ -417,7 +417,7 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
 
                        kvm_set_msi_irq(vcpu->kvm, entry, &irq);
 
-                       if (irq.level &&
+                       if (irq.trig_mode &&
                            kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
                                                irq.dest_id, irq.dest_mode))
                                __set_bit(irq.vector, ioapic_handled_vectors);
index afcd30d..e3099c6 100644 (file)
@@ -627,9 +627,11 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
 static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
 {
        u8 val;
-       if (pv_eoi_get_user(vcpu, &val) < 0)
+       if (pv_eoi_get_user(vcpu, &val) < 0) {
                printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n",
                           (unsigned long long)vcpu->arch.pv_eoi.msr_val);
+               return false;
+       }
        return val & 0x1;
 }
 
@@ -1046,11 +1048,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                                                       apic->regs + APIC_TMR);
                }
 
-               if (vcpu->arch.apicv_active)
-                       kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
-               else {
+               if (kvm_x86_ops->deliver_posted_interrupt(vcpu, vector)) {
                        kvm_lapic_set_irr(vector, apic);
-
                        kvm_make_request(KVM_REQ_EVENT, vcpu);
                        kvm_vcpu_kick(vcpu);
                }
index 3c6522b..ffcd96f 100644 (file)
@@ -339,7 +339,7 @@ TRACE_EVENT(
                /* These depend on page entry type, so compute them now.  */
                __field(bool, r)
                __field(bool, x)
-               __field(u8, u)
+               __field(signed char, u)
        ),
 
        TP_fast_assign(
index bef0ba3..24c0b2b 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 static const struct x86_cpu_id svm_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_SVM),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
+#endif
 
 #define IOPM_ALLOC_ORDER 2
 #define MSRPM_ALLOC_ORDER 1
@@ -1005,33 +1007,32 @@ static void svm_cpu_uninit(int cpu)
 static int svm_cpu_init(int cpu)
 {
        struct svm_cpu_data *sd;
-       int r;
 
        sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
        if (!sd)
                return -ENOMEM;
        sd->cpu = cpu;
-       r = -ENOMEM;
        sd->save_area = alloc_page(GFP_KERNEL);
        if (!sd->save_area)
-               goto err_1;
+               goto free_cpu_data;
 
        if (svm_sev_enabled()) {
-               r = -ENOMEM;
                sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1,
                                              sizeof(void *),
                                              GFP_KERNEL);
                if (!sd->sev_vmcbs)
-                       goto err_1;
+                       goto free_save_area;
        }
 
        per_cpu(svm_data, cpu) = sd;
 
        return 0;
 
-err_1:
+free_save_area:
+       __free_page(sd->save_area);
+free_cpu_data:
        kfree(sd);
-       return r;
+       return -ENOMEM;
 
 }
 
@@ -1350,6 +1351,24 @@ static __init void svm_adjust_mmio_mask(void)
        kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK);
 }
 
+static void svm_hardware_teardown(void)
+{
+       int cpu;
+
+       if (svm_sev_enabled()) {
+               bitmap_free(sev_asid_bitmap);
+               bitmap_free(sev_reclaim_asid_bitmap);
+
+               sev_flush_asids();
+       }
+
+       for_each_possible_cpu(cpu)
+               svm_cpu_uninit(cpu);
+
+       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
+       iopm_base = 0;
+}
+
 static __init int svm_hardware_setup(void)
 {
        int cpu;
@@ -1463,29 +1482,10 @@ static __init int svm_hardware_setup(void)
        return 0;
 
 err:
-       __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
-       iopm_base = 0;
+       svm_hardware_teardown();
        return r;
 }
 
-static __exit void svm_hardware_unsetup(void)
-{
-       int cpu;
-
-       if (svm_sev_enabled()) {
-               bitmap_free(sev_asid_bitmap);
-               bitmap_free(sev_reclaim_asid_bitmap);
-
-               sev_flush_asids();
-       }
-
-       for_each_possible_cpu(cpu)
-               svm_cpu_uninit(cpu);
-
-       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
-       iopm_base = 0;
-}
-
 static void init_seg(struct vmcb_seg *seg)
 {
        seg->selector = 0;
@@ -2196,8 +2196,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 static int avic_init_vcpu(struct vcpu_svm *svm)
 {
        int ret;
+       struct kvm_vcpu *vcpu = &svm->vcpu;
 
-       if (!kvm_vcpu_apicv_active(&svm->vcpu))
+       if (!avic || !irqchip_in_kernel(vcpu->kvm))
                return 0;
 
        ret = avic_init_backing_page(&svm->vcpu);
@@ -5232,6 +5233,9 @@ static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
        struct vmcb *vmcb = svm->vmcb;
        bool activated = kvm_vcpu_apicv_active(vcpu);
 
+       if (!avic)
+               return;
+
        if (activated) {
                /**
                 * During AVIC temporary deactivation, guest could update
@@ -5255,8 +5259,11 @@ static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
        return;
 }
 
-static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
+static int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
 {
+       if (!vcpu->arch.apicv_active)
+               return -1;
+
        kvm_lapic_set_irr(vec, vcpu->arch.apic);
        smp_mb__after_atomic();
 
@@ -5268,6 +5275,8 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
                put_cpu();
        } else
                kvm_vcpu_wake_up(vcpu);
+
+       return 0;
 }
 
 static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
@@ -7378,7 +7387,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
        .hardware_setup = svm_hardware_setup,
-       .hardware_unsetup = svm_hardware_unsetup,
+       .hardware_unsetup = svm_hardware_teardown,
        .check_processor_compatibility = svm_check_processor_compat,
        .hardware_enable = svm_hardware_enable,
        .hardware_disable = svm_hardware_disable,
@@ -7433,6 +7442,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .run = svm_vcpu_run,
        .handle_exit = handle_exit,
        .skip_emulated_instruction = skip_emulated_instruction,
+       .update_emulated_instruction = NULL,
        .set_interrupt_shadow = svm_set_interrupt_shadow,
        .get_interrupt_shadow = svm_get_interrupt_shadow,
        .patch_hypercall = svm_patch_hypercall,
index 283bdb7..f486e26 100644 (file)
@@ -12,6 +12,7 @@ extern bool __read_mostly enable_ept;
 extern bool __read_mostly enable_unrestricted_guest;
 extern bool __read_mostly enable_ept_ad_bits;
 extern bool __read_mostly enable_pml;
+extern bool __read_mostly enable_apicv;
 extern int __read_mostly pt_mode;
 
 #define PT_MODE_SYSTEM         0
index 3589cd3..e920d78 100644 (file)
@@ -3161,10 +3161,10 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
  * or KVM_SET_NESTED_STATE).  Otherwise it's called from vmlaunch/vmresume.
  *
  * Returns:
- *     NVMX_ENTRY_SUCCESS: Entered VMX non-root mode
- *     NVMX_ENTRY_VMFAIL:  Consistency check VMFail
- *     NVMX_ENTRY_VMEXIT:  Consistency check VMExit
- *     NVMX_ENTRY_KVM_INTERNAL_ERROR: KVM internal error
+ *     NVMX_VMENTRY_SUCCESS: Entered VMX non-root mode
+ *     NVMX_VMENTRY_VMFAIL:  Consistency check VMFail
+ *     NVMX_VMENTRY_VMEXIT:  Consistency check VMExit
+ *     NVMX_VMENTRY_KVM_INTERNAL_ERROR: KVM internal error
  */
 enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
                                                        bool from_vmentry)
@@ -3609,8 +3609,15 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
        unsigned long exit_qual;
        bool block_nested_events =
            vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
+       bool mtf_pending = vmx->nested.mtf_pending;
        struct kvm_lapic *apic = vcpu->arch.apic;
 
+       /*
+        * Clear the MTF state. If a higher priority VM-exit is delivered first,
+        * this state is discarded.
+        */
+       vmx->nested.mtf_pending = false;
+
        if (lapic_in_kernel(vcpu) &&
                test_bit(KVM_APIC_INIT, &apic->pending_events)) {
                if (block_nested_events)
@@ -3621,8 +3628,28 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
                return 0;
        }
 
+       /*
+        * Process any exceptions that are not debug traps before MTF.
+        */
+       if (vcpu->arch.exception.pending &&
+           !vmx_pending_dbg_trap(vcpu) &&
+           nested_vmx_check_exception(vcpu, &exit_qual)) {
+               if (block_nested_events)
+                       return -EBUSY;
+               nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
+               return 0;
+       }
+
+       if (mtf_pending) {
+               if (block_nested_events)
+                       return -EBUSY;
+               nested_vmx_update_pending_dbg(vcpu);
+               nested_vmx_vmexit(vcpu, EXIT_REASON_MONITOR_TRAP_FLAG, 0, 0);
+               return 0;
+       }
+
        if (vcpu->arch.exception.pending &&
-               nested_vmx_check_exception(vcpu, &exit_qual)) {
+           nested_vmx_check_exception(vcpu, &exit_qual)) {
                if (block_nested_events)
                        return -EBUSY;
                nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
@@ -5285,24 +5312,17 @@ fail:
        return 1;
 }
 
-
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-                                      struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+                                int size)
 {
-       unsigned long exit_qualification;
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        gpa_t bitmap, last_bitmap;
-       unsigned int port;
-       int size;
        u8 b;
 
-       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
-               return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
-       port = exit_qualification >> 16;
-       size = (exit_qualification & 7) + 1;
-
        last_bitmap = (gpa_t)-1;
        b = -1;
 
@@ -5329,8 +5349,26 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        return false;
 }
 
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+                                      struct vmcs12 *vmcs12)
+{
+       unsigned long exit_qualification;
+       unsigned short port;
+       int size;
+
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+       port = exit_qualification >> 16;
+       size = (exit_qualification & 7) + 1;
+
+       return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
- * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
+ * Return 1 if we should exit from L2 to L1 to handle an MSR access,
  * rather than handle it ourselves in L0. I.e., check whether L1 expressed
  * disinterest in the current event (read or write a specific MSR) by using an
  * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
@@ -5712,6 +5750,9 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
 
                        if (vmx->nested.nested_run_pending)
                                kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
+
+                       if (vmx->nested.mtf_pending)
+                               kvm_state.flags |= KVM_STATE_NESTED_MTF_PENDING;
                }
        }
 
@@ -5892,6 +5933,9 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
        vmx->nested.nested_run_pending =
                !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
 
+       vmx->nested.mtf_pending =
+               !!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING);
+
        ret = -EINVAL;
        if (nested_cpu_has_shadow_vmcs(vmcs12) &&
            vmcs12->vmcs_link_pointer != -1ull) {
@@ -5949,8 +5993,7 @@ void nested_vmx_set_vmcs_shadowing_bitmap(void)
  * bit in the high half is on if the corresponding bit in the control field
  * may be on. See also vmx_control_verify().
  */
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-                               bool apicv)
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
 {
        /*
         * Note that as a general rule, the high half of the MSRs (bits in
@@ -5977,7 +6020,7 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
                PIN_BASED_EXT_INTR_MASK |
                PIN_BASED_NMI_EXITING |
                PIN_BASED_VIRTUAL_NMIS |
-               (apicv ? PIN_BASED_POSTED_INTR : 0);
+               (enable_apicv ? PIN_BASED_POSTED_INTR : 0);
        msrs->pinbased_ctls_high |=
                PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
                PIN_BASED_VMX_PREEMPTION_TIMER;
index fc874d4..9aeda46 100644 (file)
@@ -17,8 +17,7 @@ enum nvmx_vmentry_status {
 };
 
 void vmx_leave_nested(struct kvm_vcpu *vcpu);
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-                               bool apicv);
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps);
 void nested_vmx_hardware_unsetup(void);
 __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
 void nested_vmx_set_vmcs_shadowing_bitmap(void);
@@ -34,6 +33,8 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
 int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
                        u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
 void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu);
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+                                int size);
 
 static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
 {
@@ -175,6 +176,11 @@ static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
        return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
 }
 
+static inline int nested_cpu_has_mtf(struct vmcs12 *vmcs12)
+{
+       return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
+}
+
 static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12)
 {
        return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);
index 3be25ec..40b1e61 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 static const struct x86_cpu_id vmx_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_VMX),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
+#endif
 
 bool __read_mostly enable_vpid = 1;
 module_param_named(vpid, enable_vpid, bool, 0444);
@@ -95,7 +97,7 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
-static bool __read_mostly enable_apicv = 1;
+bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
@@ -1175,6 +1177,10 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
                                           vmx->guest_msrs[i].mask);
 
        }
+
+       if (vmx->nested.need_vmcs12_to_shadow_sync)
+               nested_sync_vmcs12_to_shadow(vcpu);
+
        if (vmx->guest_state_loaded)
                return;
 
@@ -1599,6 +1605,40 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+
+/*
+ * Recognizes a pending MTF VM-exit and records the nested state for later
+ * delivery.
+ */
+static void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       if (!is_guest_mode(vcpu))
+               return;
+
+       /*
+        * Per the SDM, MTF takes priority over debug-trap exceptions besides
+        * T-bit traps. As instruction emulation is completed (i.e. at the
+        * instruction boundary), any #DB exception pending delivery must be a
+        * debug-trap. Record the pending MTF state to be delivered in
+        * vmx_check_nested_events().
+        */
+       if (nested_cpu_has_mtf(vmcs12) &&
+           (!vcpu->arch.exception.pending ||
+            vcpu->arch.exception.nr == DB_VECTOR))
+               vmx->nested.mtf_pending = true;
+       else
+               vmx->nested.mtf_pending = false;
+}
+
+static int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       vmx_update_emulated_instruction(vcpu);
+       return skip_emulated_instruction(vcpu);
+}
+
 static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
 {
        /*
@@ -3818,24 +3858,29 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
  * 2. If target vcpu isn't running(root mode), kick it to pick up the
  * interrupt from PIR in next vmentry.
  */
-static void vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
+static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        int r;
 
        r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
        if (!r)
-               return;
+               return 0;
+
+       if (!vcpu->arch.apicv_active)
+               return -1;
 
        if (pi_test_and_set_pir(vector, &vmx->pi_desc))
-               return;
+               return 0;
 
        /* If a previous notification has sent the IPI, nothing to do.  */
        if (pi_test_and_set_on(&vmx->pi_desc))
-               return;
+               return 0;
 
        if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
                kvm_vcpu_kick(vcpu);
+
+       return 0;
 }
 
 /*
@@ -6482,8 +6527,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
                vmcs_write32(PLE_WINDOW, vmx->ple_window);
        }
 
-       if (vmx->nested.need_vmcs12_to_shadow_sync)
-               nested_sync_vmcs12_to_shadow(vcpu);
+       /*
+        * We did this in prepare_switch_to_guest, because it needs to
+        * be within srcu_read_lock.
+        */
+       WARN_ON_ONCE(vmx->nested.need_vmcs12_to_shadow_sync);
 
        if (kvm_register_is_dirty(vcpu, VCPU_REGS_RSP))
                vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
@@ -6757,8 +6805,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
 
        if (nested)
                nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
-                                          vmx_capability.ept,
-                                          kvm_vcpu_apicv_active(vcpu));
+                                          vmx_capability.ept);
        else
                memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs));
 
@@ -6839,8 +6886,7 @@ static int __init vmx_check_processor_compat(void)
        if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0)
                return -EIO;
        if (nested)
-               nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept,
-                                          enable_apicv);
+               nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept);
        if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
                printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
                                smp_processor_id());
@@ -7101,6 +7147,40 @@ static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
        to_vmx(vcpu)->req_immediate_exit = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+                                 struct x86_instruction_info *info)
+{
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       unsigned short port;
+       bool intercept;
+       int size;
+
+       if (info->intercept == x86_intercept_in ||
+           info->intercept == x86_intercept_ins) {
+               port = info->src_val;
+               size = info->dst_bytes;
+       } else {
+               port = info->dst_val;
+               size = info->src_bytes;
+       }
+
+       /*
+        * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+        * VM-exits depend on the 'unconditional IO exiting' VM-execution
+        * control.
+        *
+        * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+        */
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               intercept = nested_cpu_has(vmcs12,
+                                          CPU_BASED_UNCOND_IO_EXITING);
+       else
+               intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+       /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+       return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
                               struct x86_instruction_info *info,
                               enum x86_intercept_stage stage)
@@ -7108,19 +7188,45 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+       switch (info->intercept) {
        /*
         * RDPID causes #UD if disabled through secondary execution controls.
         * Because it is marked as EmulateOnUD, we need to intercept it here.
         */
-       if (info->intercept == x86_intercept_rdtscp &&
-           !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
-               ctxt->exception.vector = UD_VECTOR;
-               ctxt->exception.error_code_valid = false;
-               return X86EMUL_PROPAGATE_FAULT;
-       }
+       case x86_intercept_rdtscp:
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+                       ctxt->exception.vector = UD_VECTOR;
+                       ctxt->exception.error_code_valid = false;
+                       return X86EMUL_PROPAGATE_FAULT;
+               }
+               break;
+
+       case x86_intercept_in:
+       case x86_intercept_ins:
+       case x86_intercept_out:
+       case x86_intercept_outs:
+               return vmx_check_intercept_io(vcpu, info);
+
+       case x86_intercept_lgdt:
+       case x86_intercept_lidt:
+       case x86_intercept_lldt:
+       case x86_intercept_ltr:
+       case x86_intercept_sgdt:
+       case x86_intercept_sidt:
+       case x86_intercept_sldt:
+       case x86_intercept_str:
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
+                       return X86EMUL_CONTINUE;
+
+               /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+               break;
 
        /* TODO: check more intercepts... */
-       return X86EMUL_CONTINUE;
+       default:
+               break;
+       }
+
+       return X86EMUL_UNHANDLEABLE;
 }
 
 #ifdef CONFIG_X86_64
@@ -7702,7 +7808,7 @@ static __init int hardware_setup(void)
 
        if (nested) {
                nested_vmx_setup_ctls_msrs(&vmcs_config.nested,
-                                          vmx_capability.ept, enable_apicv);
+                                          vmx_capability.ept);
 
                r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers);
                if (r)
@@ -7786,7 +7892,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
 
        .run = vmx_vcpu_run,
        .handle_exit = vmx_handle_exit,
-       .skip_emulated_instruction = skip_emulated_instruction,
+       .skip_emulated_instruction = vmx_skip_emulated_instruction,
+       .update_emulated_instruction = vmx_update_emulated_instruction,
        .set_interrupt_shadow = vmx_set_interrupt_shadow,
        .get_interrupt_shadow = vmx_get_interrupt_shadow,
        .patch_hypercall = vmx_patch_hypercall,
index 7f42cf3..e64da06 100644 (file)
@@ -150,6 +150,9 @@ struct nested_vmx {
        /* L2 must run next, and mustn't decide to exit to L1. */
        bool nested_run_pending;
 
+       /* Pending MTF VM-exit into L1.  */
+       bool mtf_pending;
+
        struct loaded_vmcs vmcs02;
 
        /*
index fb5d64e..5de2006 100644 (file)
@@ -6891,6 +6891,8 @@ restart:
                        kvm_rip_write(vcpu, ctxt->eip);
                        if (r && ctxt->tf)
                                r = kvm_vcpu_do_singlestep(vcpu);
+                       if (kvm_x86_ops->update_emulated_instruction)
+                               kvm_x86_ops->update_emulated_instruction(vcpu);
                        __kvm_set_rflags(vcpu, ctxt->eflags);
                }
 
@@ -7188,15 +7190,15 @@ static void kvm_timer_init(void)
 
        if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
 #ifdef CONFIG_CPU_FREQ
-               struct cpufreq_policy policy;
+               struct cpufreq_policy *policy;
                int cpu;
 
-               memset(&policy, 0, sizeof(policy));
                cpu = get_cpu();
-               cpufreq_get_policy(&policy, cpu);
-               if (policy.cpuinfo.max_freq)
-                       max_tsc_khz = policy.cpuinfo.max_freq;
+               policy = cpufreq_cpu_get(cpu);
+               if (policy && policy->cpuinfo.max_freq)
+                       max_tsc_khz = policy->cpuinfo.max_freq;
                put_cpu();
+               cpufreq_cpu_put(policy);
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -7306,12 +7308,12 @@ int kvm_arch_init(void *opaque)
        }
 
        if (!ops->cpu_has_kvm_support()) {
-               printk(KERN_ERR "kvm: no hardware support\n");
+               pr_err_ratelimited("kvm: no hardware support\n");
                r = -EOPNOTSUPP;
                goto out;
        }
        if (ops->disabled_by_bios()) {
-               printk(KERN_ERR "kvm: disabled by bios\n");
+               pr_err_ratelimited("kvm: disabled by bios\n");
                r = -EOPNOTSUPP;
                goto out;
        }
index 64229da..69309cd 100644 (file)
@@ -363,13 +363,8 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m,
 {
        const struct ptdump_range ptdump_ranges[] = {
 #ifdef CONFIG_X86_64
-
-#define normalize_addr_shift (64 - (__VIRTUAL_MASK_SHIFT + 1))
-#define normalize_addr(u) ((signed long)((u) << normalize_addr_shift) >> \
-                          normalize_addr_shift)
-
        {0, PTRS_PER_PGD * PGD_LEVEL_MULT / 2},
-       {normalize_addr(PTRS_PER_PGD * PGD_LEVEL_MULT / 2), ~0UL},
+       {GUARD_HOLE_END_ADDR, ~0UL},
 #else
        {0, ~0UL},
 #endif
index fa8506e..d19a2ed 100644 (file)
@@ -180,7 +180,7 @@ void efi_sync_low_kernel_mappings(void)
 static inline phys_addr_t
 virt_to_phys_or_null_size(void *va, unsigned long size)
 {
-       bool bad_size;
+       phys_addr_t pa;
 
        if (!va)
                return 0;
@@ -188,16 +188,13 @@ virt_to_phys_or_null_size(void *va, unsigned long size)
        if (virt_addr_valid(va))
                return virt_to_phys(va);
 
-       /*
-        * A fully aligned variable on the stack is guaranteed not to
-        * cross a page bounary. Try to catch strings on the stack by
-        * checking that 'size' is a power of two.
-        */
-       bad_size = size > PAGE_SIZE || !is_power_of_2(size);
+       pa = slow_virt_to_phys(va);
 
-       WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
+       /* check if the object crosses a page boundary */
+       if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK))
+               return 0;
 
-       return slow_virt_to_phys(va);
+       return pa;
 }
 
 #define virt_to_phys_or_null(addr)                             \
@@ -568,85 +565,25 @@ efi_thunk_set_virtual_address_map(unsigned long memory_map_size,
 
 static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
-       efi_status_t status;
-       u32 phys_tm, phys_tc;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_tm = virt_to_phys_or_null(tm);
-       phys_tc = virt_to_phys_or_null(tc);
-
-       status = efi_thunk(get_time, phys_tm, phys_tc);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static efi_status_t efi_thunk_set_time(efi_time_t *tm)
 {
-       efi_status_t status;
-       u32 phys_tm;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_tm = virt_to_phys_or_null(tm);
-
-       status = efi_thunk(set_time, phys_tm);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static efi_status_t
 efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
                          efi_time_t *tm)
 {
-       efi_status_t status;
-       u32 phys_enabled, phys_pending, phys_tm;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_enabled = virt_to_phys_or_null(enabled);
-       phys_pending = virt_to_phys_or_null(pending);
-       phys_tm = virt_to_phys_or_null(tm);
-
-       status = efi_thunk(get_wakeup_time, phys_enabled,
-                            phys_pending, phys_tm);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static efi_status_t
 efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
 {
-       efi_status_t status;
-       u32 phys_tm;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_tm = virt_to_phys_or_null(tm);
-
-       status = efi_thunk(set_wakeup_time, enabled, phys_tm);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static unsigned long efi_name_size(efi_char16_t *name)
@@ -658,6 +595,8 @@ static efi_status_t
 efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
                       u32 *attr, unsigned long *data_size, void *data)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        efi_status_t status;
        u32 phys_name, phys_vendor, phys_attr;
        u32 phys_data_size, phys_data;
@@ -665,14 +604,19 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
 
        spin_lock_irqsave(&efi_runtime_lock, flags);
 
+       *vnd = *vendor;
+
        phys_data_size = virt_to_phys_or_null(data_size);
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
        phys_attr = virt_to_phys_or_null(attr);
        phys_data = virt_to_phys_or_null_size(data, *data_size);
 
-       status = efi_thunk(get_variable, phys_name, phys_vendor,
-                          phys_attr, phys_data_size, phys_data);
+       if (!phys_name || (data && !phys_data))
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(get_variable, phys_name, phys_vendor,
+                                  phys_attr, phys_data_size, phys_data);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -683,19 +627,25 @@ static efi_status_t
 efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
                       u32 attr, unsigned long data_size, void *data)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        u32 phys_name, phys_vendor, phys_data;
        efi_status_t status;
        unsigned long flags;
 
        spin_lock_irqsave(&efi_runtime_lock, flags);
 
+       *vnd = *vendor;
+
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_data = virt_to_phys_or_null_size(data, data_size);
 
-       /* If data_size is > sizeof(u32) we've got problems */
-       status = efi_thunk(set_variable, phys_name, phys_vendor,
-                          attr, data_size, phys_data);
+       if (!phys_name || !phys_data)
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(set_variable, phys_name, phys_vendor,
+                                  attr, data_size, phys_data);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -707,6 +657,8 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
                                   u32 attr, unsigned long data_size,
                                   void *data)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        u32 phys_name, phys_vendor, phys_data;
        efi_status_t status;
        unsigned long flags;
@@ -714,13 +666,17 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
        if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
                return EFI_NOT_READY;
 
+       *vnd = *vendor;
+
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_data = virt_to_phys_or_null_size(data, data_size);
 
-       /* If data_size is > sizeof(u32) we've got problems */
-       status = efi_thunk(set_variable, phys_name, phys_vendor,
-                          attr, data_size, phys_data);
+       if (!phys_name || !phys_data)
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(set_variable, phys_name, phys_vendor,
+                                  attr, data_size, phys_data);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -732,39 +688,36 @@ efi_thunk_get_next_variable(unsigned long *name_size,
                            efi_char16_t *name,
                            efi_guid_t *vendor)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        efi_status_t status;
        u32 phys_name_size, phys_name, phys_vendor;
        unsigned long flags;
 
        spin_lock_irqsave(&efi_runtime_lock, flags);
 
+       *vnd = *vendor;
+
        phys_name_size = virt_to_phys_or_null(name_size);
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_name = virt_to_phys_or_null_size(name, *name_size);
 
-       status = efi_thunk(get_next_variable, phys_name_size,
-                          phys_name, phys_vendor);
+       if (!phys_name)
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(get_next_variable, phys_name_size,
+                                  phys_name, phys_vendor);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
+       *vendor = *vnd;
        return status;
 }
 
 static efi_status_t
 efi_thunk_get_next_high_mono_count(u32 *count)
 {
-       efi_status_t status;
-       u32 phys_count;
-       unsigned long flags;
-
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_count = virt_to_phys_or_null(count);
-       status = efi_thunk(get_next_high_mono_count, phys_count);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static void
index 7940912..507f4fb 100644 (file)
@@ -72,6 +72,9 @@
 #include <asm/mwait.h>
 #include <asm/pci_x86.h>
 #include <asm/cpu.h>
+#ifdef CONFIG_X86_IOPL_IOPERM
+#include <asm/io_bitmap.h>
+#endif
 
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
@@ -837,6 +840,25 @@ static void xen_load_sp0(unsigned long sp0)
        this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
 }
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+static void xen_update_io_bitmap(void)
+{
+       struct physdev_set_iobitmap iobitmap;
+       struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
+
+       native_tss_update_io_bitmap();
+
+       iobitmap.bitmap = (uint8_t *)(&tss->x86_tss) +
+                         tss->x86_tss.io_bitmap_base;
+       if (tss->x86_tss.io_bitmap_base == IO_BITMAP_OFFSET_INVALID)
+               iobitmap.nr_ports = 0;
+       else
+               iobitmap.nr_ports = IO_BITMAP_BITS;
+
+       HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &iobitmap);
+}
+#endif
+
 static void xen_io_delay(void)
 {
 }
@@ -1047,6 +1069,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .write_idt_entry = xen_write_idt_entry,
        .load_sp0 = xen_load_sp0,
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+       .update_io_bitmap = xen_update_io_bitmap,
+#endif
        .io_delay = xen_io_delay,
 
        /* Xen takes care of %gs when switching to usermode for us */
index 3f977c5..5cc775b 100644 (file)
@@ -412,7 +412,7 @@ void blk_insert_flush(struct request *rq)
         */
        if ((policy & REQ_FSEQ_DATA) &&
            !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
-               blk_mq_request_bypass_insert(rq, false);
+               blk_mq_request_bypass_insert(rq, false, false);
                return;
        }
 
index ca22afd..856356b 100644 (file)
@@ -361,13 +361,19 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
                                       bool has_sched,
                                       struct request *rq)
 {
-       /* dispatch flush rq directly */
-       if (rq->rq_flags & RQF_FLUSH_SEQ) {
-               spin_lock(&hctx->lock);
-               list_add(&rq->queuelist, &hctx->dispatch);
-               spin_unlock(&hctx->lock);
+       /*
+        * dispatch flush and passthrough rq directly
+        *
+        * passthrough request has to be added to hctx->dispatch directly.
+        * For some reason, device may be in one situation which can't
+        * handle FS request, so STS_RESOURCE is always returned and the
+        * FS request will be added to hctx->dispatch. However passthrough
+        * request may be required at that time for fixing the problem. If
+        * passthrough request is added to scheduler queue, there isn't any
+        * chance to dispatch it given we prioritize requests in hctx->dispatch.
+        */
+       if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq))
                return true;
-       }
 
        if (has_sched)
                rq->rq_flags |= RQF_SORTED;
@@ -391,8 +397,10 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head,
 
        WARN_ON(e && (rq->tag != -1));
 
-       if (blk_mq_sched_bypass_insert(hctx, !!e, rq))
+       if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) {
+               blk_mq_request_bypass_insert(rq, at_head, false);
                goto run;
+       }
 
        if (e && e->type->ops.insert_requests) {
                LIST_HEAD(list);
index fbacde4..586c9d6 100644 (file)
@@ -183,8 +183,8 @@ found_tag:
        return tag + tag_offset;
 }
 
-void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags,
-                   struct blk_mq_ctx *ctx, unsigned int tag)
+void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
+                   unsigned int tag)
 {
        if (!blk_mq_tag_is_reserved(tags, tag)) {
                const int real_tag = tag - tags->nr_reserved_tags;
index 15bc74a..2b8321e 100644 (file)
@@ -26,8 +26,8 @@ extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int r
 extern void blk_mq_free_tags(struct blk_mq_tags *tags);
 
 extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data);
-extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags,
-                          struct blk_mq_ctx *ctx, unsigned int tag);
+extern void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
+                          unsigned int tag);
 extern int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
                                        struct blk_mq_tags **tags,
                                        unsigned int depth, bool can_grow);
index a12b176..d92088d 100644 (file)
@@ -477,9 +477,9 @@ static void __blk_mq_free_request(struct request *rq)
        blk_pm_mark_last_busy(rq);
        rq->mq_hctx = NULL;
        if (rq->tag != -1)
-               blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag);
+               blk_mq_put_tag(hctx->tags, ctx, rq->tag);
        if (sched_tag != -1)
-               blk_mq_put_tag(hctx, hctx->sched_tags, ctx, sched_tag);
+               blk_mq_put_tag(hctx->sched_tags, ctx, sched_tag);
        blk_mq_sched_restart(hctx);
        blk_queue_exit(q);
 }
@@ -735,7 +735,7 @@ static void blk_mq_requeue_work(struct work_struct *work)
                 * merge.
                 */
                if (rq->rq_flags & RQF_DONTPREP)
-                       blk_mq_request_bypass_insert(rq, false);
+                       blk_mq_request_bypass_insert(rq, false, false);
                else
                        blk_mq_sched_insert_request(rq, true, false, false);
        }
@@ -1286,7 +1286,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
                        q->mq_ops->commit_rqs(hctx);
 
                spin_lock(&hctx->lock);
-               list_splice_init(list, &hctx->dispatch);
+               list_splice_tail_init(list, &hctx->dispatch);
                spin_unlock(&hctx->lock);
 
                /*
@@ -1677,12 +1677,16 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
  * Should only be used carefully, when the caller knows we want to
  * bypass a potential IO scheduler on the target device.
  */
-void blk_mq_request_bypass_insert(struct request *rq, bool run_queue)
+void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
+                                 bool run_queue)
 {
        struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
 
        spin_lock(&hctx->lock);
-       list_add_tail(&rq->queuelist, &hctx->dispatch);
+       if (at_head)
+               list_add(&rq->queuelist, &hctx->dispatch);
+       else
+               list_add_tail(&rq->queuelist, &hctx->dispatch);
        spin_unlock(&hctx->lock);
 
        if (run_queue)
@@ -1849,7 +1853,7 @@ insert:
        if (bypass_insert)
                return BLK_STS_RESOURCE;
 
-       blk_mq_request_bypass_insert(rq, run_queue);
+       blk_mq_request_bypass_insert(rq, false, run_queue);
        return BLK_STS_OK;
 }
 
@@ -1876,7 +1880,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
 
        ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true);
        if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
-               blk_mq_request_bypass_insert(rq, true);
+               blk_mq_request_bypass_insert(rq, false, true);
        else if (ret != BLK_STS_OK)
                blk_mq_end_request(rq, ret);
 
@@ -1910,7 +1914,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                if (ret != BLK_STS_OK) {
                        if (ret == BLK_STS_RESOURCE ||
                                        ret == BLK_STS_DEV_RESOURCE) {
-                               blk_mq_request_bypass_insert(rq,
+                               blk_mq_request_bypass_insert(rq, false,
                                                        list_empty(list));
                                break;
                        }
@@ -3398,7 +3402,6 @@ static void blk_mq_poll_stats_fn(struct blk_stat_callback *cb)
 }
 
 static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
-                                      struct blk_mq_hw_ctx *hctx,
                                       struct request *rq)
 {
        unsigned long ret = 0;
@@ -3431,7 +3434,6 @@ static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
 }
 
 static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
-                                    struct blk_mq_hw_ctx *hctx,
                                     struct request *rq)
 {
        struct hrtimer_sleeper hs;
@@ -3451,7 +3453,7 @@ static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
        if (q->poll_nsec > 0)
                nsecs = q->poll_nsec;
        else
-               nsecs = blk_mq_poll_nsecs(q, hctx, rq);
+               nsecs = blk_mq_poll_nsecs(q, rq);
 
        if (!nsecs)
                return false;
@@ -3506,7 +3508,7 @@ static bool blk_mq_poll_hybrid(struct request_queue *q,
                        return false;
        }
 
-       return blk_mq_poll_hybrid_sleep(q, hctx, rq);
+       return blk_mq_poll_hybrid_sleep(q, rq);
 }
 
 /**
index eaaca8f..10bfdfb 100644 (file)
@@ -66,7 +66,8 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
  */
 void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
                                bool at_head);
-void blk_mq_request_bypass_insert(struct request *rq, bool run_queue);
+void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
+                                 bool run_queue);
 void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
                                struct list_head *list);
 
@@ -199,7 +200,7 @@ static inline bool blk_mq_get_dispatch_budget(struct blk_mq_hw_ctx *hctx)
 static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx,
                                           struct request *rq)
 {
-       blk_mq_put_tag(hctx, hctx->tags, rq->mq_ctx, rq->tag);
+       blk_mq_put_tag(hctx->tags, rq->mq_ctx, rq->tag);
        rq->tag = -1;
 
        if (rq->rq_flags & RQF_MQ_INFLIGHT) {
index b5516b0..6e9ec6e 100644 (file)
@@ -55,12 +55,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
 }
 #endif
 
+static bool acpi_no_watchdog;
+
 static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
 {
        const struct acpi_table_wdat *wdat = NULL;
        acpi_status status;
 
-       if (acpi_disabled)
+       if (acpi_disabled || acpi_no_watchdog)
                return NULL;
 
        status = acpi_get_table(ACPI_SIG_WDAT, 0,
@@ -88,6 +90,14 @@ bool acpi_has_watchdog(void)
 }
 EXPORT_SYMBOL_GPL(acpi_has_watchdog);
 
+/* ACPI watchdog can be disabled on boot command line */
+static int __init disable_acpi_watchdog(char *str)
+{
+       acpi_no_watchdog = true;
+       return 1;
+}
+__setup("acpi_no_watchdog", disable_acpi_watchdog);
+
 void __init acpi_watchdog_init(void)
 {
        const struct acpi_wdat_entry *entries;
@@ -126,12 +136,11 @@ void __init acpi_watchdog_init(void)
                gas = &entries[i].register_region;
 
                res.start = gas->address;
+               res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
                if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
                        res.flags = IORESOURCE_MEM;
-                       res.end = res.start + ALIGN(gas->access_width, 4) - 1;
                } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
                        res.flags = IORESOURCE_IO;
-                       res.end = res.start + gas->access_width - 1;
                } else {
                        pr_warn("Unsupported address space: %u\n",
                                gas->space_id);
index 0b081de..de8d354 100644 (file)
@@ -608,6 +608,13 @@ static void software_node_release(struct kobject *kobj)
 {
        struct swnode *swnode = kobj_to_swnode(kobj);
 
+       if (swnode->parent) {
+               ida_simple_remove(&swnode->parent->child_ids, swnode->id);
+               list_del(&swnode->entry);
+       } else {
+               ida_simple_remove(&swnode_root_ids, swnode->id);
+       }
+
        if (swnode->allocated) {
                property_entries_free(swnode->node->properties);
                kfree(swnode->node);
@@ -773,13 +780,6 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
        if (!swnode)
                return;
 
-       if (swnode->parent) {
-               ida_simple_remove(&swnode->parent->child_ids, swnode->id);
-               list_del(&swnode->entry);
-       } else {
-               ida_simple_remove(&swnode_root_ids, swnode->id);
-       }
-
        kobject_put(&swnode->kobj);
 }
 EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
index cd3612e..8ef65c0 100644 (file)
@@ -853,14 +853,17 @@ static void reset_fdc_info(int mode)
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+       unsigned int new_fdc = fdc;
+
        if (drive >= 0 && drive < N_DRIVE) {
-               fdc = FDC(drive);
+               new_fdc = FDC(drive);
                current_drive = drive;
        }
-       if (fdc != 1 && fdc != 0) {
+       if (new_fdc >= N_FDC) {
                pr_info("bad fdc value\n");
                return;
        }
+       fdc = new_fdc;
        set_dor(fdc, ~0, 8);
 #if N_FDC > 1
        set_dor(1 - fdc, ~8, 0);
index bc83786..62b6608 100644 (file)
@@ -14,9 +14,6 @@
 #include <linux/fault-inject.h>
 
 struct nullb_cmd {
-       struct list_head list;
-       struct llist_node ll_list;
-       struct __call_single_data csd;
        struct request *rq;
        struct bio *bio;
        unsigned int tag;
index 1651079..1330604 100644 (file)
@@ -1518,8 +1518,6 @@ static int setup_commands(struct nullb_queue *nq)
 
        for (i = 0; i < nq->queue_depth; i++) {
                cmd = &nq->cmds[i];
-               INIT_LIST_HEAD(&cmd->list);
-               cmd->ll_list.next = NULL;
                cmd->tag = -1U;
        }
 
index 117cfc8..cda5cf9 100644 (file)
@@ -276,7 +276,7 @@ static const struct block_device_operations pcd_bdops = {
        .release        = pcd_block_release,
        .ioctl          = pcd_block_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl          = blkdev_compat_ptr_ioctl,
+       .compat_ioctl   = blkdev_compat_ptr_ioctl,
 #endif
        .check_events   = pcd_block_check_events,
 };
index 886b263..c51292c 100644 (file)
@@ -519,7 +519,7 @@ static const struct block_device_operations gdrom_bdops = {
        .check_events           = gdrom_bdops_check_events,
        .ioctl                  = gdrom_bdops_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl                  = blkdev_compat_ptr_ioctl,
+       .compat_ioctl           = blkdev_compat_ptr_ioctl,
 #endif
 };
 
index cbe6c94..808874b 100644 (file)
@@ -1076,9 +1076,17 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
                        pol = policy->last_policy;
                } else if (def_gov) {
                        pol = cpufreq_parse_policy(def_gov->name);
-               } else {
-                       return -ENODATA;
+                       /*
+                        * In case the default governor is neiter "performance"
+                        * nor "powersave", fall back to the initial policy
+                        * value set by the driver.
+                        */
+                       if (pol == CPUFREQ_POLICY_UNKNOWN)
+                               pol = policy->policy;
                }
+               if (pol != CPUFREQ_POLICY_PERFORMANCE &&
+                   pol != CPUFREQ_POLICY_POWERSAVE)
+                       return -ENODATA;
        }
 
        return cpufreq_set_policy(policy, gov, pol);
index cceee8b..7dcf209 100644 (file)
@@ -738,7 +738,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
 {
        struct devfreq *devfreq;
        struct devfreq_governor *governor;
-       static atomic_t devfreq_no = ATOMIC_INIT(-1);
        int err = 0;
 
        if (!dev || !profile || !governor_name) {
@@ -800,8 +799,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
        atomic_set(&devfreq->suspend_count, 0);
 
-       dev_set_name(&devfreq->dev, "devfreq%d",
-                               atomic_inc_return(&devfreq_no));
+       dev_set_name(&devfreq->dev, "%s", dev_name(dev));
        err = device_register(&devfreq->dev);
        if (err) {
                mutex_unlock(&devfreq->lock);
index d409785..c343c7c 100644 (file)
@@ -108,6 +108,7 @@ static int dma_buf_release(struct inode *inode, struct file *file)
                dma_resv_fini(dmabuf->resv);
 
        module_put(dmabuf->owner);
+       kfree(dmabuf->name);
        kfree(dmabuf);
        return 0;
 }
index e51d836..1092d4c 100644 (file)
@@ -1947,8 +1947,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
                return;
        }
 
-       spin_lock(&cohc->lock);
-
        /*
         * When we reach this point, at least one queue item
         * should have been moved over from cohc->queue to
@@ -1969,8 +1967,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
        if (coh901318_queue_start(cohc) == NULL)
                cohc->busy = 0;
 
-       spin_unlock(&cohc->lock);
-
        /*
         * This tasklet will remove items from cohc->active
         * and thus terminates them.
index 1d73478..df47be6 100644 (file)
@@ -204,6 +204,7 @@ static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
        minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL);
        if (minor < 0) {
                rc = minor;
+               kfree(dev);
                goto ida_err;
        }
 
@@ -212,7 +213,6 @@ static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
        rc = device_register(dev);
        if (rc < 0) {
                dev_err(&idxd->pdev->dev, "device register failed\n");
-               put_device(dev);
                goto dev_reg_err;
        }
        idxd_cdev->minor = minor;
@@ -221,8 +221,8 @@ static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
 
  dev_reg_err:
        ida_simple_remove(&cdev_ctx->minor_ida, MINOR(dev->devt));
+       put_device(dev);
  ida_err:
-       kfree(dev);
        idxd_cdev->dev = NULL;
        return rc;
 }
index 6d907fe..6ca6e52 100644 (file)
@@ -124,6 +124,7 @@ static int idxd_config_bus_probe(struct device *dev)
                rc = idxd_device_config(idxd);
                if (rc < 0) {
                        spin_unlock_irqrestore(&idxd->dev_lock, flags);
+                       module_put(THIS_MODULE);
                        dev_warn(dev, "Device config failed: %d\n", rc);
                        return rc;
                }
@@ -132,6 +133,7 @@ static int idxd_config_bus_probe(struct device *dev)
                rc = idxd_device_enable(idxd);
                if (rc < 0) {
                        spin_unlock_irqrestore(&idxd->dev_lock, flags);
+                       module_put(THIS_MODULE);
                        dev_warn(dev, "Device enable failed: %d\n", rc);
                        return rc;
                }
@@ -142,6 +144,7 @@ static int idxd_config_bus_probe(struct device *dev)
                rc = idxd_register_dma_device(idxd);
                if (rc < 0) {
                        spin_unlock_irqrestore(&idxd->dev_lock, flags);
+                       module_put(THIS_MODULE);
                        dev_dbg(dev, "Failed to register dmaengine device\n");
                        return rc;
                }
@@ -516,7 +519,7 @@ static ssize_t group_tokens_reserved_store(struct device *dev,
        if (val > idxd->max_tokens)
                return -EINVAL;
 
-       if (val > idxd->nr_tokens)
+       if (val > idxd->nr_tokens + group->tokens_reserved)
                return -EINVAL;
 
        group->tokens_reserved = val;
@@ -901,6 +904,20 @@ static ssize_t wq_size_show(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%u\n", wq->size);
 }
 
+static int total_claimed_wq_size(struct idxd_device *idxd)
+{
+       int i;
+       int wq_size = 0;
+
+       for (i = 0; i < idxd->max_wqs; i++) {
+               struct idxd_wq *wq = &idxd->wqs[i];
+
+               wq_size += wq->size;
+       }
+
+       return wq_size;
+}
+
 static ssize_t wq_size_store(struct device *dev,
                             struct device_attribute *attr, const char *buf,
                             size_t count)
@@ -920,7 +937,7 @@ static ssize_t wq_size_store(struct device *dev,
        if (wq->state != IDXD_WQ_DISABLED)
                return -EPERM;
 
-       if (size > idxd->max_wq_size)
+       if (size + total_claimed_wq_size(idxd) - wq->size > idxd->max_wq_size)
                return -EINVAL;
 
        wq->size = size;
@@ -999,12 +1016,14 @@ static ssize_t wq_type_store(struct device *dev,
                return -EPERM;
 
        old_type = wq->type;
-       if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_KERNEL]))
+       if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_NONE]))
+               wq->type = IDXD_WQT_NONE;
+       else if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_KERNEL]))
                wq->type = IDXD_WQT_KERNEL;
        else if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_USER]))
                wq->type = IDXD_WQT_USER;
        else
-               wq->type = IDXD_WQT_NONE;
+               return -EINVAL;
 
        /* If we are changing queue type, clear the name */
        if (wq->type != old_type)
index 066b21a..4d4477d 100644 (file)
@@ -1331,13 +1331,14 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
        sdma_channel_synchronize(chan);
 
-       if (sdmac->event_id0)
+       if (sdmac->event_id0 >= 0)
                sdma_event_disable(sdmac, sdmac->event_id0);
        if (sdmac->event_id1)
                sdma_event_disable(sdmac, sdmac->event_id1);
 
        sdmac->event_id0 = 0;
        sdmac->event_id1 = 0;
+       sdmac->context_loaded = false;
 
        sdma_set_channel_priority(sdmac, 0);
 
@@ -1631,7 +1632,7 @@ static int sdma_config(struct dma_chan *chan,
        memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
 
        /* Set ENBLn earlier to make sure dma request triggered after that */
-       if (sdmac->event_id0) {
+       if (sdmac->event_id0 >= 0) {
                if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
                        return -EINVAL;
                sdma_event_enable(sdmac, sdmac->event_id0);
index 3a45079..4a750e2 100644 (file)
@@ -281,7 +281,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get(
 
        /* Do not allocate if desc are waiting for ack */
        list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
-               if (async_tx_test_ack(&dma_desc->txd)) {
+               if (async_tx_test_ack(&dma_desc->txd) && !dma_desc->cb_count) {
                        list_del(&dma_desc->node);
                        spin_unlock_irqrestore(&tdc->lock, flags);
                        dma_desc->txd.flags = 0;
@@ -756,10 +756,6 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
        bool was_busy;
 
        spin_lock_irqsave(&tdc->lock, flags);
-       if (list_empty(&tdc->pending_sg_req)) {
-               spin_unlock_irqrestore(&tdc->lock, flags);
-               return 0;
-       }
 
        if (!tdc->busy)
                goto skip_dma_stop;
index ea79c2d..0536866 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
@@ -96,6 +97,24 @@ struct udma_match_data {
        u32 level_start_idx[];
 };
 
+struct udma_hwdesc {
+       size_t cppi5_desc_size;
+       void *cppi5_desc_vaddr;
+       dma_addr_t cppi5_desc_paddr;
+
+       /* TR descriptor internal pointers */
+       void *tr_req_base;
+       struct cppi5_tr_resp_t *tr_resp_base;
+};
+
+struct udma_rx_flush {
+       struct udma_hwdesc hwdescs[2];
+
+       size_t buffer_size;
+       void *buffer_vaddr;
+       dma_addr_t buffer_paddr;
+};
+
 struct udma_dev {
        struct dma_device ddev;
        struct device *dev;
@@ -112,6 +131,8 @@ struct udma_dev {
        struct list_head desc_to_purge;
        spinlock_t lock;
 
+       struct udma_rx_flush rx_flush;
+
        int tchan_cnt;
        int echan_cnt;
        int rchan_cnt;
@@ -130,16 +151,6 @@ struct udma_dev {
        u32 psil_base;
 };
 
-struct udma_hwdesc {
-       size_t cppi5_desc_size;
-       void *cppi5_desc_vaddr;
-       dma_addr_t cppi5_desc_paddr;
-
-       /* TR descriptor internal pointers */
-       void *tr_req_base;
-       struct cppi5_tr_resp_t *tr_resp_base;
-};
-
 struct udma_desc {
        struct virt_dma_desc vd;
 
@@ -169,7 +180,7 @@ enum udma_chan_state {
 
 struct udma_tx_drain {
        struct delayed_work work;
-       unsigned long jiffie;
+       ktime_t tstamp;
        u32 residue;
 };
 
@@ -502,7 +513,7 @@ static bool udma_is_chan_paused(struct udma_chan *uc)
 {
        u32 val, pause_mask;
 
-       switch (uc->desc->dir) {
+       switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
                val = udma_rchanrt_read(uc->rchan,
                                        UDMA_RCHAN_RT_PEER_RT_EN_REG);
@@ -551,12 +562,17 @@ static void udma_sync_for_device(struct udma_chan *uc, int idx)
        }
 }
 
+static inline dma_addr_t udma_get_rx_flush_hwdesc_paddr(struct udma_chan *uc)
+{
+       return uc->ud->rx_flush.hwdescs[uc->config.pkt_mode].cppi5_desc_paddr;
+}
+
 static int udma_push_to_ring(struct udma_chan *uc, int idx)
 {
        struct udma_desc *d = uc->desc;
-
        struct k3_ring *ring = NULL;
-       int ret = -EINVAL;
+       dma_addr_t paddr;
+       int ret;
 
        switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
@@ -567,21 +583,37 @@ static int udma_push_to_ring(struct udma_chan *uc, int idx)
                ring = uc->tchan->t_ring;
                break;
        default:
-               break;
+               return -EINVAL;
        }
 
-       if (ring) {
-               dma_addr_t desc_addr = udma_curr_cppi5_desc_paddr(d, idx);
+       /* RX flush packet: idx == -1 is only passed in case of DEV_TO_MEM */
+       if (idx == -1) {
+               paddr = udma_get_rx_flush_hwdesc_paddr(uc);
+       } else {
+               paddr = udma_curr_cppi5_desc_paddr(d, idx);
 
                wmb(); /* Ensure that writes are not moved over this point */
                udma_sync_for_device(uc, idx);
-               ret = k3_ringacc_ring_push(ring, &desc_addr);
-               uc->in_ring_cnt++;
        }
 
+       ret = k3_ringacc_ring_push(ring, &paddr);
+       if (!ret)
+               uc->in_ring_cnt++;
+
        return ret;
 }
 
+static bool udma_desc_is_rx_flush(struct udma_chan *uc, dma_addr_t addr)
+{
+       if (uc->config.dir != DMA_DEV_TO_MEM)
+               return false;
+
+       if (addr == udma_get_rx_flush_hwdesc_paddr(uc))
+               return true;
+
+       return false;
+}
+
 static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
 {
        struct k3_ring *ring = NULL;
@@ -610,6 +642,10 @@ static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
                if (cppi5_desc_is_tdcm(*addr))
                        return ret;
 
+               /* Check for flush descriptor */
+               if (udma_desc_is_rx_flush(uc, *addr))
+                       return -ENOENT;
+
                d = udma_udma_desc_from_paddr(uc, *addr);
 
                if (d)
@@ -890,6 +926,9 @@ static int udma_stop(struct udma_chan *uc)
 
        switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
+               if (!uc->cyclic && !uc->desc)
+                       udma_push_to_ring(uc, -1);
+
                udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG,
                                   UDMA_PEER_RT_EN_ENABLE |
                                   UDMA_PEER_RT_EN_TEARDOWN);
@@ -946,9 +985,10 @@ static bool udma_is_desc_really_done(struct udma_chan *uc, struct udma_desc *d)
        peer_bcnt = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG);
        bcnt = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_BCNT_REG);
 
+       /* Transfer is incomplete, store current residue and time stamp */
        if (peer_bcnt < bcnt) {
                uc->tx_drain.residue = bcnt - peer_bcnt;
-               uc->tx_drain.jiffie = jiffies;
+               uc->tx_drain.tstamp = ktime_get();
                return false;
        }
 
@@ -961,35 +1001,59 @@ static void udma_check_tx_completion(struct work_struct *work)
                                            tx_drain.work.work);
        bool desc_done = true;
        u32 residue_diff;
-       unsigned long jiffie_diff, delay;
+       ktime_t time_diff;
+       unsigned long delay;
+
+       while (1) {
+               if (uc->desc) {
+                       /* Get previous residue and time stamp */
+                       residue_diff = uc->tx_drain.residue;
+                       time_diff = uc->tx_drain.tstamp;
+                       /*
+                        * Get current residue and time stamp or see if
+                        * transfer is complete
+                        */
+                       desc_done = udma_is_desc_really_done(uc, uc->desc);
+               }
 
-       if (uc->desc) {
-               residue_diff = uc->tx_drain.residue;
-               jiffie_diff = uc->tx_drain.jiffie;
-               desc_done = udma_is_desc_really_done(uc, uc->desc);
-       }
-
-       if (!desc_done) {
-               jiffie_diff = uc->tx_drain.jiffie - jiffie_diff;
-               residue_diff -= uc->tx_drain.residue;
-               if (residue_diff) {
-                       /* Try to guess when we should check next time */
-                       residue_diff /= jiffie_diff;
-                       delay = uc->tx_drain.residue / residue_diff / 3;
-                       if (jiffies_to_msecs(delay) < 5)
-                               delay = 0;
-               } else {
-                       /* No progress, check again in 1 second  */
-                       delay = HZ;
+               if (!desc_done) {
+                       /*
+                        * Find the time delta and residue delta w.r.t
+                        * previous poll
+                        */
+                       time_diff = ktime_sub(uc->tx_drain.tstamp,
+                                             time_diff) + 1;
+                       residue_diff -= uc->tx_drain.residue;
+                       if (residue_diff) {
+                               /*
+                                * Try to guess when we should check
+                                * next time by calculating rate at
+                                * which data is being drained at the
+                                * peer device
+                                */
+                               delay = (time_diff / residue_diff) *
+                                       uc->tx_drain.residue;
+                       } else {
+                               /* No progress, check again in 1 second  */
+                               schedule_delayed_work(&uc->tx_drain.work, HZ);
+                               break;
+                       }
+
+                       usleep_range(ktime_to_us(delay),
+                                    ktime_to_us(delay) + 10);
+                       continue;
                }
 
-               schedule_delayed_work(&uc->tx_drain.work, delay);
-       } else if (uc->desc) {
-               struct udma_desc *d = uc->desc;
+               if (uc->desc) {
+                       struct udma_desc *d = uc->desc;
 
-               uc->bcnt += d->residue;
-               udma_start(uc);
-               vchan_cookie_complete(&d->vd);
+                       uc->bcnt += d->residue;
+                       udma_start(uc);
+                       vchan_cookie_complete(&d->vd);
+                       break;
+               }
+
+               break;
        }
 }
 
@@ -1033,29 +1097,27 @@ static irqreturn_t udma_ring_irq_handler(int irq, void *data)
                        goto out;
                }
 
-               if (uc->cyclic) {
-                       /* push the descriptor back to the ring */
-                       if (d == uc->desc) {
+               if (d == uc->desc) {
+                       /* active descriptor */
+                       if (uc->cyclic) {
                                udma_cyclic_packet_elapsed(uc);
                                vchan_cyclic_callback(&d->vd);
-                       }
-               } else {
-                       bool desc_done = false;
-
-                       if (d == uc->desc) {
-                               desc_done = udma_is_desc_really_done(uc, d);
-
-                               if (desc_done) {
+                       } else {
+                               if (udma_is_desc_really_done(uc, d)) {
                                        uc->bcnt += d->residue;
                                        udma_start(uc);
+                                       vchan_cookie_complete(&d->vd);
                                } else {
                                        schedule_delayed_work(&uc->tx_drain.work,
                                                              0);
                                }
                        }
-
-                       if (desc_done)
-                               vchan_cookie_complete(&d->vd);
+               } else {
+                       /*
+                        * terminated descriptor, mark the descriptor as
+                        * completed to update the channel's cookie marker
+                        */
+                       dma_cookie_complete(&d->vd.tx);
                }
        }
 out:
@@ -1965,36 +2027,81 @@ static struct udma_desc *udma_alloc_tr_desc(struct udma_chan *uc,
        return d;
 }
 
+/**
+ * udma_get_tr_counters - calculate TR counters for a given length
+ * @len: Length of the trasnfer
+ * @align_to: Preferred alignment
+ * @tr0_cnt0: First TR icnt0
+ * @tr0_cnt1: First TR icnt1
+ * @tr1_cnt0: Second (if used) TR icnt0
+ *
+ * For len < SZ_64K only one TR is enough, tr1_cnt0 is not updated
+ * For len >= SZ_64K two TRs are used in a simple way:
+ * First TR: SZ_64K-alignment blocks (tr0_cnt0, tr0_cnt1)
+ * Second TR: the remaining length (tr1_cnt0)
+ *
+ * Returns the number of TRs the length needs (1 or 2)
+ * -EINVAL if the length can not be supported
+ */
+static int udma_get_tr_counters(size_t len, unsigned long align_to,
+                               u16 *tr0_cnt0, u16 *tr0_cnt1, u16 *tr1_cnt0)
+{
+       if (len < SZ_64K) {
+               *tr0_cnt0 = len;
+               *tr0_cnt1 = 1;
+
+               return 1;
+       }
+
+       if (align_to > 3)
+               align_to = 3;
+
+realign:
+       *tr0_cnt0 = SZ_64K - BIT(align_to);
+       if (len / *tr0_cnt0 >= SZ_64K) {
+               if (align_to) {
+                       align_to--;
+                       goto realign;
+               }
+               return -EINVAL;
+       }
+
+       *tr0_cnt1 = len / *tr0_cnt0;
+       *tr1_cnt0 = len % *tr0_cnt0;
+
+       return 2;
+}
+
 static struct udma_desc *
 udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
                      unsigned int sglen, enum dma_transfer_direction dir,
                      unsigned long tx_flags, void *context)
 {
-       enum dma_slave_buswidth dev_width;
        struct scatterlist *sgent;
        struct udma_desc *d;
-       size_t tr_size;
        struct cppi5_tr_type1_t *tr_req = NULL;
+       u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
        unsigned int i;
-       u32 burst;
+       size_t tr_size;
+       int num_tr = 0;
+       int tr_idx = 0;
 
-       if (dir == DMA_DEV_TO_MEM) {
-               dev_width = uc->cfg.src_addr_width;
-               burst = uc->cfg.src_maxburst;
-       } else if (dir == DMA_MEM_TO_DEV) {
-               dev_width = uc->cfg.dst_addr_width;
-               burst = uc->cfg.dst_maxburst;
-       } else {
-               dev_err(uc->ud->dev, "%s: bad direction?\n", __func__);
+       if (!is_slave_direction(dir)) {
+               dev_err(uc->ud->dev, "Only slave cyclic is supported\n");
                return NULL;
        }
 
-       if (!burst)
-               burst = 1;
+       /* estimate the number of TRs we will need */
+       for_each_sg(sgl, sgent, sglen, i) {
+               if (sg_dma_len(sgent) < SZ_64K)
+                       num_tr++;
+               else
+                       num_tr += 2;
+       }
 
        /* Now allocate and setup the descriptor. */
        tr_size = sizeof(struct cppi5_tr_type1_t);
-       d = udma_alloc_tr_desc(uc, tr_size, sglen, dir);
+       d = udma_alloc_tr_desc(uc, tr_size, num_tr, dir);
        if (!d)
                return NULL;
 
@@ -2002,19 +2109,46 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 
        tr_req = d->hwdesc[0].tr_req_base;
        for_each_sg(sgl, sgent, sglen, i) {
-               d->residue += sg_dma_len(sgent);
+               dma_addr_t sg_addr = sg_dma_address(sgent);
+
+               num_tr = udma_get_tr_counters(sg_dma_len(sgent), __ffs(sg_addr),
+                                             &tr0_cnt0, &tr0_cnt1, &tr1_cnt0);
+               if (num_tr < 0) {
+                       dev_err(uc->ud->dev, "size %u is not supported\n",
+                               sg_dma_len(sgent));
+                       udma_free_hwdesc(uc, d);
+                       kfree(d);
+                       return NULL;
+               }
 
                cppi5_tr_init(&tr_req[i].flags, CPPI5_TR_TYPE1, false, false,
                              CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
                cppi5_tr_csf_set(&tr_req[i].flags, CPPI5_TR_CSF_SUPR_EVT);
 
-               tr_req[i].addr = sg_dma_address(sgent);
-               tr_req[i].icnt0 = burst * dev_width;
-               tr_req[i].dim1 = burst * dev_width;
-               tr_req[i].icnt1 = sg_dma_len(sgent) / tr_req[i].icnt0;
+               tr_req[tr_idx].addr = sg_addr;
+               tr_req[tr_idx].icnt0 = tr0_cnt0;
+               tr_req[tr_idx].icnt1 = tr0_cnt1;
+               tr_req[tr_idx].dim1 = tr0_cnt0;
+               tr_idx++;
+
+               if (num_tr == 2) {
+                       cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
+                                     false, false,
+                                     CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
+                                        CPPI5_TR_CSF_SUPR_EVT);
+
+                       tr_req[tr_idx].addr = sg_addr + tr0_cnt1 * tr0_cnt0;
+                       tr_req[tr_idx].icnt0 = tr1_cnt0;
+                       tr_req[tr_idx].icnt1 = 1;
+                       tr_req[tr_idx].dim1 = tr1_cnt0;
+                       tr_idx++;
+               }
+
+               d->residue += sg_dma_len(sgent);
        }
 
-       cppi5_tr_csf_set(&tr_req[i - 1].flags, CPPI5_TR_CSF_EOP);
+       cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, CPPI5_TR_CSF_EOP);
 
        return d;
 }
@@ -2319,47 +2453,66 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
                        size_t buf_len, size_t period_len,
                        enum dma_transfer_direction dir, unsigned long flags)
 {
-       enum dma_slave_buswidth dev_width;
        struct udma_desc *d;
-       size_t tr_size;
+       size_t tr_size, period_addr;
        struct cppi5_tr_type1_t *tr_req;
-       unsigned int i;
        unsigned int periods = buf_len / period_len;
-       u32 burst;
+       u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
+       unsigned int i;
+       int num_tr;
 
-       if (dir == DMA_DEV_TO_MEM) {
-               dev_width = uc->cfg.src_addr_width;
-               burst = uc->cfg.src_maxburst;
-       } else if (dir == DMA_MEM_TO_DEV) {
-               dev_width = uc->cfg.dst_addr_width;
-               burst = uc->cfg.dst_maxburst;
-       } else {
-               dev_err(uc->ud->dev, "%s: bad direction?\n", __func__);
+       if (!is_slave_direction(dir)) {
+               dev_err(uc->ud->dev, "Only slave cyclic is supported\n");
                return NULL;
        }
 
-       if (!burst)
-               burst = 1;
+       num_tr = udma_get_tr_counters(period_len, __ffs(buf_addr), &tr0_cnt0,
+                                     &tr0_cnt1, &tr1_cnt0);
+       if (num_tr < 0) {
+               dev_err(uc->ud->dev, "size %zu is not supported\n",
+                       period_len);
+               return NULL;
+       }
 
        /* Now allocate and setup the descriptor. */
        tr_size = sizeof(struct cppi5_tr_type1_t);
-       d = udma_alloc_tr_desc(uc, tr_size, periods, dir);
+       d = udma_alloc_tr_desc(uc, tr_size, periods * num_tr, dir);
        if (!d)
                return NULL;
 
        tr_req = d->hwdesc[0].tr_req_base;
+       period_addr = buf_addr;
        for (i = 0; i < periods; i++) {
-               cppi5_tr_init(&tr_req[i].flags, CPPI5_TR_TYPE1, false, false,
-                             CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+               int tr_idx = i * num_tr;
 
-               tr_req[i].addr = buf_addr + period_len * i;
-               tr_req[i].icnt0 = dev_width;
-               tr_req[i].icnt1 = period_len / dev_width;
-               tr_req[i].dim1 = dev_width;
+               cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1, false,
+                             false, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+
+               tr_req[tr_idx].addr = period_addr;
+               tr_req[tr_idx].icnt0 = tr0_cnt0;
+               tr_req[tr_idx].icnt1 = tr0_cnt1;
+               tr_req[tr_idx].dim1 = tr0_cnt0;
+
+               if (num_tr == 2) {
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
+                                        CPPI5_TR_CSF_SUPR_EVT);
+                       tr_idx++;
+
+                       cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
+                                     false, false,
+                                     CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+
+                       tr_req[tr_idx].addr = period_addr + tr0_cnt1 * tr0_cnt0;
+                       tr_req[tr_idx].icnt0 = tr1_cnt0;
+                       tr_req[tr_idx].icnt1 = 1;
+                       tr_req[tr_idx].dim1 = tr1_cnt0;
+               }
 
                if (!(flags & DMA_PREP_INTERRUPT))
-                       cppi5_tr_csf_set(&tr_req[i].flags,
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
                                         CPPI5_TR_CSF_SUPR_EVT);
+
+               period_addr += period_len;
        }
 
        return d;
@@ -2517,29 +2670,12 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                return NULL;
        }
 
-       if (len < SZ_64K) {
-               num_tr = 1;
-               tr0_cnt0 = len;
-               tr0_cnt1 = 1;
-       } else {
-               unsigned long align_to = __ffs(src | dest);
-
-               if (align_to > 3)
-                       align_to = 3;
-               /*
-                * Keep simple: tr0: SZ_64K-alignment blocks,
-                *              tr1: the remaining
-                */
-               num_tr = 2;
-               tr0_cnt0 = (SZ_64K - BIT(align_to));
-               if (len / tr0_cnt0 >= SZ_64K) {
-                       dev_err(uc->ud->dev, "size %zu is not supported\n",
-                               len);
-                       return NULL;
-               }
-
-               tr0_cnt1 = len / tr0_cnt0;
-               tr1_cnt0 = len % tr0_cnt0;
+       num_tr = udma_get_tr_counters(len, __ffs(src | dest), &tr0_cnt0,
+                                     &tr0_cnt1, &tr1_cnt0);
+       if (num_tr < 0) {
+               dev_err(uc->ud->dev, "size %zu is not supported\n",
+                       len);
+               return NULL;
        }
 
        d = udma_alloc_tr_desc(uc, tr_size, num_tr, DMA_MEM_TO_MEM);
@@ -2631,6 +2767,9 @@ static enum dma_status udma_tx_status(struct dma_chan *chan,
 
        ret = dma_cookie_status(chan, cookie, txstate);
 
+       if (!udma_is_chan_running(uc))
+               ret = DMA_COMPLETE;
+
        if (ret == DMA_IN_PROGRESS && udma_is_chan_paused(uc))
                ret = DMA_PAUSED;
 
@@ -2697,11 +2836,8 @@ static int udma_pause(struct dma_chan *chan)
 {
        struct udma_chan *uc = to_udma_chan(chan);
 
-       if (!uc->desc)
-               return -EINVAL;
-
        /* pause the channel */
-       switch (uc->desc->dir) {
+       switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
                udma_rchanrt_update_bits(uc->rchan,
                                         UDMA_RCHAN_RT_PEER_RT_EN_REG,
@@ -2730,11 +2866,8 @@ static int udma_resume(struct dma_chan *chan)
 {
        struct udma_chan *uc = to_udma_chan(chan);
 
-       if (!uc->desc)
-               return -EINVAL;
-
        /* resume the channel */
-       switch (uc->desc->dir) {
+       switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
                udma_rchanrt_update_bits(uc->rchan,
                                         UDMA_RCHAN_RT_PEER_RT_EN_REG,
@@ -3248,6 +3381,98 @@ static int udma_setup_resources(struct udma_dev *ud)
        return ch_count;
 }
 
+static int udma_setup_rx_flush(struct udma_dev *ud)
+{
+       struct udma_rx_flush *rx_flush = &ud->rx_flush;
+       struct cppi5_desc_hdr_t *tr_desc;
+       struct cppi5_tr_type1_t *tr_req;
+       struct cppi5_host_desc_t *desc;
+       struct device *dev = ud->dev;
+       struct udma_hwdesc *hwdesc;
+       size_t tr_size;
+
+       /* Allocate 1K buffer for discarded data on RX channel teardown */
+       rx_flush->buffer_size = SZ_1K;
+       rx_flush->buffer_vaddr = devm_kzalloc(dev, rx_flush->buffer_size,
+                                             GFP_KERNEL);
+       if (!rx_flush->buffer_vaddr)
+               return -ENOMEM;
+
+       rx_flush->buffer_paddr = dma_map_single(dev, rx_flush->buffer_vaddr,
+                                               rx_flush->buffer_size,
+                                               DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, rx_flush->buffer_paddr))
+               return -ENOMEM;
+
+       /* Set up descriptor to be used for TR mode */
+       hwdesc = &rx_flush->hwdescs[0];
+       tr_size = sizeof(struct cppi5_tr_type1_t);
+       hwdesc->cppi5_desc_size = cppi5_trdesc_calc_size(tr_size, 1);
+       hwdesc->cppi5_desc_size = ALIGN(hwdesc->cppi5_desc_size,
+                                       ud->desc_align);
+
+       hwdesc->cppi5_desc_vaddr = devm_kzalloc(dev, hwdesc->cppi5_desc_size,
+                                               GFP_KERNEL);
+       if (!hwdesc->cppi5_desc_vaddr)
+               return -ENOMEM;
+
+       hwdesc->cppi5_desc_paddr = dma_map_single(dev, hwdesc->cppi5_desc_vaddr,
+                                                 hwdesc->cppi5_desc_size,
+                                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, hwdesc->cppi5_desc_paddr))
+               return -ENOMEM;
+
+       /* Start of the TR req records */
+       hwdesc->tr_req_base = hwdesc->cppi5_desc_vaddr + tr_size;
+       /* Start address of the TR response array */
+       hwdesc->tr_resp_base = hwdesc->tr_req_base + tr_size;
+
+       tr_desc = hwdesc->cppi5_desc_vaddr;
+       cppi5_trdesc_init(tr_desc, 1, tr_size, 0, 0);
+       cppi5_desc_set_pktids(tr_desc, 0, CPPI5_INFO1_DESC_FLOWID_DEFAULT);
+       cppi5_desc_set_retpolicy(tr_desc, 0, 0);
+
+       tr_req = hwdesc->tr_req_base;
+       cppi5_tr_init(&tr_req->flags, CPPI5_TR_TYPE1, false, false,
+                     CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+       cppi5_tr_csf_set(&tr_req->flags, CPPI5_TR_CSF_SUPR_EVT);
+
+       tr_req->addr = rx_flush->buffer_paddr;
+       tr_req->icnt0 = rx_flush->buffer_size;
+       tr_req->icnt1 = 1;
+
+       /* Set up descriptor to be used for packet mode */
+       hwdesc = &rx_flush->hwdescs[1];
+       hwdesc->cppi5_desc_size = ALIGN(sizeof(struct cppi5_host_desc_t) +
+                                       CPPI5_INFO0_HDESC_EPIB_SIZE +
+                                       CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE,
+                                       ud->desc_align);
+
+       hwdesc->cppi5_desc_vaddr = devm_kzalloc(dev, hwdesc->cppi5_desc_size,
+                                               GFP_KERNEL);
+       if (!hwdesc->cppi5_desc_vaddr)
+               return -ENOMEM;
+
+       hwdesc->cppi5_desc_paddr = dma_map_single(dev, hwdesc->cppi5_desc_vaddr,
+                                                 hwdesc->cppi5_desc_size,
+                                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, hwdesc->cppi5_desc_paddr))
+               return -ENOMEM;
+
+       desc = hwdesc->cppi5_desc_vaddr;
+       cppi5_hdesc_init(desc, 0, 0);
+       cppi5_desc_set_pktids(&desc->hdr, 0, CPPI5_INFO1_DESC_FLOWID_DEFAULT);
+       cppi5_desc_set_retpolicy(&desc->hdr, 0, 0);
+
+       cppi5_hdesc_attach_buf(desc,
+                              rx_flush->buffer_paddr, rx_flush->buffer_size,
+                              rx_flush->buffer_paddr, rx_flush->buffer_size);
+
+       dma_sync_single_for_device(dev, hwdesc->cppi5_desc_paddr,
+                                  hwdesc->cppi5_desc_size, DMA_TO_DEVICE);
+       return 0;
+}
+
 #define TI_UDMAC_BUSWIDTHS     (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
                                 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
                                 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
@@ -3361,6 +3586,10 @@ static int udma_probe(struct platform_device *pdev)
        if (ud->desc_align < dma_get_cache_alignment())
                ud->desc_align = dma_get_cache_alignment();
 
+       ret = udma_setup_rx_flush(ud);
+       if (ret)
+               return ret;
+
        for (i = 0; i < ud->tchan_cnt; i++) {
                struct udma_tchan *tchan = &ud->tchans[i];
 
index 621220a..21ea99f 100644 (file)
@@ -552,7 +552,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 
                seed = early_memremap(efi.rng_seed, sizeof(*seed));
                if (seed != NULL) {
-                       size = seed->size;
+                       size = READ_ONCE(seed->size);
                        early_memunmap(seed, sizeof(*seed));
                } else {
                        pr_err("Could not map UEFI random seed!\n");
@@ -562,7 +562,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
                                              sizeof(*seed) + size);
                        if (seed != NULL) {
                                pr_notice("seeding entropy pool\n");
-                               add_bootloader_randomness(seed->bits, seed->size);
+                               add_bootloader_randomness(seed->bits, size);
                                early_memunmap(seed, sizeof(*seed) + size);
                        } else {
                                pr_err("Could not map UEFI random seed!\n");
index 94e2fd7..42f4feb 100644 (file)
@@ -1389,7 +1389,7 @@ amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
 
 static struct drm_driver kms_driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_ATOMIC |
+           DRIVER_ATOMIC |
            DRIVER_GEM |
            DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
            DRIVER_SYNCOBJ_TIMELINE,
index d3c27a3..7546da0 100644 (file)
@@ -195,6 +195,7 @@ struct amdgpu_gmc {
        uint32_t                srbm_soft_reset;
        bool                    prt_warning;
        uint64_t                stolen_size;
+       uint32_t                sdpif_register;
        /* apertures */
        u64                     shared_aperture_start;
        u64                     shared_aperture_end;
index 22bbb36..0270259 100644 (file)
@@ -52,7 +52,7 @@
  * 1. Primary ring
  * 2. Async ring
  */
-#define GFX10_NUM_GFX_RINGS    2
+#define GFX10_NUM_GFX_RINGS_NV1X       1
 #define GFX10_MEC_HPD_SIZE     2048
 
 #define F32_CE_PROGRAM_RAM_SIZE                65536
@@ -1304,7 +1304,7 @@ static int gfx_v10_0_sw_init(void *handle)
        case CHIP_NAVI14:
        case CHIP_NAVI12:
                adev->gfx.me.num_me = 1;
-               adev->gfx.me.num_pipe_per_me = 2;
+               adev->gfx.me.num_pipe_per_me = 1;
                adev->gfx.me.num_queue_per_pipe = 1;
                adev->gfx.mec.num_mec = 2;
                adev->gfx.mec.num_pipe_per_mec = 4;
@@ -2710,18 +2710,20 @@ static int gfx_v10_0_cp_gfx_start(struct amdgpu_device *adev)
        amdgpu_ring_commit(ring);
 
        /* submit cs packet to copy state 0 to next available state */
-       ring = &adev->gfx.gfx_ring[1];
-       r = amdgpu_ring_alloc(ring, 2);
-       if (r) {
-               DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r);
-               return r;
-       }
-
-       amdgpu_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
-       amdgpu_ring_write(ring, 0);
+       if (adev->gfx.num_gfx_rings > 1) {
+               /* maximum supported gfx ring is 2 */
+               ring = &adev->gfx.gfx_ring[1];
+               r = amdgpu_ring_alloc(ring, 2);
+               if (r) {
+                       DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r);
+                       return r;
+               }
 
-       amdgpu_ring_commit(ring);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
+               amdgpu_ring_write(ring, 0);
 
+               amdgpu_ring_commit(ring);
+       }
        return 0;
 }
 
@@ -2818,39 +2820,41 @@ static int gfx_v10_0_cp_gfx_resume(struct amdgpu_device *adev)
        mutex_unlock(&adev->srbm_mutex);
 
        /* Init gfx ring 1 for pipe 1 */
-       mutex_lock(&adev->srbm_mutex);
-       gfx_v10_0_cp_gfx_switch_pipe(adev, PIPE_ID1);
-       ring = &adev->gfx.gfx_ring[1];
-       rb_bufsz = order_base_2(ring->ring_size / 8);
-       tmp = REG_SET_FIELD(0, CP_RB1_CNTL, RB_BUFSZ, rb_bufsz);
-       tmp = REG_SET_FIELD(tmp, CP_RB1_CNTL, RB_BLKSZ, rb_bufsz - 2);
-       WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
-       /* Initialize the ring buffer's write pointers */
-       ring->wptr = 0;
-       WREG32_SOC15(GC, 0, mmCP_RB1_WPTR, lower_32_bits(ring->wptr));
-       WREG32_SOC15(GC, 0, mmCP_RB1_WPTR_HI, upper_32_bits(ring->wptr));
-       /* Set the wb address wether it's enabled or not */
-       rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
-       WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
-       WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) &
-               CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK);
-       wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
-       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO,
-               lower_32_bits(wptr_gpu_addr));
-       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI,
-               upper_32_bits(wptr_gpu_addr));
-
-       mdelay(1);
-       WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
-
-       rb_addr = ring->gpu_addr >> 8;
-       WREG32_SOC15(GC, 0, mmCP_RB1_BASE, rb_addr);
-       WREG32_SOC15(GC, 0, mmCP_RB1_BASE_HI, upper_32_bits(rb_addr));
-       WREG32_SOC15(GC, 0, mmCP_RB1_ACTIVE, 1);
-
-       gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
-       mutex_unlock(&adev->srbm_mutex);
-
+       if (adev->gfx.num_gfx_rings > 1) {
+               mutex_lock(&adev->srbm_mutex);
+               gfx_v10_0_cp_gfx_switch_pipe(adev, PIPE_ID1);
+               /* maximum supported gfx ring is 2 */
+               ring = &adev->gfx.gfx_ring[1];
+               rb_bufsz = order_base_2(ring->ring_size / 8);
+               tmp = REG_SET_FIELD(0, CP_RB1_CNTL, RB_BUFSZ, rb_bufsz);
+               tmp = REG_SET_FIELD(tmp, CP_RB1_CNTL, RB_BLKSZ, rb_bufsz - 2);
+               WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
+               /* Initialize the ring buffer's write pointers */
+               ring->wptr = 0;
+               WREG32_SOC15(GC, 0, mmCP_RB1_WPTR, lower_32_bits(ring->wptr));
+               WREG32_SOC15(GC, 0, mmCP_RB1_WPTR_HI, upper_32_bits(ring->wptr));
+               /* Set the wb address wether it's enabled or not */
+               rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
+               WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
+               WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) &
+                            CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK);
+               wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+               WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO,
+                            lower_32_bits(wptr_gpu_addr));
+               WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI,
+                            upper_32_bits(wptr_gpu_addr));
+
+               mdelay(1);
+               WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
+
+               rb_addr = ring->gpu_addr >> 8;
+               WREG32_SOC15(GC, 0, mmCP_RB1_BASE, rb_addr);
+               WREG32_SOC15(GC, 0, mmCP_RB1_BASE_HI, upper_32_bits(rb_addr));
+               WREG32_SOC15(GC, 0, mmCP_RB1_ACTIVE, 1);
+
+               gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
+               mutex_unlock(&adev->srbm_mutex);
+       }
        /* Switch to pipe 0 */
        mutex_lock(&adev->srbm_mutex);
        gfx_v10_0_cp_gfx_switch_pipe(adev, PIPE_ID0);
@@ -3513,6 +3517,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring)
 
                /* reset ring buffer */
                ring->wptr = 0;
+               atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
                amdgpu_ring_clear_ring(ring);
        } else {
                amdgpu_ring_clear_ring(ring);
@@ -3966,7 +3971,8 @@ static int gfx_v10_0_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS;
+       adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X;
+
        adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS;
 
        gfx_v10_0_set_kiq_pm4_funcs(adev);
index 3afdbbd..889154a 100644 (file)
@@ -3663,6 +3663,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring)
 
                /* reset ring buffer */
                ring->wptr = 0;
+               atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
                amdgpu_ring_clear_ring(ring);
        } else {
                amdgpu_ring_clear_ring(ring);
index 90216ab..cc0c273 100644 (file)
@@ -1271,6 +1271,19 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
        }
 }
 
+/**
+ * gmc_v9_0_restore_registers - restores regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This restores register values, saved at suspend.
+ */
+static void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
+{
+       if (adev->asic_type == CHIP_RAVEN)
+               WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
+}
+
 /**
  * gmc_v9_0_gart_enable - gart enable
  *
@@ -1376,6 +1389,20 @@ static int gmc_v9_0_hw_init(void *handle)
        return r;
 }
 
+/**
+ * gmc_v9_0_save_registers - saves regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This saves potential register values that should be
+ * restored upon resume
+ */
+static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
+{
+       if (adev->asic_type == CHIP_RAVEN)
+               adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
+}
+
 /**
  * gmc_v9_0_gart_disable - gart disable
  *
@@ -1412,9 +1439,16 @@ static int gmc_v9_0_hw_fini(void *handle)
 
 static int gmc_v9_0_suspend(void *handle)
 {
+       int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       return gmc_v9_0_hw_fini(adev);
+       r = gmc_v9_0_hw_fini(adev);
+       if (r)
+               return r;
+
+       gmc_v9_0_save_registers(adev);
+
+       return 0;
 }
 
 static int gmc_v9_0_resume(void *handle)
@@ -1422,6 +1456,7 @@ static int gmc_v9_0_resume(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       gmc_v9_0_restore_registers(adev);
        r = gmc_v9_0_hw_init(adev);
        if (r)
                return r;
index e8f66fb..e997251 100644 (file)
@@ -1422,6 +1422,73 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
                drm_kms_helper_hotplug_event(dev);
 }
 
+static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev)
+{
+       struct smu_context *smu = &adev->smu;
+       int ret = 0;
+
+       if (!is_support_sw_smu(adev))
+               return 0;
+
+       /* This interface is for dGPU Navi1x.Linux dc-pplib interface depends
+        * on window driver dc implementation.
+        * For Navi1x, clock settings of dcn watermarks are fixed. the settings
+        * should be passed to smu during boot up and resume from s3.
+        * boot up: dc calculate dcn watermark clock settings within dc_create,
+        * dcn20_resource_construct
+        * then call pplib functions below to pass the settings to smu:
+        * smu_set_watermarks_for_clock_ranges
+        * smu_set_watermarks_table
+        * navi10_set_watermarks_table
+        * smu_write_watermarks_table
+        *
+        * For Renoir, clock settings of dcn watermark are also fixed values.
+        * dc has implemented different flow for window driver:
+        * dc_hardware_init / dc_set_power_state
+        * dcn10_init_hw
+        * notify_wm_ranges
+        * set_wm_ranges
+        * -- Linux
+        * smu_set_watermarks_for_clock_ranges
+        * renoir_set_watermarks_table
+        * smu_write_watermarks_table
+        *
+        * For Linux,
+        * dc_hardware_init -> amdgpu_dm_init
+        * dc_set_power_state --> dm_resume
+        *
+        * therefore, this function apply to navi10/12/14 but not Renoir
+        * *
+        */
+       switch(adev->asic_type) {
+       case CHIP_NAVI10:
+       case CHIP_NAVI14:
+       case CHIP_NAVI12:
+               break;
+       default:
+               return 0;
+       }
+
+       mutex_lock(&smu->mutex);
+
+       /* pass data to smu controller */
+       if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
+                       !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
+               ret = smu_write_watermarks_table(smu);
+
+               if (ret) {
+                       mutex_unlock(&smu->mutex);
+                       DRM_ERROR("Failed to update WMTABLE!\n");
+                       return ret;
+               }
+               smu->watermarks_bitmap |= WATERMARKS_LOADED;
+       }
+
+       mutex_unlock(&smu->mutex);
+
+       return 0;
+}
+
 /**
  * dm_hw_init() - Initialize DC device
  * @handle: The base driver device containing the amdgpu_dm device.
@@ -1700,6 +1767,8 @@ static int dm_resume(void *handle)
 
        amdgpu_dm_irq_resume_late(adev);
 
+       amdgpu_dm_smu_write_watermarks_table(adev);
+
        return 0;
 }
 
index 5672f77..da73161 100644 (file)
@@ -451,6 +451,7 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                                           aconnector->dc_sink);
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
+               aconnector->dc_link->cur_link_settings.lane_count = 0;
        }
 
        drm_connector_unregister(connector);
index f36a0d8..446ba0a 100644 (file)
@@ -840,8 +840,8 @@ static void hubbub1_det_request_size(
 
        hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe);
 
-       swath_bytes_horz_wc = height * blk256_height * bpe;
-       swath_bytes_vert_wc = width * blk256_width * bpe;
+       swath_bytes_horz_wc = width * blk256_height * bpe;
+       swath_bytes_vert_wc = height * blk256_width * bpe;
 
        *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
                        false : /* full 256B request */
index b6f74bf..27bb8c1 100644 (file)
 #define mmCRTC4_CRTC_DRR_CONTROL                                                                       0x0f3e
 #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX                                                              2
 
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0                                                                  0x395d
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX                                                         2
 
 // addressBlock: dce_dc_fmt4_dispdec
 // base address: 0x2000
index 99ad4dd..ad8e9b5 100644 (file)
@@ -222,7 +222,7 @@ int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type,
 {
        int ret = 0;
 
-       if (min <= 0 && max <= 0)
+       if (min < 0 && max < 0)
                return -EINVAL;
 
        if (!smu_clk_dpm_is_enabled(smu, clk_type))
index 861e641..568c041 100644 (file)
@@ -111,8 +111,8 @@ static struct smu_12_0_cmn2aisc_mapping renoir_clk_map[SMU_CLK_COUNT] = {
        CLK_MAP(GFXCLK, CLOCK_GFXCLK),
        CLK_MAP(SCLK,   CLOCK_GFXCLK),
        CLK_MAP(SOCCLK, CLOCK_SOCCLK),
-       CLK_MAP(UCLK, CLOCK_UMCCLK),
-       CLK_MAP(MCLK, CLOCK_UMCCLK),
+       CLK_MAP(UCLK, CLOCK_FCLK),
+       CLK_MAP(MCLK, CLOCK_FCLK),
 };
 
 static struct smu_12_0_cmn2aisc_mapping renoir_table_map[SMU_TABLE_COUNT] = {
@@ -280,7 +280,7 @@ static int renoir_print_clk_levels(struct smu_context *smu,
                break;
        case SMU_MCLK:
                count = NUM_MEMCLK_DPM_LEVELS;
-               cur_value = metrics.ClockFrequency[CLOCK_UMCCLK];
+               cur_value = metrics.ClockFrequency[CLOCK_FCLK];
                break;
        case SMU_DCEFCLK:
                count = NUM_DCFCLK_DPM_LEVELS;
index b06c057..c9e5ce1 100644 (file)
@@ -978,8 +978,12 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
        struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
        int ret = 0;
 
-       max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
+       if (!smu->smu_table.max_sustainable_clocks)
+               max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
                                         GFP_KERNEL);
+       else
+               max_sustainable_clocks = smu->smu_table.max_sustainable_clocks;
+
        smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
 
        max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
index 870e6db..518e659 100644 (file)
@@ -458,9 +458,6 @@ int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_
 {
        int ret = 0;
 
-       if (max < min)
-               return -EINVAL;
-
        switch (clk_type) {
        case SMU_GFXCLK:
        case SMU_SCLK:
index 56f55c5..2dfa2fd 100644 (file)
@@ -210,8 +210,7 @@ static int anx6345_dp_link_training(struct anx6345 *anx6345)
        if (err)
                return err;
 
-       dpcd[0] = drm_dp_max_link_rate(anx6345->dpcd);
-       dpcd[0] = drm_dp_link_rate_to_bw_code(dpcd[0]);
+       dpcd[0] = dp_bw;
        err = regmap_write(anx6345->map[I2C_IDX_DPTX],
                           SP_DP_MAIN_LINK_BW_SET_REG, dpcd[0]);
        if (err)
index a421a2e..df31e57 100644 (file)
@@ -254,11 +254,16 @@ static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
        if (ret)
                goto err_zero_use;
 
-       if (obj->import_attach)
+       if (obj->import_attach) {
                shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
-       else
+       } else {
+               pgprot_t prot = PAGE_KERNEL;
+
+               if (!shmem->map_cached)
+                       prot = pgprot_writecombine(prot);
                shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT,
-                                   VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+                                   VM_MAP, prot);
+       }
 
        if (!shmem->vaddr) {
                DRM_DEBUG_KMS("Failed to vmap pages\n");
@@ -540,8 +545,9 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
        }
 
        vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND;
-       vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
-       vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
+       vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+       if (!shmem->map_cached)
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        vma->vm_ops = &drm_gem_shmem_vm_ops;
 
        return 0;
index 33628d8..a85365c 100644 (file)
@@ -1773,8 +1773,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies),
                                      dsi->supplies);
        if (ret) {
-               dev_info(dev, "failed to get regulators: %d\n", ret);
-               return -EPROBE_DEFER;
+               if (ret != -EPROBE_DEFER)
+                       dev_info(dev, "failed to get regulators: %d\n", ret);
+               return ret;
        }
 
        dsi->clks = devm_kcalloc(dev,
@@ -1787,9 +1788,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
                dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
                if (IS_ERR(dsi->clks[i])) {
                        if (strcmp(clk_names[i], "sclk_mipi") == 0) {
-                               strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME);
-                               i--;
-                               continue;
+                               dsi->clks[i] = devm_clk_get(dev,
+                                                       OLD_SCLK_MIPI_CLK_NAME);
+                               if (!IS_ERR(dsi->clks[i]))
+                                       continue;
                        }
 
                        dev_info(dev, "failed to get the clock: %s\n",
index 9ff921f..f141916 100644 (file)
@@ -1805,18 +1805,10 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
 
        hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
 
-       if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) {
+       if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV)
                if (IS_ERR(hdata->reg_hdmi_en))
                        return PTR_ERR(hdata->reg_hdmi_en);
 
-               ret = regulator_enable(hdata->reg_hdmi_en);
-               if (ret) {
-                       DRM_DEV_ERROR(dev,
-                                     "failed to enable hdmi-en regulator\n");
-                       return ret;
-               }
-       }
-
        return hdmi_bridge_init(hdata);
 }
 
@@ -2023,6 +2015,15 @@ static int hdmi_probe(struct platform_device *pdev)
                }
        }
 
+       if (!IS_ERR(hdata->reg_hdmi_en)) {
+               ret = regulator_enable(hdata->reg_hdmi_en);
+               if (ret) {
+                       DRM_DEV_ERROR(dev,
+                             "failed to enable hdmi-en regulator\n");
+                       goto err_hdmiphy;
+               }
+       }
+
        pm_runtime_enable(dev);
 
        audio_infoframe = &hdata->audio.infoframe;
@@ -2047,7 +2048,8 @@ err_unregister_audio:
 
 err_rpm_disable:
        pm_runtime_disable(dev);
-
+       if (!IS_ERR(hdata->reg_hdmi_en))
+               regulator_disable(hdata->reg_hdmi_en);
 err_hdmiphy:
        if (hdata->hdmiphy_port)
                put_device(&hdata->hdmiphy_port->dev);
index 0da8602..e2ac098 100644 (file)
@@ -83,7 +83,6 @@
 #define VSIZE_OFST                     20
 #define LDI_INT_EN                     0x741C
 #define FRAME_END_INT_EN_OFST          1
-#define UNDERFLOW_INT_EN_OFST          2
 #define LDI_CTRL                       0x7420
 #define BPP_OFST                       3
 #define DATA_GATE_EN                   BIT(2)
index 73cd28a..8600012 100644 (file)
@@ -46,7 +46,6 @@ struct ade_hw_ctx {
        struct clk *media_noc_clk;
        struct clk *ade_pix_clk;
        struct reset_control *reset;
-       struct work_struct display_reset_wq;
        bool power_on;
        int irq;
 
@@ -136,7 +135,6 @@ static void ade_init(struct ade_hw_ctx *ctx)
         */
        ade_update_bits(base + ADE_CTRL, FRM_END_START_OFST,
                        FRM_END_START_MASK, REG_EFFECTIVE_IN_ADEEN_FRMEND);
-       ade_update_bits(base + LDI_INT_EN, UNDERFLOW_INT_EN_OFST, MASK(1), 1);
 }
 
 static bool ade_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -304,17 +302,6 @@ static void ade_crtc_disable_vblank(struct drm_crtc *crtc)
                        MASK(1), 0);
 }
 
-static void drm_underflow_wq(struct work_struct *work)
-{
-       struct ade_hw_ctx *ctx = container_of(work, struct ade_hw_ctx,
-                                             display_reset_wq);
-       struct drm_device *drm_dev = ctx->crtc->dev;
-       struct drm_atomic_state *state;
-
-       state = drm_atomic_helper_suspend(drm_dev);
-       drm_atomic_helper_resume(drm_dev, state);
-}
-
 static irqreturn_t ade_irq_handler(int irq, void *data)
 {
        struct ade_hw_ctx *ctx = data;
@@ -331,12 +318,6 @@ static irqreturn_t ade_irq_handler(int irq, void *data)
                                MASK(1), 1);
                drm_crtc_handle_vblank(crtc);
        }
-       if (status & BIT(UNDERFLOW_INT_EN_OFST)) {
-               ade_update_bits(base + LDI_INT_CLR, UNDERFLOW_INT_EN_OFST,
-                               MASK(1), 1);
-               DRM_ERROR("LDI underflow!");
-               schedule_work(&ctx->display_reset_wq);
-       }
 
        return IRQ_HANDLED;
 }
@@ -919,7 +900,6 @@ static void *ade_hw_ctx_alloc(struct platform_device *pdev,
        if (ret)
                return ERR_PTR(-EIO);
 
-       INIT_WORK(&ctx->display_reset_wq, drm_underflow_wq);
        ctx->crtc = crtc;
 
        return ctx;
index b8c5f89..a1f2411 100644 (file)
@@ -294,7 +294,7 @@ extra-$(CONFIG_DRM_I915_WERROR) += \
                $(shell cd $(srctree)/$(src) && find * -name '*.h')))
 
 quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
-      cmd_hdrtest = $(CC) $(c_flags) -S -o /dev/null -x c /dev/null -include $<; touch $@
+      cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@
 
 $(obj)/%.hdrtest: $(src)/%.h FORCE
        $(call if_changed_dep,hdrtest)
index 21561ac..46c40db 100644 (file)
@@ -4466,13 +4466,19 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
 
 static void icl_mbus_init(struct drm_i915_private *dev_priv)
 {
-       u32 val;
+       u32 mask, val;
 
-       val = MBUS_ABOX_BT_CREDIT_POOL1(16) |
-             MBUS_ABOX_BT_CREDIT_POOL2(16) |
-             MBUS_ABOX_B_CREDIT(1) |
-             MBUS_ABOX_BW_CREDIT(1);
+       mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK |
+               MBUS_ABOX_BT_CREDIT_POOL2_MASK |
+               MBUS_ABOX_B_CREDIT_MASK |
+               MBU