Merge tag 'kbuild-fixes-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/masah...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Mar 2018 18:37:01 +0000 (10:37 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Mar 2018 18:37:01 +0000 (10:37 -0800)
Pull Kbuild fixes from Masahiro Yamada:

 - suppress sparse warnings about unknown attributes

 - fix typos and stale comments

 - fix build error of arch/sh

 - fix wrong use of ld-option vs cc-ldoption

 - remove redundant GCC_PLUGINS_CFLAGS assignment

 - fix another memory leak of Kconfig

 - fix line number in error messages of Kconfig

 - do not write confusing CONFIG_DEFCONFIG_LIST out to .config

 - add xstrdup() to Kconfig to handle memory shortage errors

 - show also a Debian package name if ncurses is missing

* tag 'kbuild-fixes-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild:
  MAINTAINERS: take over Kconfig maintainership
  kconfig: fix line number in recursive inclusion error message
  Coccinelle: memdup: Fix typo in warning messages
  kconfig: Update ncurses package names for menuconfig
  kbuild/kallsyms: trivial typo fix
  kbuild: test --build-id linker flag by ld-option instead of cc-ldoption
  kbuild: drop superfluous GCC_PLUGINS_CFLAGS assignment
  kconfig: Don't leak choice names during parsing
  sh: fix build error for empty CONFIG_BUILTIN_DTB_SOURCE
  kconfig: set SYMBOL_AUTO to the symbol marked with defconfig_list
  kconfig: add xstrdup() helper
  kbuild: disable sparse warnings about unknown attributes
  Makefile: Fix lying comment re. silentoldconfig

303 files changed:
Documentation/PCI/pci.txt
Documentation/devicetree/bindings/auxdisplay/arm-charlcd.txt [moved from Documentation/devicetree/bindings/misc/arm-charlcd.txt with 100% similarity]
Documentation/devicetree/bindings/power/wakeup-source.txt
Documentation/devicetree/bindings/thermal/imx-thermal.txt
Documentation/media/dmx.h.rst.exceptions
Documentation/media/uapi/dvb/dmx-qbuf.rst
Documentation/virtual/kvm/api.txt
Documentation/virtual/kvm/cpuid.txt
Documentation/virtual/kvm/msr.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/boot/dts/axs101.dts
arch/arc/boot/dts/axs10x_mb.dtsi
arch/arc/boot/dts/haps_hs_idu.dts
arch/arc/boot/dts/nsim_700.dts
arch/arc/boot/dts/nsim_hs.dts
arch/arc/boot/dts/nsim_hs_idu.dts
arch/arc/boot/dts/nsimosci.dts
arch/arc/boot/dts/nsimosci_hs.dts
arch/arc/boot/dts/nsimosci_hs_idu.dts
arch/arc/include/asm/entry-arcv2.h
arch/arc/kernel/mcip.c
arch/arc/kernel/setup.c
arch/arc/kernel/smp.c
arch/arc/mm/cache.c
arch/arm/boot/dts/bcm11351.dtsi
arch/arm/boot/dts/bcm21664.dtsi
arch/arm/boot/dts/bcm2835.dtsi
arch/arm/boot/dts/bcm2836.dtsi
arch/arm/boot/dts/bcm2837.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/bcm958625hr.dts
arch/arm/boot/dts/gemini-dlink-dns-313.dts
arch/arm/boot/dts/imx6dl-icore-rqs.dts
arch/arm/boot/dts/logicpd-som-lv.dtsi
arch/arm/boot/dts/logicpd-torpedo-som.dtsi
arch/arm/boot/dts/omap5-uevm.dts
arch/arm/boot/dts/rk3036.dtsi
arch/arm/boot/dts/rk322x.dtsi
arch/arm/boot/dts/rk3288-phycore-som.dtsi
arch/arm/boot/dts/zx296702.dtsi
arch/arm/configs/omap2plus_defconfig
arch/arm/kvm/hyp/Makefile
arch/arm/kvm/hyp/banked-sr.c
arch/arm/mach-clps711x/board-dt.c
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/timer.c
arch/arm/plat-orion/common.c
arch/arm64/boot/dts/amlogic/meson-axg.dtsi
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
arch/arm64/boot/dts/cavium/thunder2-99xx.dtsi
arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
arch/arm64/boot/dts/mediatek/mt8173.dtsi
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
arch/arm64/boot/dts/rockchip/rk3328.dtsi
arch/arm64/boot/dts/rockchip/rk3368.dtsi
arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/processor.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/head.S
arch/parisc/kernel/pacache.S
arch/parisc/kernel/smp.c
arch/parisc/kernel/time.c
arch/parisc/mm/init.c
arch/riscv/include/asm/barrier.h
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/vsie.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/entry/calling.h
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/entry/entry_64_compat.S
arch/x86/include/asm/apm.h
arch/x86/include/asm/asm-prototypes.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/microcode.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/refcount.h
arch/x86/include/asm/rmwcc.h
arch/x86/include/uapi/asm/kvm_para.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/head_64.S
arch/x86/kernel/kvm.c
arch/x86/kernel/unwind_orc.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/Makefile
arch/x86/lib/retpoline.S
arch/x86/mm/fault.c
arch/x86/mm/mem_encrypt_boot.S
arch/x86/realmode/rm/trampoline_64.S
arch/x86/xen/enlighten_pv.c
block/blk-cgroup.c
block/blk-core.c
block/blk-mq.c
block/genhd.c
block/ioctl.c
block/kyber-iosched.c
block/mq-deadline.c
block/partition-generic.c
drivers/block/amiflop.c
drivers/block/ataflop.c
drivers/block/brd.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/pktcdvd.c
drivers/block/swim.c
drivers/block/z2ram.c
drivers/bus/ti-sysc.c
drivers/char/tpm/st33zp24/st33zp24.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_i2c_infineon.c
drivers/char/tpm/tpm_i2c_nuvoton.c
drivers/char/tpm/tpm_tis_core.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/s3c24xx-cpufreq.c
drivers/cpufreq/scpi-cpufreq.c
drivers/crypto/ccp/psp-dev.c
drivers/edac/sb_edac.c
drivers/gpio/gpiolib-of.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_request.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/ide/ide-probe.c
drivers/md/bcache/request.c
drivers/md/bcache/super.c
drivers/md/md-multipath.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid1.h
drivers/md/raid10.c
drivers/md/raid10.h
drivers/md/raid5-log.h
drivers/md/raid5-ppl.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/Kconfig
drivers/media/common/videobuf2/Kconfig
drivers/media/common/videobuf2/Makefile
drivers/media/common/videobuf2/vb2-trace.c [moved from drivers/media/v4l2-core/vb2-trace.c with 100% similarity]
drivers/media/dvb-core/Makefile
drivers/media/dvb-core/dmxdev.c
drivers/media/dvb-core/dvb_demux.c
drivers/media/dvb-core/dvb_net.c
drivers/media/dvb-core/dvb_vb2.c
drivers/media/dvb-frontends/m88ds3103.c
drivers/media/i2c/tvp5150.c
drivers/media/pci/ttpci/av7110.c
drivers/media/pci/ttpci/av7110_av.c
drivers/media/usb/au0828/Kconfig
drivers/media/usb/ttusb-dec/ttusb_dec.c
drivers/media/v4l2-core/Kconfig
drivers/media/v4l2-core/Makefile
drivers/memory/brcmstb_dpfe.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-k3.c
drivers/mmc/host/dw_mmc-rockchip.c
drivers/mmc/host/dw_mmc-zx.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h
drivers/mmc/host/sdhci-pci-core.c
drivers/net/xen-netfront.c
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/multipath.c
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/core.c
drivers/nvme/target/loop.c
drivers/pci/setup-res.c
drivers/pinctrl/meson/pinctrl-meson-axg.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/wmi.c
drivers/soc/imx/gpc.c
drivers/watchdog/Kconfig
drivers/xen/events/events_base.c
drivers/xen/pvcalls-back.c
drivers/xen/pvcalls-front.c
fs/block_dev.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/super.c
fs/ceph/super.h
fs/direct-io.c
fs/xfs/scrub/agheader.c
fs/xfs/xfs_refcount_item.c
fs/xfs/xfs_rmap_item.c
fs/xfs/xfs_super.c
include/drm/drm_drv.h
include/linux/bio.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/genhd.h
include/linux/init.h
include/linux/jump_label.h
include/linux/kernel.h
include/linux/kvm_host.h
include/linux/nospec.h
include/media/demux.h
include/media/dmxdev.h
include/media/dvb_demux.h
include/media/dvb_vb2.h
include/soc/arc/mcip.h
include/uapi/drm/virtgpu_drm.h
include/uapi/linux/blktrace_api.h
include/uapi/linux/dvb/dmx.h
include/uapi/linux/kvm.h
include/uapi/linux/psp-sev.h
init/main.c
kernel/extable.c
kernel/jump_label.c
kernel/printk/printk.c
lib/dma-debug.c
lib/idr.c
net/ceph/ceph_common.c
samples/seccomp/Makefile
scripts/Makefile.build
sound/core/control.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/usb/quirks-table.h
sound/x86/intel_hdmi_audio.c
tools/kvm/kvm_stat/kvm_stat
tools/kvm/kvm_stat/kvm_stat.txt
tools/objtool/builtin-check.c
tools/objtool/builtin-orc.c
tools/objtool/builtin.h
tools/objtool/check.c
tools/objtool/check.h
tools/testing/radix-tree/idr-test.c
tools/testing/radix-tree/linux.c
tools/testing/radix-tree/linux/compiler_types.h [new file with mode: 0644]
tools/testing/radix-tree/linux/gfp.h
tools/testing/radix-tree/linux/slab.h
tools/testing/selftests/android/Makefile
tools/testing/selftests/futex/Makefile
tools/testing/selftests/memfd/config [new file with mode: 0644]
tools/testing/selftests/memory-hotplug/Makefile
tools/testing/selftests/pstore/config
tools/testing/selftests/sync/Makefile
tools/testing/selftests/vDSO/Makefile
tools/testing/selftests/vm/.gitignore
virt/kvm/arm/arch_timer.c
virt/kvm/kvm_main.c

index 611a75e4366ed2404b807dc03f1159f65d0a819a..badb26ac33dc8eec08d38c3ee13c24380568aadc 100644 (file)
@@ -570,7 +570,9 @@ your driver if they're helpful, or just use plain hex constants.
 The device IDs are arbitrary hex numbers (vendor controlled) and normally used
 only in a single location, the pci_device_id table.
 
-Please DO submit new vendor/device IDs to http://pciids.sourceforge.net/.
+Please DO submit new vendor/device IDs to http://pci-ids.ucw.cz/.
+There are mirrors of the pci.ids file at http://pciids.sourceforge.net/
+and https://github.com/pciutils/pciids.
 
 
 
index 3c81f78b5c27d50bb809cf6bbf13766a779024f5..5d254ab13ebf384034b7e8629365a7b0070c2af3 100644 (file)
@@ -60,7 +60,7 @@ Examples
                #size-cells = <0>;
 
                button@1 {
-                       debounce_interval = <50>;
+                       debounce-interval = <50>;
                        wakeup-source;
                        linux,code = <116>;
                        label = "POWER";
index 28be51afdb6a2623a9eb9465a86e0ec3fa7a1d7a..379eb763073e68d4a63b540c6ca3384a3b09f642 100644 (file)
@@ -22,7 +22,32 @@ Optional properties:
 - clocks : thermal sensor's clock source.
 
 Example:
+ocotp: ocotp@21bc000 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "fsl,imx6sx-ocotp", "syscon";
+       reg = <0x021bc000 0x4000>;
+       clocks = <&clks IMX6SX_CLK_OCOTP>;
 
+       tempmon_calib: calib@38 {
+               reg = <0x38 4>;
+       };
+
+       tempmon_temp_grade: temp-grade@20 {
+               reg = <0x20 4>;
+       };
+};
+
+tempmon: tempmon {
+       compatible = "fsl,imx6sx-tempmon", "fsl,imx6q-tempmon";
+       interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+       fsl,tempmon = <&anatop>;
+       nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>;
+       nvmem-cell-names = "calib", "temp_grade";
+       clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>;
+};
+
+Legacy method (Deprecated):
 tempmon {
        compatible = "fsl,imx6q-tempmon";
        fsl,tempmon = <&anatop>;
index 63f55a9ae2b1ffa54d088eb60b7e79e36c050f6e..a8c4239ed95bab6c87d8adcdb4edfa52de981099 100644 (file)
@@ -50,9 +50,15 @@ replace typedef dmx_filter_t :c:type:`dmx_filter`
 replace typedef dmx_pes_type_t :c:type:`dmx_pes_type`
 replace typedef dmx_input_t :c:type:`dmx_input`
 
-ignore symbol DMX_OUT_DECODER
-ignore symbol DMX_OUT_TAP
-ignore symbol DMX_OUT_TS_TAP
-ignore symbol DMX_OUT_TSDEMUX_TAP
+replace symbol DMX_BUFFER_FLAG_HAD_CRC32_DISCARD :c:type:`dmx_buffer_flags`
+replace        symbol DMX_BUFFER_FLAG_TEI :c:type:`dmx_buffer_flags`
+replace        symbol DMX_BUFFER_PKT_COUNTER_MISMATCH :c:type:`dmx_buffer_flags`
+replace        symbol DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED :c:type:`dmx_buffer_flags`
+replace        symbol DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR :c:type:`dmx_buffer_flags`
+
+replace symbol DMX_OUT_DECODER :c:type:`dmx_output`
+replace symbol DMX_OUT_TAP :c:type:`dmx_output`
+replace symbol DMX_OUT_TS_TAP :c:type:`dmx_output`
+replace symbol DMX_OUT_TSDEMUX_TAP :c:type:`dmx_output`
 
 replace ioctl DMX_DQBUF dmx_qbuf
index b48c4931658eda71586ec7ea4ddb380df518170f..be5a4c6f19040c6e5bf1acbb34f9598e6eec0b2f 100644 (file)
@@ -51,9 +51,10 @@ out to disk. Buffers remain locked until dequeued, until the
 the device is closed.
 
 Applications call the ``DMX_DQBUF`` ioctl to dequeue a filled
-(capturing) buffer from the driver's outgoing queue. They just set the ``reserved`` field array to zero. When ``DMX_DQBUF`` is called with a
-pointer to this structure, the driver fills the remaining fields or
-returns an error code.
+(capturing) buffer from the driver's outgoing queue.
+They just set the ``index`` field withe the buffer ID to be queued.
+When ``DMX_DQBUF`` is called with a pointer to struct :c:type:`dmx_buffer`,
+the driver fills the remaining fields or returns an error code.
 
 By default ``DMX_DQBUF`` blocks when no buffer is in the outgoing
 queue. When the ``O_NONBLOCK`` flag was given to the
index 792fa8717d133e1aa7d6c73a8b948d53150e6d78..d6b3ff51a14fd96600cc9f65f8ed11cd5c64b768 100644 (file)
@@ -123,14 +123,15 @@ memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
 flag KVM_VM_MIPS_VZ.
 
 
-4.3 KVM_GET_MSR_INDEX_LIST
+4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
 
-Capability: basic
+Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
 Architectures: x86
-Type: system
+Type: system ioctl
 Parameters: struct kvm_msr_list (in/out)
 Returns: 0 on success; -1 on error
 Errors:
+  EFAULT:    the msr index list cannot be read from or written to
   E2BIG:     the msr index list is to be to fit in the array specified by
              the user.
 
@@ -139,16 +140,23 @@ struct kvm_msr_list {
        __u32 indices[0];
 };
 
-This ioctl returns the guest msrs that are supported.  The list varies
-by kvm version and host processor, but does not change otherwise.  The
-user fills in the size of the indices array in nmsrs, and in return
-kvm adjusts nmsrs to reflect the actual number of msrs and fills in
-the indices array with their numbers.
+The user fills in the size of the indices array in nmsrs, and in return
+kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
+indices array with their numbers.
+
+KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported.  The list
+varies by kvm version and host processor, but does not change otherwise.
 
 Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
 not returned in the MSR list, as different vcpus can have a different number
 of banks, as set via the KVM_X86_SETUP_MCE ioctl.
 
+KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
+to the KVM_GET_MSRS system ioctl.  This lets userspace probe host capabilities
+and processor features that are exposed via MSRs (e.g., VMX capabilities).
+This list also varies by kvm version and host processor, but does not change
+otherwise.
+
 
 4.4 KVM_CHECK_EXTENSION
 
@@ -475,14 +483,22 @@ Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
 
 4.18 KVM_GET_MSRS
 
-Capability: basic
+Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
 Architectures: x86
-Type: vcpu ioctl
+Type: system ioctl, vcpu ioctl
 Parameters: struct kvm_msrs (in/out)
-Returns: 0 on success, -1 on error
+Returns: number of msrs successfully returned;
+        -1 on error
+
+When used as a system ioctl:
+Reads the values of MSR-based features that are available for the VM.  This
+is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
+The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
+in a system ioctl.
 
+When used as a vcpu ioctl:
 Reads model-specific registers from the vcpu.  Supported msr indices can
-be obtained using KVM_GET_MSR_INDEX_LIST.
+be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
 
 struct kvm_msrs {
        __u32 nmsrs; /* number of msrs in entries */
index dcab6dc11e3b08117456f10903ad3ac2fa29eb99..87a7506f31c2b7f9b03be131ba3b3ef1c85f360b 100644 (file)
@@ -58,6 +58,10 @@ KVM_FEATURE_PV_TLB_FLUSH           ||     9 || guest checks this feature bit
                                    ||       || before enabling paravirtualized
                                    ||       || tlb flush.
 ------------------------------------------------------------------------------
+KVM_FEATURE_ASYNC_PF_VMEXIT        ||    10 || paravirtualized async PF VM exit
+                                   ||       || can be enabled by setting bit 2
+                                   ||       || when writing to msr 0x4b564d02
+------------------------------------------------------------------------------
 KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ||    24 || host will warn if no guest-side
                                    ||       || per-cpu warps are expected in
                                    ||       || kvmclock.
index 1ebecc115dc6efdbbfa76eb4ab329f5b1d8b765e..f3f0d57ced8e1827fe8e8e6dc49808b18c9253fb 100644 (file)
@@ -170,7 +170,8 @@ MSR_KVM_ASYNC_PF_EN: 0x4b564d02
        when asynchronous page faults are enabled on the vcpu 0 when
        disabled. Bit 1 is 1 if asynchronous page faults can be injected
        when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
-       are delivered to L1 as #PF vmexits.
+       are delivered to L1 as #PF vmexits.  Bit 2 can be set only if
+       KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.
 
        First 4 byte of 64 byte memory location will be written to by
        the hypervisor at the time of asynchronous page fault (APF)
index b708b6daff7925d738d71125886e8887fc4c7d5f..4623caf8d72d8591b87a300b35b5ad0aca10f6a5 100644 (file)
@@ -1238,7 +1238,7 @@ F:        drivers/clk/at91
 
 ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
 M:     Nicolas Ferre <nicolas.ferre@microchip.com>
-M:     Alexandre Belloni <alexandre.belloni@free-electrons.com>
+M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.linux4sam.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git
@@ -1590,7 +1590,7 @@ ARM/Marvell Dove/MV78xx0/Orion SOC support
 M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
-M:     Gregory Clement <gregory.clement@free-electrons.com>
+M:     Gregory Clement <gregory.clement@bootlin.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/soc/dove/
@@ -1604,7 +1604,7 @@ F:        arch/arm/boot/dts/orion5x*
 ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K SOC support
 M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
-M:     Gregory Clement <gregory.clement@free-electrons.com>
+M:     Gregory Clement <gregory.clement@bootlin.com>
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -1999,8 +1999,10 @@ M:       Maxime Coquelin <mcoquelin.stm32@gmail.com>
 M:     Alexandre Torgue <alexandre.torgue@st.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mcoquelin/stm32.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/atorgue/stm32.git stm32-next
 N:     stm32
+F:     arch/arm/boot/dts/stm32*
+F:     arch/arm/mach-stm32/
 F:     drivers/clocksource/armv7m_systick.c
 
 ARM/TANGO ARCHITECTURE
@@ -10928,6 +10930,17 @@ L:     linux-gpio@vger.kernel.org
 S:     Supported
 F:     drivers/pinctrl/pinctrl-at91-pio4.*
 
+PIN CONTROLLER - FREESCALE
+M:     Dong Aisheng <aisheng.dong@nxp.com>
+M:     Fabio Estevam <festevam@gmail.com>
+M:     Shawn Guo <shawnguo@kernel.org>
+M:     Stefan Agner <stefan@agner.ch>
+R:     Pengutronix Kernel Team <kernel@pengutronix.de>
+L:     linux-gpio@vger.kernel.org
+S:     Maintained
+F:     drivers/pinctrl/freescale/
+F:     Documentation/devicetree/bindings/pinctrl/fsl,*
+
 PIN CONTROLLER - INTEL
 M:     Mika Westerberg <mika.westerberg@linux.intel.com>
 M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
index 20c01bd3acb304fd4ebe94401af571dcc48452d9..541f0c5b71c34a004d989ba709fd5b1620491202 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -489,6 +489,11 @@ KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
 KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
 endif
 
+RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register
+RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk
+RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG)))
+export RETPOLINE_CFLAGS
+
 ifeq ($(config-targets),1)
 # ===========================================================================
 # *config targets only - make sure prerequisites are updated, and descend
index f3a80cf164cc92a0860ddb77f5402dd7d8856ab0..d76bf4a8374016043963f1c04d42700e64ad605a 100644 (file)
@@ -484,7 +484,6 @@ config ARC_CURR_IN_REG
 
 config ARC_EMUL_UNALIGNED
        bool "Emulate unaligned memory access (userspace only)"
-       default N
        select SYSCTL_ARCH_UNALIGN_NO_WARN
        select SYSCTL_ARCH_UNALIGN_ALLOW
        depends on ISA_ARCOMPACT
index 70aec7d6ca600c2889d0a78bc3dac5b5fcb5b967..626b694c7be75ccf7868d7423aca79fb58eef586 100644 (file)
@@ -17,6 +17,6 @@
        compatible = "snps,axs101", "snps,arc-sdp";
 
        chosen {
-               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0 video=1280x720@60";
+               bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0 video=1280x720@60 print-fatal-signals=1";
        };
 };
index 74d070cd3c13a723fef1a2b3cd91cd2919392762..47b74fbc403c21cc2f493f6f84d6216b7c5ef5c1 100644 (file)
                        };
 
                        eeprom@0x54{
-                               compatible = "24c01";
+                               compatible = "atmel,24c01";
                                reg = <0x54>;
                                pagesize = <0x8>;
                        };
 
                        eeprom@0x57{
-                               compatible = "24c04";
+                               compatible = "atmel,24c04";
                                reg = <0x57>;
                                pagesize = <0x8>;
                        };
index 215cddd0b63baa4d1f865828e1df50914526e64e..0c603308aeb360880bca3a3403a74044cb1c12bc 100644 (file)
@@ -22,7 +22,7 @@
        };
 
        chosen {
-               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=ttyS0,115200n8 debug";
+               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=ttyS0,115200n8 debug print-fatal-signals=1";
        };
 
        aliases {
index 5ee96b067c085ce1f061e0aac02732d63d4ecf7e..ff2f2c70c545645f7cb38a526914378edc303aa1 100644 (file)
@@ -17,7 +17,7 @@
        interrupt-parent = <&core_intc>;
 
        chosen {
-               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8 print-fatal-signals=1";
        };
 
        aliases {
index 8d787b251f73746191cfea3bd176bfb2869eccce..8e2489b16b0aeecb9bc83de255ccad3eeb33efd5 100644 (file)
@@ -24,7 +24,7 @@
        };
 
        chosen {
-               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8 print-fatal-signals=1";
        };
 
        aliases {
index 4f98ebf71fd836624b248aa0cd107fb892bb76b2..ed12f494721df91f4597b2ead8b1c7ecd5a4f5e2 100644 (file)
@@ -15,7 +15,7 @@
        interrupt-parent = <&core_intc>;
 
        chosen {
-               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+               bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8 print-fatal-signals=1";
        };
 
        aliases {
index 3c391ba565ed080cfad8b66f4c3395975eec90da..7842e5eb4ab5cbb73c1bac4d881d7b332979bdaa 100644 (file)
@@ -20,7 +20,7 @@
                /* this is for console on PGU */
                /* bootargs = "console=tty0 consoleblank=0"; */
                /* this is for console on serial */
-               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug video=640x480-24";
+               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug video=640x480-24 print-fatal-signals=1";
        };
 
        aliases {
index 14a727cbf4c98e12590f0ad74148f24971f772f4..b8838cf2b4ec72ab119e72f367c6ef6184a72bce 100644 (file)
@@ -20,7 +20,7 @@
                /* this is for console on PGU */
                /* bootargs = "console=tty0 consoleblank=0"; */
                /* this is for console on serial */
-               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug video=640x480-24";
+               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug video=640x480-24 print-fatal-signals=1";
        };
 
        aliases {
index 5052917d4a99490ea77d2e18cc03b97ce3722f3a..72a2c723f1f7af826b07c49a416bf3265ed39f89 100644 (file)
@@ -18,7 +18,7 @@
 
        chosen {
                /* this is for console on serial */
-               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblan=0 debug video=640x480-24";
+               bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblan=0 debug video=640x480-24 print-fatal-signals=1";
        };
 
        aliases {
index 257a68f3c2feef3a369093f5bade883e814b7648..309f4e6721b3e22829847f88a4da884fdc9edf93 100644 (file)
 .macro FAKE_RET_FROM_EXCPN
        lr      r9, [status32]
        bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
-       or      r9, r9, (STATUS_L_MASK|STATUS_IE_MASK)
+       or      r9, r9, STATUS_IE_MASK
        kflag   r9
 .endm
 
index f61a52b01625b106143b089570b327b585e5a254..5fe84e481654ebe76a483bf81c2a11ffe870322d 100644 (file)
@@ -22,10 +22,79 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
 
 static char smp_cpuinfo_buf[128];
 
+/*
+ * Set mask to halt GFRC if any online core in SMP cluster is halted.
+ * Only works for ARC HS v3.0+, on earlier versions has no effect.
+ */
+static void mcip_update_gfrc_halt_mask(int cpu)
+{
+       struct bcr_generic gfrc;
+       unsigned long flags;
+       u32 gfrc_halt_mask;
+
+       READ_BCR(ARC_REG_GFRC_BUILD, gfrc);
+
+       /*
+        * CMD_GFRC_SET_CORE and CMD_GFRC_READ_CORE commands were added in
+        * GFRC 0x3 version.
+        */
+       if (gfrc.ver < 0x3)
+               return;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+
+       __mcip_cmd(CMD_GFRC_READ_CORE, 0);
+       gfrc_halt_mask = read_aux_reg(ARC_REG_MCIP_READBACK);
+       gfrc_halt_mask |= BIT(cpu);
+       __mcip_cmd_data(CMD_GFRC_SET_CORE, 0, gfrc_halt_mask);
+
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
+static void mcip_update_debug_halt_mask(int cpu)
+{
+       u32 mcip_mask = 0;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+
+       /*
+        * mcip_mask is same for CMD_DEBUG_SET_SELECT and CMD_DEBUG_SET_MASK
+        * commands. So read it once instead of reading both CMD_DEBUG_READ_MASK
+        * and CMD_DEBUG_READ_SELECT.
+        */
+       __mcip_cmd(CMD_DEBUG_READ_SELECT, 0);
+       mcip_mask = read_aux_reg(ARC_REG_MCIP_READBACK);
+
+       mcip_mask |= BIT(cpu);
+
+       __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, mcip_mask);
+       /*
+        * Parameter specified halt cause:
+        * STATUS32[H]/actionpoint/breakpoint/self-halt
+        * We choose all of them (0xF).
+        */
+       __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xF, mcip_mask);
+
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
 static void mcip_setup_per_cpu(int cpu)
 {
+       struct mcip_bcr mp;
+
+       READ_BCR(ARC_REG_MCIP_BCR, mp);
+
        smp_ipi_irq_setup(cpu, IPI_IRQ);
        smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
+
+       /* Update GFRC halt mask as new CPU came online */
+       if (mp.gfrc)
+               mcip_update_gfrc_halt_mask(cpu);
+
+       /* Update MCIP debug mask as new CPU came online */
+       if (mp.dbg)
+               mcip_update_debug_halt_mask(cpu);
 }
 
 static void mcip_ipi_send(int cpu)
@@ -101,11 +170,6 @@ static void mcip_probe_n_setup(void)
                IS_AVAIL1(mp.gfrc, "GFRC"));
 
        cpuinfo_arc700[0].extn.gfrc = mp.gfrc;
-
-       if (mp.dbg) {
-               __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf);
-               __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf);
-       }
 }
 
 struct plat_smp_ops plat_smp_ops = {
index ec12fe1c2f07334d01735376af9b839a89012234..b2cae79a25d716165eaf65060cb8ed0be11f3b6c 100644 (file)
@@ -51,7 +51,7 @@ static const struct id_to_str arc_cpu_rel[] = {
        { 0x51, "R2.0" },
        { 0x52, "R2.1" },
        { 0x53, "R3.0" },
-       { 0x54, "R4.0" },
+       { 0x54, "R3.10a" },
 #endif
        { 0x00, NULL   }
 };
index efe8b4200a676529a9f3f0af52d50faca176a1e3..21d86c36692b4f9bbf2e6c255832d7c98377c545 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/reboot.h>
 #include <linux/irqdomain.h>
 #include <linux/export.h>
+#include <linux/of_fdt.h>
 
 #include <asm/processor.h>
 #include <asm/setup.h>
@@ -47,6 +48,42 @@ void __init smp_prepare_boot_cpu(void)
 {
 }
 
+static int __init arc_get_cpu_map(const char *name, struct cpumask *cpumask)
+{
+       unsigned long dt_root = of_get_flat_dt_root();
+       const char *buf;
+
+       buf = of_get_flat_dt_prop(dt_root, name, NULL);
+       if (!buf)
+               return -EINVAL;
+
+       if (cpulist_parse(buf, cpumask))
+               return -EINVAL;
+
+       return 0;
+}
+
+/*
+ * Read from DeviceTree and setup cpu possible mask. If there is no
+ * "possible-cpus" property in DeviceTree pretend all [0..NR_CPUS-1] exist.
+ */
+static void __init arc_init_cpu_possible(void)
+{
+       struct cpumask cpumask;
+
+       if (arc_get_cpu_map("possible-cpus", &cpumask)) {
+               pr_warn("Failed to get possible-cpus from dtb, pretending all %u cpus exist\n",
+                       NR_CPUS);
+
+               cpumask_setall(&cpumask);
+       }
+
+       if (!cpumask_test_cpu(0, &cpumask))
+               panic("Master cpu (cpu[0]) is missed in cpu possible mask!");
+
+       init_cpu_possible(&cpumask);
+}
+
 /*
  * Called from setup_arch() before calling setup_processor()
  *
@@ -58,10 +95,7 @@ void __init smp_prepare_boot_cpu(void)
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i;
-
-       for (i = 0; i < NR_CPUS; i++)
-               set_cpu_possible(i, true);
+       arc_init_cpu_possible();
 
        if (plat_smp_ops.init_early_smp)
                plat_smp_ops.init_early_smp();
@@ -70,16 +104,12 @@ void __init smp_init_cpus(void)
 /* called from init ( ) =>  process 1 */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-       int i;
-
        /*
         * if platform didn't set the present map already, do it now
         * boot cpu is set to present already by init/main.c
         */
-       if (num_present_cpus() <= 1) {
-               for (i = 0; i < max_cpus; i++)
-                       set_cpu_present(i, true);
-       }
+       if (num_present_cpus() <= 1)
+               init_cpu_present(cpu_possible_mask);
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
index eee924dfffa6e1baf08221ee5e7e2cd23937d782..2072f3451e9c2127a076873113292a8ae2b5b9cb 100644 (file)
@@ -780,7 +780,10 @@ noinline static void slc_entire_op(const int op)
 
        write_aux_reg(r, ctrl);
 
-       write_aux_reg(ARC_REG_SLC_INVALIDATE, 1);
+       if (op & OP_INV)        /* Inv or flush-n-inv use same cmd reg */
+               write_aux_reg(ARC_REG_SLC_INVALIDATE, 0x1);
+       else
+               write_aux_reg(ARC_REG_SLC_FLUSH, 0x1);
 
        /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
        read_aux_reg(r);
index 18045c38bcf1af1f01b4732ae200cf274e3b6eec..db7cded1b7ada534ef34f49c27cd0dce34d7cdcc 100644 (file)
@@ -55,7 +55,7 @@
                      <0x3ff00100 0x100>;
        };
 
-       smc@0x3404c000 {
+       smc@3404c000 {
                compatible = "brcm,bcm11351-smc", "brcm,kona-smc";
                reg = <0x3404c000 0x400>; /* 1 KiB in SRAM */
        };
index 6dde95f21cef6b53c995b7311ddade7988dd965a..266f2611dc22126705aab35cb6cb67601e9f3704 100644 (file)
@@ -55,7 +55,7 @@
                      <0x3ff00100 0x100>;
        };
 
-       smc@0x3404e000 {
+       smc@3404e000 {
                compatible = "brcm,bcm21664-smc", "brcm,kona-smc";
                reg = <0x3404e000 0x400>; /* 1 KiB in SRAM */
        };
index 0e3d2a5ff2081425bd5ccb0097736ebdef3f99a5..a5c3824c80563cf3222f77af9a6ffe39e22b1e0f 100644 (file)
        soc {
                ranges = <0x7e000000 0x20000000 0x02000000>;
                dma-ranges = <0x40000000 0x00000000 0x20000000>;
+       };
 
-               arm-pmu {
-                       compatible = "arm,arm1176-pmu";
-               };
+       arm-pmu {
+               compatible = "arm,arm1176-pmu";
        };
 };
 
index 1dfd7644277736fb58fa4ad8352091677a000d5e..c933e841388421045d908e0147012d0fca0ae670 100644 (file)
@@ -9,19 +9,19 @@
                         <0x40000000 0x40000000 0x00001000>;
                dma-ranges = <0xc0000000 0x00000000 0x3f000000>;
 
-               local_intc: local_intc {
+               local_intc: local_intc@40000000 {
                        compatible = "brcm,bcm2836-l1-intc";
                        reg = <0x40000000 0x100>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        interrupt-parent = <&local_intc>;
                };
+       };
 
-               arm-pmu {
-                       compatible = "arm,cortex-a7-pmu";
-                       interrupt-parent = <&local_intc>;
-                       interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
-               };
+       arm-pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupt-parent = <&local_intc>;
+               interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        timer {
index efa7d3387ab287fb72e66659644a36903c85e5fc..7704bb029605ed94f3ea8aad77dfe301e4b0beac 100644 (file)
@@ -8,7 +8,7 @@
                         <0x40000000 0x40000000 0x00001000>;
                dma-ranges = <0xc0000000 0x00000000 0x3f000000>;
 
-               local_intc: local_intc {
+               local_intc: local_intc@40000000 {
                        compatible = "brcm,bcm2836-l1-intc";
                        reg = <0x40000000 0x100>;
                        interrupt-controller;
index 18db25a5a66e0c1685457cd7959bdf239db5c76c..9d293decf8d353cdda502f5035212d967c364973 100644 (file)
                        status = "disabled";
                };
 
-               aux: aux@0x7e215000 {
+               aux: aux@7e215000 {
                        compatible = "brcm,bcm2835-aux";
                        #clock-cells = <1>;
                        reg = <0x7e215000 0x8>;
index 6a44b8021702176c63d09e55925ffd3d7e02994e..f0e2008f7490146a22ae06fbc310dbe5cb18c4d5 100644 (file)
@@ -49,7 +49,7 @@
 
        memory {
                device_type = "memory";
-               reg = <0x60000000 0x80000000>;
+               reg = <0x60000000 0x20000000>;
        };
 
        gpio-restart {
index 08568ce24d06fc9576b57c373ab96aedc80c23b7..da8bb9d60f99e6b5af6a3e7ff4c30215f6a91844 100644 (file)
 
                sata: sata@46000000 {
                        /* The ROM uses this muxmode */
-                       cortina,gemini-ata-muxmode = <3>;
+                       cortina,gemini-ata-muxmode = <0>;
                        cortina,gemini-enable-sata-bridge;
                        status = "okay";
                };
index cf42c2f5cdc7f9d13409efbd8db6d18d969f2511..1281bc39b7ab87a430b5edaaacf187b82526186d 100644 (file)
@@ -42,7 +42,7 @@
 
 /dts-v1/;
 
-#include "imx6q.dtsi"
+#include "imx6dl.dtsi"
 #include "imx6qdl-icore-rqs.dtsi"
 
 / {
index c1aa7a4518fbaca19e734795e25b4767a06a6005..a30ee9fcb3ae537dacabc5ff8e942ef26933bcfd 100644 (file)
@@ -71,6 +71,8 @@
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        clock-frequency = <2600000>;
 
        twl: twl@48 {
                >;
        };
 
-
+       i2c1_pins: pinmux_i2c1_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0)        /* i2c1_scl.i2c1_scl */
+                       OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0)        /* i2c1_sda.i2c1_sda */
+               >;
+       };
 };
 
 &omap3_pmx_wkup {
index b50b796e15c778237926e91848e17802f584eb7c..47915447a82660c9a459b7041886be1cb6e52f1a 100644 (file)
@@ -66,6 +66,8 @@
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        clock-frequency = <2600000>;
 
        twl: twl@48 {
                        OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT | MUX_MODE0)        /* hsusb0_data7.hsusb0_data7 */
                >;
        };
+       i2c1_pins: pinmux_i2c1_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0)        /* i2c1_scl.i2c1_scl */
+                       OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0)        /* i2c1_sda.i2c1_sda */
+               >;
+       };
 };
 
 &uart2 {
index ec2c8baef62ac00bf40b7ae1d28da2eab3a327d0..592e17fd4eeb7ccd1faa8f9d16635cf562092982 100644 (file)
@@ -47,7 +47,7 @@
                        gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;    /* gpio3_83 */
                        wakeup-source;
                        autorepeat;
-                       debounce_interval = <50>;
+                       debounce-interval = <50>;
                };
        };
 
index 3b704cfed69ac1f7b39343925fb2037c9e78e10b..a97458112ff6e80ca198fe1377521372973e8ca4 100644 (file)
                max-frequency = <37500000>;
                clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
                         <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
                resets = <&cru SRST_SDIO>;
                max-frequency = <37500000>;
                clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
                         <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                default-sample-phase = <158>;
                disable-wp;
                dmas = <&pdma 12>;
index 780ec3a99b21f857b414d4d47b8e773cd28c7788..341deaf62ff621ad9122b7b9c2c9950edf5eaa71 100644 (file)
                interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
                         <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                pinctrl-names = "default";
                pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
                         <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                pinctrl-names = "default";
                pinctrl-0 = <&sdio_clk &sdio_cmd &sdio_bus4>;
                max-frequency = <37500000>;
                clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
                         <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                bus-width = <8>;
                default-sample-phase = <158>;
                fifo-depth = <0x100>;
index 99cfae875e12e6e3ec9e333c7534a058bbe0a3e8..5eae4776ffdeece372e74cc2ba799103b99cb04f 100644 (file)
        };
 };
 
-&cpu0 {
-       cpu0-supply = <&vdd_cpu>;
-       operating-points = <
-               /* KHz    uV */
-               1800000 1400000
-               1608000 1350000
-               1512000 1300000
-               1416000 1200000
-               1200000 1100000
-               1008000 1050000
-                816000 1000000
-                696000  950000
-                600000  900000
-                408000  900000
-                312000  900000
-                216000  900000
-                126000  900000
-       >;
-};
-
 &emmc {
        status = "okay";
        bus-width = <8>;
index 8a74efdb636062e28e309e130f557e5bc582d65f..240e7a23d81ff3cc2eb2facad8a126970775a152 100644 (file)
@@ -56,7 +56,7 @@
                        clocks = <&topclk ZX296702_A9_PERIPHCLK>;
                };
 
-               l2cc: l2-cache-controller@0x00c00000 {
+               l2cc: l2-cache-controller@c00000 {
                        compatible = "arm,pl310-cache";
                        reg = <0x00c00000 0x1000>;
                        cache-unified;
                        arm,double-linefill-incr = <0>;
                };
 
-               pcu: pcu@0xa0008000 {
+               pcu: pcu@a0008000 {
                        compatible = "zte,zx296702-pcu";
                        reg = <0xa0008000 0x1000>;
                };
 
-               topclk: topclk@0x09800000 {
+               topclk: topclk@9800000 {
                        compatible = "zte,zx296702-topcrm-clk";
                        reg = <0x09800000 0x1000>;
                        #clock-cells = <1>;
                };
 
-               lsp1clk: lsp1clk@0x09400000 {
+               lsp1clk: lsp1clk@9400000 {
                        compatible = "zte,zx296702-lsp1crpm-clk";
                        reg = <0x09400000 0x1000>;
                        #clock-cells = <1>;
                };
 
-               lsp0clk: lsp0clk@0x0b000000 {
+               lsp0clk: lsp0clk@b000000 {
                        compatible = "zte,zx296702-lsp0crpm-clk";
                        reg = <0x0b000000 0x1000>;
                        #clock-cells = <1>;
                };
 
-               uart0: serial@0x09405000 {
+               uart0: serial@9405000 {
                        compatible = "zte,zx296702-uart";
                        reg = <0x09405000 0x1000>;
                        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
@@ -98,7 +98,7 @@
                        status = "disabled";
                };
 
-               uart1: serial@0x09406000 {
+               uart1: serial@9406000 {
                        compatible = "zte,zx296702-uart";
                        reg = <0x09406000 0x1000>;
                        interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                };
 
-               mmc0: mmc@0x09408000 {
+               mmc0: mmc@9408000 {
                        compatible = "snps,dw-mshc";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                };
 
-               mmc1: mmc@0x0b003000 {
+               mmc1: mmc@b003000 {
                        compatible = "snps,dw-mshc";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                };
 
-               sysctrl: sysctrl@0xa0007000 {
+               sysctrl: sysctrl@a0007000 {
                        compatible = "zte,sysctrl", "syscon";
                        reg = <0xa0007000 0x1000>;
                };
index 2f145c4af93a0fb387d86fea028d0c82d0041be8..92674f247a12a48ee603f992c075a8d6ac5c7d71 100644 (file)
@@ -319,7 +319,7 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_RC_CORE=m
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
-CONFIG_LIRC=m
+CONFIG_LIRC=y
 CONFIG_RC_DEVICES=y
 CONFIG_IR_RX51=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
index 5638ce0c95241f7f3afd3e994aaa9993347c9be7..63d6b404d88e39bf581c0434aff5d6b0e951279f 100644 (file)
@@ -7,6 +7,8 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING
 
 KVM=../../../../virt/kvm
 
+CFLAGS_ARMV7VE            :=$(call cc-option, -march=armv7ve)
+
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
@@ -15,7 +17,10 @@ obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
 obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
 obj-$(CONFIG_KVM_ARM_HOST) += vfp.o
 obj-$(CONFIG_KVM_ARM_HOST) += banked-sr.o
+CFLAGS_banked-sr.o        += $(CFLAGS_ARMV7VE)
+
 obj-$(CONFIG_KVM_ARM_HOST) += entry.o
 obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
 obj-$(CONFIG_KVM_ARM_HOST) += switch.o
+CFLAGS_switch.o                   += $(CFLAGS_ARMV7VE)
 obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o
index 111bda8cdebdc7e59789103838087920aedf0efe..be4b8b0a40ade5c8e412bbc75f2b311c389aa979 100644 (file)
 
 #include <asm/kvm_hyp.h>
 
+/*
+ * gcc before 4.9 doesn't understand -march=armv7ve, so we have to
+ * trick the assembler.
+ */
 __asm__(".arch_extension     virt");
 
 void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt)
index ee1f83b1a3324383b09106f01b830ea2802e210d..4c89a8e9a2e374cedfe92941661f38c2b6bc3b10 100644 (file)
@@ -69,7 +69,7 @@ static void clps711x_restart(enum reboot_mode mode, const char *cmd)
        soft_restart(0);
 }
 
-static const char *clps711x_compat[] __initconst = {
+static const char *const clps711x_compat[] __initconst = {
        "cirrus,ep7209",
        NULL
 };
index e457f299cd4430d359063788886d244a53d39f12..d6b11907380c83ddce9bc4998835a11e7a466ec7 100644 (file)
@@ -368,7 +368,7 @@ static struct spi_eeprom at25640a = {
        .flags          = EE_ADDR2,
 };
 
-static struct spi_board_info dm355_evm_spi_info[] __initconst = {
+static const struct spi_board_info dm355_evm_spi_info[] __initconst = {
        {
                .modalias       = "at25",
                .platform_data  = &at25640a,
index be997243447b949699fd116970ec0aacaffbf444..fad9a5611a5d276ce15f0fcfe9aedcc9a5d03802 100644 (file)
@@ -217,7 +217,7 @@ static struct spi_eeprom at25640a = {
        .flags          = EE_ADDR2,
 };
 
-static struct spi_board_info dm355_leopard_spi_info[] __initconst = {
+static const struct spi_board_info dm355_leopard_spi_info[] __initconst = {
        {
                .modalias       = "at25",
                .platform_data  = &at25640a,
index e75741fb2c1da095bd59ba4e0f411a6274ce6255..e3780986d2a3b40aff033f0a22759be80272cf39 100644 (file)
@@ -726,7 +726,7 @@ static struct spi_eeprom at25640 = {
        .flags          = EE_ADDR2,
 };
 
-static struct spi_board_info dm365_evm_spi_info[] __initconst = {
+static const struct spi_board_info dm365_evm_spi_info[] __initconst = {
        {
                .modalias       = "at25",
                .platform_data  = &at25640,
index 6b32dc527edcd58396dc94781992f3970cc8e793..2c20599cc3506326eddc2993afd8df2bd308e268 100644 (file)
@@ -41,7 +41,7 @@ config MACH_ARMADA_375
        depends on ARCH_MULTI_V7
        select ARMADA_370_XP_IRQ
        select ARM_ERRATA_720789
-       select ARM_ERRATA_753970
+       select PL310_ERRATA_753970
        select ARM_GIC
        select ARMADA_375_CLK
        select HAVE_ARM_SCU
@@ -57,7 +57,7 @@ config MACH_ARMADA_38X
        bool "Marvell Armada 380/385 boards"
        depends on ARCH_MULTI_V7
        select ARM_ERRATA_720789
-       select ARM_ERRATA_753970
+       select PL310_ERRATA_753970
        select ARM_GIC
        select ARM_GLOBAL_TIMER
        select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
index 43e3e188f521341884d0a6e280d5724ef606e13f..fa512413a47172212483ebec6811bc5547aa729b 100644 (file)
@@ -1011,17 +1011,17 @@ static int clk_debugfs_register_one(struct clk *c)
                return -ENOMEM;
        c->dent = d;
 
-       d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
+       d = debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
        if (!d) {
                err = -ENOMEM;
                goto err_out;
        }
-       d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+       d = debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate);
        if (!d) {
                err = -ENOMEM;
                goto err_out;
        }
-       d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
+       d = debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags);
        if (!d) {
                err = -ENOMEM;
                goto err_out;
index 4bb6751864a50e046e74c0952ad75571e1d979d0..fc5fb776a7101234bd64da673815d10a0b75f0f2 100644 (file)
@@ -299,8 +299,6 @@ static void irq_save_context(void)
        if (soc_is_dra7xx())
                return;
 
-       if (!sar_base)
-               sar_base = omap4_get_sar_ram_base();
        if (wakeupgen_ops && wakeupgen_ops->save_context)
                wakeupgen_ops->save_context();
 }
@@ -598,6 +596,8 @@ static int __init wakeupgen_init(struct device_node *node,
        irq_hotplug_init();
        irq_pm_init();
 
+       sar_base = omap4_get_sar_ram_base();
+
        return 0;
 }
 IRQCHIP_DECLARE(ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init);
index 124f9af34a15a3145edecb30108ced8a3b13a2f5..34156eca8e234f45745e849fb460fd42381cfa76 100644 (file)
@@ -977,6 +977,9 @@ static int _enable_clocks(struct omap_hwmod *oh)
 
        pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
 
+       if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
+               _enable_optional_clocks(oh);
+
        if (oh->_clk)
                clk_enable(oh->_clk);
 
@@ -985,9 +988,6 @@ static int _enable_clocks(struct omap_hwmod *oh)
                        clk_enable(os->_clk);
        }
 
-       if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
-               _enable_optional_clocks(oh);
-
        /* The opt clocks are controlled by the device driver. */
 
        return 0;
index 366158a54fcd8beae9ff50d712e1b5c63f87d456..6f68576e56956a635acae35af565d09bb2ff2d0f 100644 (file)
@@ -186,7 +186,7 @@ static void omap_pm_end(void)
        cpu_idle_poll_ctrl(false);
 }
 
-static void omap_pm_finish(void)
+static void omap_pm_wake(void)
 {
        if (soc_is_omap34xx())
                omap_prcm_irq_complete();
@@ -196,7 +196,7 @@ static const struct platform_suspend_ops omap_pm_ops = {
        .begin          = omap_pm_begin,
        .end            = omap_pm_end,
        .enter          = omap_pm_enter,
-       .finish         = omap_pm_finish,
+       .wake           = omap_pm_wake,
        .valid          = suspend_valid_only_mem,
 };
 
index ece09c9461f78d9b3908095615a688522b69e9b3..d61fbd7a2840a4980205c16d1c675a957c6292c8 100644 (file)
@@ -156,12 +156,6 @@ static struct clock_event_device clockevent_gpt = {
        .tick_resume            = omap2_gp_timer_shutdown,
 };
 
-static struct property device_disabled = {
-       .name = "status",
-       .length = sizeof("disabled"),
-       .value = "disabled",
-};
-
 static const struct of_device_id omap_timer_match[] __initconst = {
        { .compatible = "ti,omap2420-timer", },
        { .compatible = "ti,omap3430-timer", },
@@ -203,8 +197,17 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id *
                                  of_get_property(np, "ti,timer-secure", NULL)))
                        continue;
 
-               if (!of_device_is_compatible(np, "ti,omap-counter32k"))
-                       of_add_property(np, &device_disabled);
+               if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
+                       struct property *prop;
+
+                       prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+                       if (!prop)
+                               return NULL;
+                       prop->name = "status";
+                       prop->value = "disabled";
+                       prop->length = strlen(prop->value);
+                       of_add_property(np, prop);
+               }
                return np;
        }
 
index aff6994950ba6db7eb6579a90cc94e5b2bfc7329..a2399fd66e97cef3db011508dc73c718c9456bc9 100644 (file)
@@ -472,28 +472,27 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
 /*****************************************************************************
  * Ethernet switch
  ****************************************************************************/
-static __initconst const char *orion_ge00_mvmdio_bus_name = "orion-mii";
-static __initdata struct mdio_board_info
-                 orion_ge00_switch_board_info;
+static __initdata struct mdio_board_info orion_ge00_switch_board_info = {
+       .bus_id   = "orion-mii",
+       .modalias = "mv88e6085",
+};
 
 void __init orion_ge00_switch_init(struct dsa_chip_data *d)
 {
-       struct mdio_board_info *bd;
        unsigned int i;
 
        if (!IS_BUILTIN(CONFIG_PHYLIB))
                return;
 
-       for (i = 0; i < ARRAY_SIZE(d->port_names); i++)
-               if (!strcmp(d->port_names[i], "cpu"))
+       for (i = 0; i < ARRAY_SIZE(d->port_names); i++) {
+               if (!strcmp(d->port_names[i], "cpu")) {
+                       d->netdev[i] = &orion_ge00.dev;
                        break;
+               }
+       }
 
-       bd = &orion_ge00_switch_board_info;
-       bd->bus_id = orion_ge00_mvmdio_bus_name;
-       bd->mdio_addr = d->sw_addr;
-       d->netdev[i] = &orion_ge00.dev;
-       strcpy(bd->modalias, "mv88e6085");
-       bd->platform_data = d;
+       orion_ge00_switch_board_info.mdio_addr = d->sw_addr;
+       orion_ge00_switch_board_info.platform_data = d;
 
        mdiobus_register_board_info(&orion_ge00_switch_board_info, 1);
 }
index a80632641b39f8cb5dc8554aa2b2e85b6551e0ea..70c776ef7aa7321450def075b8f150ef1dbbbf9f 100644 (file)
 
                        uart_A: serial@24000 {
                                compatible = "amlogic,meson-gx-uart", "amlogic,meson-uart";
-                               reg = <0x0 0x24000 0x0 0x14>;
+                               reg = <0x0 0x24000 0x0 0x18>;
                                interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
 
                        uart_B: serial@23000 {
                                compatible = "amlogic,meson-gx-uart", "amlogic,meson-uart";
-                               reg = <0x0 0x23000 0x0 0x14>;
+                               reg = <0x0 0x23000 0x0 0x18>;
                                interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
index 6cb3c2a52bafe5f0db8a0018b35e88998ed90f01..4ee2e7951482f43122620d2668b244de1744e6b9 100644 (file)
 
                        uart_A: serial@84c0 {
                                compatible = "amlogic,meson-gx-uart";
-                               reg = <0x0 0x84c0 0x0 0x14>;
+                               reg = <0x0 0x84c0 0x0 0x18>;
                                interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
 
                        uart_B: serial@84dc {
                                compatible = "amlogic,meson-gx-uart";
-                               reg = <0x0 0x84dc 0x0 0x14>;
+                               reg = <0x0 0x84dc 0x0 0x18>;
                                interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
 
                        uart_C: serial@8700 {
                                compatible = "amlogic,meson-gx-uart";
-                               reg = <0x0 0x8700 0x0 0x14>;
+                               reg = <0x0 0x8700 0x0 0x18>;
                                interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
 
                        uart_AO: serial@4c0 {
                                compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart";
-                               reg = <0x0 0x004c0 0x0 0x14>;
+                               reg = <0x0 0x004c0 0x0 0x18>;
                                interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
 
                        uart_AO_B: serial@4e0 {
                                compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart";
-                               reg = <0x0 0x004e0 0x0 0x14>;
+                               reg = <0x0 0x004e0 0x0 0x18>;
                                interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
index 4f355f17eed6bcc29dcc14fb4546fce6a083a57f..c8514110b9da2dc2f40988ad0ae733437e33420a 100644 (file)
 
                        internal_phy: ethernet-phy@8 {
                                compatible = "ethernet-phy-id0181.4400", "ethernet-phy-ieee802.3-c22";
+                               interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
                                reg = <8>;
                                max-speed = <100>;
                        };
index 4220fbdcb24a7f18c5e3ab66574ba22c8c92c873..ff5c4c47b22bfecfa36f0090dc8be5c85b171271 100644 (file)
@@ -98,7 +98,7 @@
                clock-output-names = "clk125mhz";
        };
 
-       pci {
+       pcie@30000000 {
                compatible = "pci-host-ecam-generic";
                device_type = "pci";
                #interrupt-cells = <1>;
                ranges =
                  <0x02000000    0 0x40000000    0 0x40000000    0 0x20000000
                   0x43000000 0x40 0x00000000 0x40 0x00000000 0x20 0x00000000>;
+               bus-range = <0 0xff>;
                interrupt-map-mask = <0 0 0 7>;
                interrupt-map =
                      /* addr  pin  ic   icaddr  icintr */
index e94fa1a531922ee6b160246c4399435574909641..047641fe294c64c9dbc04dcb477827814a809677 100644 (file)
@@ -51,7 +51,7 @@
                #size-cells = <2>;
                ranges;
 
-               ramoops@0x21f00000 {
+               ramoops@21f00000 {
                        compatible = "ramoops";
                        reg = <0x0 0x21f00000 0x0 0x00100000>;
                        record-size     = <0x00020000>;
index 9fbe4705ee88bfaf1eb12a7208de0c5899d7f9d3..94597e33c8065eb4b12ee805885988991d43e42c 100644 (file)
                        reg = <0 0x10005000 0 0x1000>;
                };
 
-               pio: pinctrl@0x10005000 {
+               pio: pinctrl@10005000 {
                        compatible = "mediatek,mt8173-pinctrl";
                        reg = <0 0x1000b000 0 0x1000>;
                        mediatek,pctl-regmap = <&syscfg_pctl_a>;
index 492a011f14f6cef933dc16ce9cf591d8cdc5c79e..1c8f1b86472de9c149b706502dcc552f19376ae5 100644 (file)
                };
 
                agnoc@0 {
-                       qcom,pcie@00600000 {
+                       qcom,pcie@600000 {
                                perst-gpio = <&msmgpio 35 GPIO_ACTIVE_LOW>;
                        };
 
-                       qcom,pcie@00608000 {
+                       qcom,pcie@608000 {
                                status = "okay";
                                perst-gpio = <&msmgpio 130 GPIO_ACTIVE_LOW>;
                        };
 
-                       qcom,pcie@00610000 {
+                       qcom,pcie@610000 {
                                status = "okay";
                                perst-gpio = <&msmgpio 114 GPIO_ACTIVE_LOW>;
                        };
index 4b2afcc4fdf4791da816c6bba3c6f2ef7741ad8d..0a6f7952bbb18d65847261957715e331756c46c4 100644 (file)
                        #size-cells = <1>;
                        ranges;
 
-                       pcie0: qcom,pcie@00600000 {
+                       pcie0: qcom,pcie@600000 {
                                compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
                                status = "disabled";
                                power-domains = <&gcc PCIE0_GDSC>;
 
                        };
 
-                       pcie1: qcom,pcie@00608000 {
+                       pcie1: qcom,pcie@608000 {
                                compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
                                power-domains = <&gcc PCIE1_GDSC>;
                                bus-range = <0x00 0xff>;
                                                "bus_slave";
                        };
 
-                       pcie2: qcom,pcie@00610000 {
+                       pcie2: qcom,pcie@610000 {
                                compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
                                power-domains = <&gcc PCIE2_GDSC>;
                                bus-range = <0x00 0xff>;
index 3890468678ce1caa78a411aeb0a4a9cdedfc1302..28257724a56e74b79b83c69a76bea0da4e0fd9ed 100644 (file)
        assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
        assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>;
        clock_in_out = "input";
-       /* shows instability at 1GBit right now */
-       max-speed = <100>;
        phy-supply = <&vcc_io>;
        phy-mode = "rgmii";
        pinctrl-names = "default";
        pinctrl-0 = <&rgmiim1_pins>;
+       snps,force_thresh_dma_mode;
        snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
        snps,reset-active-low;
        snps,reset-delays-us = <0 10000 50000>;
-       tx_delay = <0x26>;
-       rx_delay = <0x11>;
+       tx_delay = <0x24>;
+       rx_delay = <0x18>;
        status = "okay";
 };
 
index a037ee56fead6db1b0bcedbbf740f6a54ca82977..cae3415544862dfddf06a034ecea62bd50739fd2 100644 (file)
                interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
                         <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                status = "disabled";
        };
                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
                         <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                status = "disabled";
        };
                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
                         <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                status = "disabled";
        };
index aa4d07046a7ba9644316cd7c57b43b64b5327766..03458ac44201c7c66d0e991881ab24e292bfdee2 100644 (file)
                max-frequency = <150000000>;
                clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
                         <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
-               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
                resets = <&cru SRST_SDIO0>;
index 0f873c897d0de5a75f9d4e4d90d7c658b7a173d3..ce592a4c0c4cdeb473a1c96106620583a8a4abef 100644 (file)
        assigned-clocks = <&cru SCLK_PCIEPHY_REF>;
        assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>;
        assigned-clock-rates = <100000000>;
-       ep-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_HIGH>;
+       ep-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
        num-lanes = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&pcie_clkreqn_cpm>;
index 7aa2144e0d47d1fb8e30a2389d4d0fbc5fc4030f..2605118d4b4ce74755ced75843d91ca22ad38ce8 100644 (file)
                compatible = "rockchip,rk3399-edp";
                reg = <0x0 0xff970000 0x0 0x8000>;
                interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH 0>;
-               clocks = <&cru PCLK_EDP>, <&cru PCLK_EDP_CTRL>;
-               clock-names = "dp", "pclk";
+               clocks = <&cru PCLK_EDP>, <&cru PCLK_EDP_CTRL>, <&cru PCLK_VIO_GRF>;
+               clock-names = "dp", "pclk", "grf";
                pinctrl-names = "default";
                pinctrl-0 = <&edp_hpd>;
                power-domains = <&power RK3399_PD_EDP>;
index 3742508cc5345882510d907dc5f58b48a08ad9e7..bd5ce31936f5b196c3ce0482ee962eb93df46216 100644 (file)
@@ -26,6 +26,7 @@ void flush_user_icache_range_asm(unsigned long, unsigned long);
 void flush_kernel_icache_range_asm(unsigned long, unsigned long);
 void flush_user_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
+void purge_kernel_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_page_asm(void *);
 void flush_kernel_icache_page(void *);
 
index 0e6ab6e4a4e9f87ba8ffc17f4d1c1e0041b5ab02..2dbe5580a1a4420ba693329a0f2622f68f759276 100644 (file)
@@ -316,6 +316,8 @@ extern int _parisc_requires_coherency;
 #define parisc_requires_coherency()    (0)
 #endif
 
+extern int running_on_qemu;
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_PARISC_PROCESSOR_H */
index 19c0c141bc3f9f0edd509708f978a2d7ca16c230..79089778725b317888d0ecdab4feab490207e4d3 100644 (file)
@@ -465,10 +465,10 @@ EXPORT_SYMBOL(copy_user_page);
 int __flush_tlb_range(unsigned long sid, unsigned long start,
                      unsigned long end)
 {
-       unsigned long flags, size;
+       unsigned long flags;
 
-       size = (end - start);
-       if (size >= parisc_tlb_flush_threshold) {
+       if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+           end - start >= parisc_tlb_flush_threshold) {
                flush_tlb_all();
                return 1;
        }
@@ -539,13 +539,11 @@ void flush_cache_mm(struct mm_struct *mm)
        struct vm_area_struct *vma;
        pgd_t *pgd;
 
-       /* Flush the TLB to avoid speculation if coherency is required. */
-       if (parisc_requires_coherency())
-               flush_tlb_all();
-
        /* Flushing the whole cache on each cpu takes forever on
           rp3440, etc.  So, avoid it if the mm isn't too big.  */
-       if (mm_total_size(mm) >= parisc_cache_flush_threshold) {
+       if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+           mm_total_size(mm) >= parisc_cache_flush_threshold) {
+               flush_tlb_all();
                flush_cache_all();
                return;
        }
@@ -553,9 +551,9 @@ void flush_cache_mm(struct mm_struct *mm)
        if (mm->context == mfsp(3)) {
                for (vma = mm->mmap; vma; vma = vma->vm_next) {
                        flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
-                       if ((vma->vm_flags & VM_EXEC) == 0)
-                               continue;
-                       flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
+                       if (vma->vm_flags & VM_EXEC)
+                               flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
+                       flush_tlb_range(vma, vma->vm_start, vma->vm_end);
                }
                return;
        }
@@ -581,14 +579,9 @@ void flush_cache_mm(struct mm_struct *mm)
 void flush_cache_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end)
 {
-       BUG_ON(!vma->vm_mm->context);
-
-       /* Flush the TLB to avoid speculation if coherency is required. */
-       if (parisc_requires_coherency())
+       if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+           end - start >= parisc_cache_flush_threshold) {
                flush_tlb_range(vma, start, end);
-
-       if ((end - start) >= parisc_cache_flush_threshold
-           || vma->vm_mm->context != mfsp(3)) {
                flush_cache_all();
                return;
        }
@@ -596,6 +589,7 @@ void flush_cache_range(struct vm_area_struct *vma,
        flush_user_dcache_range_asm(start, end);
        if (vma->vm_flags & VM_EXEC)
                flush_user_icache_range_asm(start, end);
+       flush_tlb_range(vma, start, end);
 }
 
 void
@@ -604,8 +598,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
        BUG_ON(!vma->vm_mm->context);
 
        if (pfn_valid(pfn)) {
-               if (parisc_requires_coherency())
-                       flush_tlb_page(vma, vmaddr);
+               flush_tlb_page(vma, vmaddr);
                __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
        }
 }
@@ -613,21 +606,33 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
 void flush_kernel_vmap_range(void *vaddr, int size)
 {
        unsigned long start = (unsigned long)vaddr;
+       unsigned long end = start + size;
 
-       if ((unsigned long)size > parisc_cache_flush_threshold)
+       if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+           (unsigned long)size >= parisc_cache_flush_threshold) {
+               flush_tlb_kernel_range(start, end);
                flush_data_cache();
-       else
-               flush_kernel_dcache_range_asm(start, start + size);
+               return;
+       }
+
+       flush_kernel_dcache_range_asm(start, end);
+       flush_tlb_kernel_range(start, end);
 }
 EXPORT_SYMBOL(flush_kernel_vmap_range);
 
 void invalidate_kernel_vmap_range(void *vaddr, int size)
 {
        unsigned long start = (unsigned long)vaddr;
+       unsigned long end = start + size;
 
-       if ((unsigned long)size > parisc_cache_flush_threshold)
+       if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+           (unsigned long)size >= parisc_cache_flush_threshold) {
+               flush_tlb_kernel_range(start, end);
                flush_data_cache();
-       else
-               flush_kernel_dcache_range_asm(start, start + size);
+               return;
+       }
+
+       purge_kernel_dcache_range_asm(start, end);
+       flush_tlb_kernel_range(start, end);
 }
 EXPORT_SYMBOL(invalidate_kernel_vmap_range);
index bbbe360b458f511c068620db2dd670a770ea8362..fbb4e43fda05332de57bdc135ec3711d4bd5ee77 100644 (file)
@@ -138,6 +138,16 @@ $pgt_fill_loop:
        std             %dp,0x18(%r10)
 #endif
 
+#ifdef CONFIG_64BIT
+       /* Get PDCE_PROC for monarch CPU. */
+#define MEM_PDC_LO 0x388
+#define MEM_PDC_HI 0x35C
+       ldw             MEM_PDC_LO(%r0),%r3
+       ldw             MEM_PDC_HI(%r0),%r10
+       depd            %r10, 31, 32, %r3        /* move to upper word */
+#endif
+
+
 #ifdef CONFIG_SMP
        /* Set the smp rendezvous address into page zero.
        ** It would be safer to do this in init_smp_config() but
@@ -196,12 +206,6 @@ common_stext:
         ** Someday, palo might not do this for the Monarch either.
         */
 2:
-#define MEM_PDC_LO 0x388
-#define MEM_PDC_HI 0x35C
-       ldw             MEM_PDC_LO(%r0),%r3
-       ldw             MEM_PDC_HI(%r0),%r6
-       depd            %r6, 31, 32, %r3        /* move to upper word */
-
        mfctl           %cr30,%r6               /* PCX-W2 firmware bug */
 
        ldo             PDC_PSW(%r0),%arg0              /* 21 */
@@ -268,6 +272,8 @@ $install_iva:
 aligned_rfi:
        pcxt_ssm_bug
 
+       copy            %r3, %arg0      /* PDCE_PROC for smp_callin() */
+
        rsm             PSW_SM_QUIET,%r0        /* off troublesome PSW bits */
        /* Don't need NOPs, have 8 compliant insn before rfi */
 
index 2d40c4ff3f6918ae9b2e2c6af71e20658a9850e1..67b0f7532e835f4db1214c6ccecf62183eb84e50 100644 (file)
@@ -1110,6 +1110,28 @@ ENTRY_CFI(flush_kernel_dcache_range_asm)
        .procend
 ENDPROC_CFI(flush_kernel_dcache_range_asm)
 
+ENTRY_CFI(purge_kernel_dcache_range_asm)
+       .proc
+       .callinfo NO_CALLS
+       .entry
+
+       ldil            L%dcache_stride, %r1
+       ldw             R%dcache_stride(%r1), %r23
+       ldo             -1(%r23), %r21
+       ANDCM           %r26, %r21, %r26
+
+1:      cmpb,COND(<<),n        %r26, %r25,1b
+       pdc,m           %r23(%r26)
+
+       sync
+       syncdma
+       bv              %r0(%r2)
+       nop
+       .exit
+
+       .procend
+ENDPROC_CFI(purge_kernel_dcache_range_asm)
+
 ENTRY_CFI(flush_user_icache_range_asm)
        .proc
        .callinfo NO_CALLS
index 30c28ab145409b5966f7237ec2b6ca07121adc10..4065b5e48c9d68e70b38da3743e219e02934fe5b 100644 (file)
@@ -292,10 +292,15 @@ smp_cpu_init(int cpunum)
  * Slaves start using C here. Indirectly called from smp_slave_stext.
  * Do what start_kernel() and main() do for boot strap processor (aka monarch)
  */
-void __init smp_callin(void)
+void __init smp_callin(unsigned long pdce_proc)
 {
        int slave_id = cpu_now_booting;
 
+#ifdef CONFIG_64BIT
+       WARN_ON(((unsigned long)(PAGE0->mem_pdc_hi) << 32
+                       | PAGE0->mem_pdc) != pdce_proc);
+#endif
+
        smp_cpu_init(slave_id);
        preempt_disable();
 
index 4b8fd6dc22dabebcf1da3b2e32381d2df3197eda..f7e684560186f9c3d5db133b8e66281c0f3c0e12 100644 (file)
@@ -76,10 +76,10 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
        next_tick = cpuinfo->it_value;
 
        /* Calculate how many ticks have elapsed. */
+       now = mfctl(16);
        do {
                ++ticks_elapsed;
                next_tick += cpt;
-               now = mfctl(16);
        } while (next_tick - now > cpt);
 
        /* Store (in CR16 cycles) up to when we are accounting right now. */
@@ -103,16 +103,17 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
         * if one or the other wrapped. If "now" is "bigger" we'll end up
         * with a very large unsigned number.
         */
-       while (next_tick - mfctl(16) > cpt)
+       now = mfctl(16);
+       while (next_tick - now > cpt)
                next_tick += cpt;
 
        /* Program the IT when to deliver the next interrupt.
         * Only bottom 32-bits of next_tick are writable in CR16!
         * Timer interrupt will be delivered at least a few hundred cycles
-        * after the IT fires, so if we are too close (<= 500 cycles) to the
+        * after the IT fires, so if we are too close (<= 8000 cycles) to the
         * next cycle, simply skip it.
         */
-       if (next_tick - mfctl(16) <= 500)
+       if (next_tick - now <= 8000)
                next_tick += cpt;
        mtctl(next_tick, 16);
 
@@ -248,7 +249,7 @@ static int __init init_cr16_clocksource(void)
         * different sockets, so mark them unstable and lower rating on
         * multi-socket SMP systems.
         */
-       if (num_online_cpus() > 1) {
+       if (num_online_cpus() > 1 && !running_on_qemu) {
                int cpu;
                unsigned long cpu0_loc;
                cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;
index 48f41399fc0b8b63acd84d774a09ad2d0aba5086..cab32ee824d2ac4b7fe9adf4f3bb25533cc043c6 100644 (file)
@@ -629,7 +629,12 @@ void __init mem_init(void)
 #endif
 
        mem_init_print_info(NULL);
-#ifdef CONFIG_DEBUG_KERNEL /* double-sanity-check paranoia */
+
+#if 0
+       /*
+        * Do not expose the virtual kernel memory layout to userspace.
+        * But keep code for debugging purposes.
+        */
        printk("virtual kernel memory layout:\n"
               "    vmalloc : 0x%px - 0x%px   (%4ld MB)\n"
               "    memory  : 0x%px - 0x%px   (%4ld MB)\n"
index c0319cbf1eec58d7ea8960259838b865c23f49a1..5510366d169aea821e9f09ffe613363a2009db93 100644 (file)
@@ -34,9 +34,9 @@
 #define wmb()          RISCV_FENCE(ow,ow)
 
 /* These barriers do not need to enforce ordering on devices, just memory. */
-#define smp_mb()       RISCV_FENCE(rw,rw)
-#define smp_rmb()      RISCV_FENCE(r,r)
-#define smp_wmb()      RISCV_FENCE(w,w)
+#define __smp_mb()     RISCV_FENCE(rw,rw)
+#define __smp_rmb()    RISCV_FENCE(r,r)
+#define __smp_wmb()    RISCV_FENCE(w,w)
 
 /*
  * This is a very specific barrier: it's currently only used in two places in
index 9c7d707158622e7f0743570db60599fa95a9de3b..07c6e81163bf5e248c1b744f69b75548aeae5d44 100644 (file)
 #include "trace.h"
 #include "trace-s390.h"
 
-
-static const intercept_handler_t instruction_handlers[256] = {
-       [0x01] = kvm_s390_handle_01,
-       [0x82] = kvm_s390_handle_lpsw,
-       [0x83] = kvm_s390_handle_diag,
-       [0xaa] = kvm_s390_handle_aa,
-       [0xae] = kvm_s390_handle_sigp,
-       [0xb2] = kvm_s390_handle_b2,
-       [0xb6] = kvm_s390_handle_stctl,
-       [0xb7] = kvm_s390_handle_lctl,
-       [0xb9] = kvm_s390_handle_b9,
-       [0xe3] = kvm_s390_handle_e3,
-       [0xe5] = kvm_s390_handle_e5,
-       [0xeb] = kvm_s390_handle_eb,
-};
-
 u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
@@ -129,16 +113,39 @@ static int handle_validity(struct kvm_vcpu *vcpu)
 
 static int handle_instruction(struct kvm_vcpu *vcpu)
 {
-       intercept_handler_t handler;
-
        vcpu->stat.exit_instruction++;
        trace_kvm_s390_intercept_instruction(vcpu,
                                             vcpu->arch.sie_block->ipa,
                                             vcpu->arch.sie_block->ipb);
-       handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
-       if (handler)
-               return handler(vcpu);
-       return -EOPNOTSUPP;
+
+       switch (vcpu->arch.sie_block->ipa >> 8) {
+       case 0x01:
+               return kvm_s390_handle_01(vcpu);
+       case 0x82:
+               return kvm_s390_handle_lpsw(vcpu);
+       case 0x83:
+               return kvm_s390_handle_diag(vcpu);
+       case 0xaa:
+               return kvm_s390_handle_aa(vcpu);
+       case 0xae:
+               return kvm_s390_handle_sigp(vcpu);
+       case 0xb2:
+               return kvm_s390_handle_b2(vcpu);
+       case 0xb6:
+               return kvm_s390_handle_stctl(vcpu);
+       case 0xb7:
+               return kvm_s390_handle_lctl(vcpu);
+       case 0xb9:
+               return kvm_s390_handle_b9(vcpu);
+       case 0xe3:
+               return kvm_s390_handle_e3(vcpu);
+       case 0xe5:
+               return kvm_s390_handle_e5(vcpu);
+       case 0xeb:
+               return kvm_s390_handle_eb(vcpu);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static int inject_prog_on_prog_intercept(struct kvm_vcpu *vcpu)
index aabf46f5f883d44d71cddc88b5ef28ec677ff200..b04616b57a94713a24ed19b142adb94b8c96e748 100644 (file)
@@ -169,8 +169,15 @@ static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu)
 
 static int ckc_irq_pending(struct kvm_vcpu *vcpu)
 {
-       if (vcpu->arch.sie_block->ckc >= kvm_s390_get_tod_clock_fast(vcpu->kvm))
+       const u64 now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
+       const u64 ckc = vcpu->arch.sie_block->ckc;
+
+       if (vcpu->arch.sie_block->gcr[0] & 0x0020000000000000ul) {
+               if ((s64)ckc >= (s64)now)
+                       return 0;
+       } else if (ckc >= now) {
                return 0;
+       }
        return ckc_interrupts_enabled(vcpu);
 }
 
@@ -187,12 +194,6 @@ static int cpu_timer_irq_pending(struct kvm_vcpu *vcpu)
        return kvm_s390_get_cpu_timer(vcpu) >> 63;
 }
 
-static inline int is_ioirq(unsigned long irq_type)
-{
-       return ((irq_type >= IRQ_PEND_IO_ISC_7) &&
-               (irq_type <= IRQ_PEND_IO_ISC_0));
-}
-
 static uint64_t isc_to_isc_bits(int isc)
 {
        return (0x80 >> isc) << 24;
@@ -236,10 +237,15 @@ static inline int kvm_s390_gisa_tac_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gis
        return test_and_clear_bit_inv(IPM_BIT_OFFSET + gisc, (unsigned long *) gisa);
 }
 
-static inline unsigned long pending_irqs(struct kvm_vcpu *vcpu)
+static inline unsigned long pending_irqs_no_gisa(struct kvm_vcpu *vcpu)
 {
        return vcpu->kvm->arch.float_int.pending_irqs |
-               vcpu->arch.local_int.pending_irqs |
+               vcpu->arch.local_int.pending_irqs;
+}
+
+static inline unsigned long pending_irqs(struct kvm_vcpu *vcpu)
+{
+       return pending_irqs_no_gisa(vcpu) |
                kvm_s390_gisa_get_ipm(vcpu->kvm->arch.gisa) << IRQ_PEND_IO_ISC_7;
 }
 
@@ -337,7 +343,7 @@ static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
 
 static void set_intercept_indicators_io(struct kvm_vcpu *vcpu)
 {
-       if (!(pending_irqs(vcpu) & IRQ_PEND_IO_MASK))
+       if (!(pending_irqs_no_gisa(vcpu) & IRQ_PEND_IO_MASK))
                return;
        else if (psw_ioint_disabled(vcpu))
                kvm_s390_set_cpuflags(vcpu, CPUSTAT_IO_INT);
@@ -1011,24 +1017,6 @@ out:
        return rc;
 }
 
-typedef int (*deliver_irq_t)(struct kvm_vcpu *vcpu);
-
-static const deliver_irq_t deliver_irq_funcs[] = {
-       [IRQ_PEND_MCHK_EX]        = __deliver_machine_check,
-       [IRQ_PEND_MCHK_REP]       = __deliver_machine_check,
-       [IRQ_PEND_PROG]           = __deliver_prog,
-       [IRQ_PEND_EXT_EMERGENCY]  = __deliver_emergency_signal,
-       [IRQ_PEND_EXT_EXTERNAL]   = __deliver_external_call,
-       [IRQ_PEND_EXT_CLOCK_COMP] = __deliver_ckc,
-       [IRQ_PEND_EXT_CPU_TIMER]  = __deliver_cpu_timer,
-       [IRQ_PEND_RESTART]        = __deliver_restart,
-       [IRQ_PEND_SET_PREFIX]     = __deliver_set_prefix,
-       [IRQ_PEND_PFAULT_INIT]    = __deliver_pfault_init,
-       [IRQ_PEND_EXT_SERVICE]    = __deliver_service,
-       [IRQ_PEND_PFAULT_DONE]    = __deliver_pfault_done,
-       [IRQ_PEND_VIRTIO]         = __deliver_virtio,
-};
-
 /* Check whether an external call is pending (deliverable or not) */
 int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)
 {
@@ -1066,13 +1054,19 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 
 static u64 __calculate_sltime(struct kvm_vcpu *vcpu)
 {
-       u64 now, cputm, sltime = 0;
+       const u64 now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
+       const u64 ckc = vcpu->arch.sie_block->ckc;
+       u64 cputm, sltime = 0;
 
        if (ckc_interrupts_enabled(vcpu)) {
-               now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
-               sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
-               /* already expired or overflow? */
-               if (!sltime || vcpu->arch.sie_block->ckc <= now)
+               if (vcpu->arch.sie_block->gcr[0] & 0x0020000000000000ul) {
+                       if ((s64)now < (s64)ckc)
+                               sltime = tod_to_ns((s64)ckc - (s64)now);
+               } else if (now < ckc) {
+                       sltime = tod_to_ns(ckc - now);
+               }
+               /* already expired */
+               if (!sltime)
                        return 0;
                if (cpu_timer_interrupts_enabled(vcpu)) {
                        cputm = kvm_s390_get_cpu_timer(vcpu);
@@ -1192,7 +1186,6 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
 int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
-       deliver_irq_t func;
        int rc = 0;
        unsigned long irq_type;
        unsigned long irqs;
@@ -1212,16 +1205,57 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
        while ((irqs = deliverable_irqs(vcpu)) && !rc) {
                /* bits are in the reverse order of interrupt priority */
                irq_type = find_last_bit(&irqs, IRQ_PEND_COUNT);
-               if (is_ioirq(irq_type)) {
+               switch (irq_type) {
+               case IRQ_PEND_IO_ISC_0:
+               case IRQ_PEND_IO_ISC_1:
+               case IRQ_PEND_IO_ISC_2:
+               case IRQ_PEND_IO_ISC_3:
+               case IRQ_PEND_IO_ISC_4:
+               case IRQ_PEND_IO_ISC_5:
+               case IRQ_PEND_IO_ISC_6:
+               case IRQ_PEND_IO_ISC_7:
                        rc = __deliver_io(vcpu, irq_type);
-               } else {
-                       func = deliver_irq_funcs[irq_type];
-                       if (!func) {
-                               WARN_ON_ONCE(func == NULL);
-                               clear_bit(irq_type, &li->pending_irqs);
-                               continue;
-                       }
-                       rc = func(vcpu);
+                       break;
+               case IRQ_PEND_MCHK_EX:
+               case IRQ_PEND_MCHK_REP:
+                       rc = __deliver_machine_check(vcpu);
+                       break;
+               case IRQ_PEND_PROG:
+                       rc = __deliver_prog(vcpu);
+                       break;
+               case IRQ_PEND_EXT_EMERGENCY:
+                       rc = __deliver_emergency_signal(vcpu);
+                       break;
+               case IRQ_PEND_EXT_EXTERNAL:
+                       rc = __deliver_external_call(vcpu);
+                       break;
+               case IRQ_PEND_EXT_CLOCK_COMP:
+                       rc = __deliver_ckc(vcpu);
+                       break;
+               case IRQ_PEND_EXT_CPU_TIMER:
+                       rc = __deliver_cpu_timer(vcpu);
+                       break;
+               case IRQ_PEND_RESTART:
+                       rc = __deliver_restart(vcpu);
+                       break;
+               case IRQ_PEND_SET_PREFIX:
+                       rc = __deliver_set_prefix(vcpu);
+                       break;
+               case IRQ_PEND_PFAULT_INIT:
+                       rc = __deliver_pfault_init(vcpu);
+                       break;
+               case IRQ_PEND_EXT_SERVICE:
+                       rc = __deliver_service(vcpu);
+                       break;
+               case IRQ_PEND_PFAULT_DONE:
+                       rc = __deliver_pfault_done(vcpu);
+                       break;
+               case IRQ_PEND_VIRTIO:
+                       rc = __deliver_virtio(vcpu);
+                       break;
+               default:
+                       WARN_ONCE(1, "Unknown pending irq type %ld", irq_type);
+                       clear_bit(irq_type, &li->pending_irqs);
                }
        }
 
@@ -1701,7 +1735,8 @@ static void __floating_irq_kick(struct kvm *kvm, u64 type)
                kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_STOP_INT);
                break;
        case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-               kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
+               if (!(type & KVM_S390_INT_IO_AI_MASK && kvm->arch.gisa))
+                       kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
                break;
        default:
                kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_EXT_INT);
index ba4c7092335ad254fe0d385b99aa231dbecd2d53..77d7818130db49cb0108acf68a3d737e064cb918 100644 (file)
@@ -179,6 +179,28 @@ int kvm_arch_hardware_enable(void)
 static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
                              unsigned long end);
 
+static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
+{
+       u8 delta_idx = 0;
+
+       /*
+        * The TOD jumps by delta, we have to compensate this by adding
+        * -delta to the epoch.
+        */
+       delta = -delta;
+
+       /* sign-extension - we're adding to signed values below */
+       if ((s64)delta < 0)
+               delta_idx = -1;
+
+       scb->epoch += delta;
+       if (scb->ecd & ECD_MEF) {
+               scb->epdx += delta_idx;
+               if (scb->epoch < delta)
+                       scb->epdx += 1;
+       }
+}
+
 /*
  * This callback is executed during stop_machine(). All CPUs are therefore
  * temporarily stopped. In order not to change guest behavior, we have to
@@ -194,13 +216,17 @@ static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
        unsigned long long *delta = v;
 
        list_for_each_entry(kvm, &vm_list, vm_list) {
-               kvm->arch.epoch -= *delta;
                kvm_for_each_vcpu(i, vcpu, kvm) {
-                       vcpu->arch.sie_block->epoch -= *delta;
+                       kvm_clock_sync_scb(vcpu->arch.sie_block, *delta);
+                       if (i == 0) {
+                               kvm->arch.epoch = vcpu->arch.sie_block->epoch;
+                               kvm->arch.epdx = vcpu->arch.sie_block->epdx;
+                       }
                        if (vcpu->arch.cputm_enabled)
                                vcpu->arch.cputm_start += *delta;
                        if (vcpu->arch.vsie_block)
-                               vcpu->arch.vsie_block->epoch -= *delta;
+                               kvm_clock_sync_scb(vcpu->arch.vsie_block,
+                                                  *delta);
                }
        }
        return NOTIFY_OK;
@@ -902,12 +928,9 @@ static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
        if (copy_from_user(&gtod, (void __user *)attr->addr, sizeof(gtod)))
                return -EFAULT;
 
-       if (test_kvm_facility(kvm, 139))
-               kvm_s390_set_tod_clock_ext(kvm, &gtod);
-       else if (gtod.epoch_idx == 0)
-               kvm_s390_set_tod_clock(kvm, gtod.tod);
-       else
+       if (!test_kvm_facility(kvm, 139) && gtod.epoch_idx)
                return -EINVAL;
+       kvm_s390_set_tod_clock(kvm, &gtod);
 
        VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx",
                gtod.epoch_idx, gtod.tod);
@@ -932,13 +955,14 @@ static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
 
 static int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
 {
-       u64 gtod;
+       struct kvm_s390_vm_tod_clock gtod = { 0 };
 
-       if (copy_from_user(&gtod, (void __user *)attr->addr, sizeof(gtod)))
+       if (copy_from_user(&gtod.tod, (void __user *)attr->addr,
+                          sizeof(gtod.tod)))
                return -EFAULT;
 
-       kvm_s390_set_tod_clock(kvm, gtod);
-       VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod);
+       kvm_s390_set_tod_clock(kvm, &gtod);
+       VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod.tod);
        return 0;
 }
 
@@ -2389,6 +2413,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
        mutex_lock(&vcpu->kvm->lock);
        preempt_disable();
        vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
+       vcpu->arch.sie_block->epdx = vcpu->kvm->arch.epdx;
        preempt_enable();
        mutex_unlock(&vcpu->kvm->lock);
        if (!kvm_is_ucontrol(vcpu->kvm)) {
@@ -3021,8 +3046,8 @@ retry:
        return 0;
 }
 
-void kvm_s390_set_tod_clock_ext(struct kvm *kvm,
-                                const struct kvm_s390_vm_tod_clock *gtod)
+void kvm_s390_set_tod_clock(struct kvm *kvm,
+                           const struct kvm_s390_vm_tod_clock *gtod)
 {
        struct kvm_vcpu *vcpu;
        struct kvm_s390_tod_clock_ext htod;
@@ -3034,10 +3059,12 @@ void kvm_s390_set_tod_clock_ext(struct kvm *kvm,
        get_tod_clock_ext((char *)&htod);
 
        kvm->arch.epoch = gtod->tod - htod.tod;
-       kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx;
-
-       if (kvm->arch.epoch > gtod->tod)
-               kvm->arch.epdx -= 1;
+       kvm->arch.epdx = 0;
+       if (test_kvm_facility(kvm, 139)) {
+               kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx;
+               if (kvm->arch.epoch > gtod->tod)
+                       kvm->arch.epdx -= 1;
+       }
 
        kvm_s390_vcpu_block_all(kvm);
        kvm_for_each_vcpu(i, vcpu, kvm) {
@@ -3050,22 +3077,6 @@ void kvm_s390_set_tod_clock_ext(struct kvm *kvm,
        mutex_unlock(&kvm->lock);
 }
 
-void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod)
-{
-       struct kvm_vcpu *vcpu;
-       int i;
-
-       mutex_lock(&kvm->lock);
-       preempt_disable();
-       kvm->arch.epoch = tod - get_tod_clock();
-       kvm_s390_vcpu_block_all(kvm);
-       kvm_for_each_vcpu(i, vcpu, kvm)
-               vcpu->arch.sie_block->epoch = kvm->arch.epoch;
-       kvm_s390_vcpu_unblock_all(kvm);
-       preempt_enable();
-       mutex_unlock(&kvm->lock);
-}
-
 /**
  * kvm_arch_fault_in_page - fault-in guest page if necessary
  * @vcpu: The corresponding virtual cpu
index bd31b37b0e6f83905e7204b2eb439050aaeb1187..f55ac0ef99ea70bf3fb1d8f7eb7e303eb405b2b4 100644 (file)
@@ -19,8 +19,6 @@
 #include <asm/processor.h>
 #include <asm/sclp.h>
 
-typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
-
 /* Transactional Memory Execution related macros */
 #define IS_TE_ENABLED(vcpu)    ((vcpu->arch.sie_block->ecb & ECB_TE))
 #define TDB_FORMAT1            1
@@ -283,9 +281,8 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
 int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
 
 /* implemented in kvm-s390.c */
-void kvm_s390_set_tod_clock_ext(struct kvm *kvm,
-                                const struct kvm_s390_vm_tod_clock *gtod);
-void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod);
+void kvm_s390_set_tod_clock(struct kvm *kvm,
+                           const struct kvm_s390_vm_tod_clock *gtod);
 long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
 int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
 int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr);
index c4c4e157c03631a1d745ccafdfec111a6a08a49e..f0b4185158afcb229cac5b06f23f5664afffebec 100644 (file)
@@ -85,9 +85,10 @@ int kvm_s390_handle_e3(struct kvm_vcpu *vcpu)
 /* Handle SCK (SET CLOCK) interception */
 static int handle_set_clock(struct kvm_vcpu *vcpu)
 {
+       struct kvm_s390_vm_tod_clock gtod = { 0 };
        int rc;
        u8 ar;
-       u64 op2, val;
+       u64 op2;
 
        vcpu->stat.instruction_sck++;
 
@@ -97,12 +98,12 @@ static int handle_set_clock(struct kvm_vcpu *vcpu)
        op2 = kvm_s390_get_base_disp_s(vcpu, &ar);
        if (op2 & 7)    /* Operand must be on a doubleword boundary */
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
-       rc = read_guest(vcpu, op2, ar, &val, sizeof(val));
+       rc = read_guest(vcpu, op2, ar, &gtod.tod, sizeof(gtod.tod));
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
-       VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", val);
-       kvm_s390_set_tod_clock(vcpu->kvm, val);
+       VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", gtod.tod);
+       kvm_s390_set_tod_clock(vcpu->kvm, &gtod);
 
        kvm_s390_set_psw_cc(vcpu, 0);
        return 0;
@@ -795,55 +796,60 @@ out:
        return rc;
 }
 
-static const intercept_handler_t b2_handlers[256] = {
-       [0x02] = handle_stidp,
-       [0x04] = handle_set_clock,
-       [0x10] = handle_set_prefix,
-       [0x11] = handle_store_prefix,
-       [0x12] = handle_store_cpu_address,
-       [0x14] = kvm_s390_handle_vsie,
-       [0x21] = handle_ipte_interlock,
-       [0x29] = handle_iske,
-       [0x2a] = handle_rrbe,
-       [0x2b] = handle_sske,
-       [0x2c] = handle_test_block,
-       [0x30] = handle_io_inst,
-       [0x31] = handle_io_inst,
-       [0x32] = handle_io_inst,
-       [0x33] = handle_io_inst,
-       [0x34] = handle_io_inst,
-       [0x35] = handle_io_inst,
-       [0x36] = handle_io_inst,
-       [0x37] = handle_io_inst,
-       [0x38] = handle_io_inst,
-       [0x39] = handle_io_inst,
-       [0x3a] = handle_io_inst,
-       [0x3b] = handle_io_inst,
-       [0x3c] = handle_io_inst,
-       [0x50] = handle_ipte_interlock,
-       [0x56] = handle_sthyi,
-       [0x5f] = handle_io_inst,
-       [0x74] = handle_io_inst,
-       [0x76] = handle_io_inst,
-       [0x7d] = handle_stsi,
-       [0xb1] = handle_stfl,
-       [0xb2] = handle_lpswe,
-};
-
 int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
 {
-       intercept_handler_t handler;
-
-       /*
-        * A lot of B2 instructions are priviledged. Here we check for
-        * the privileged ones, that we can handle in the kernel.
-        * Anything else goes to userspace.
-        */
-       handler = b2_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
-       if (handler)
-               return handler(vcpu);
-
-       return -EOPNOTSUPP;
+       switch (vcpu->arch.sie_block->ipa & 0x00ff) {
+       case 0x02:
+               return handle_stidp(vcpu);
+       case 0x04:
+               return handle_set_clock(vcpu);
+       case 0x10:
+               return handle_set_prefix(vcpu);
+       case 0x11:
+               return handle_store_prefix(vcpu);
+       case 0x12:
+               return handle_store_cpu_address(vcpu);
+       case 0x14:
+               return kvm_s390_handle_vsie(vcpu);
+       case 0x21:
+       case 0x50:
+               return handle_ipte_interlock(vcpu);
+       case 0x29:
+               return handle_iske(vcpu);
+       case 0x2a:
+               return handle_rrbe(vcpu);
+       case 0x2b:
+               return handle_sske(vcpu);
+       case 0x2c:
+               return handle_test_block(vcpu);
+       case 0x30:
+       case 0x31:
+       case 0x32:
+       case 0x33:
+       case 0x34:
+       case 0x35:
+       case 0x36:
+       case 0x37:
+       case 0x38:
+       case 0x39:
+       case 0x3a:
+       case 0x3b:
+       case 0x3c:
+       case 0x5f:
+       case 0x74:
+       case 0x76:
+               return handle_io_inst(vcpu);
+       case 0x56:
+               return handle_sthyi(vcpu);
+       case 0x7d:
+               return handle_stsi(vcpu);
+       case 0xb1:
+               return handle_stfl(vcpu);
+       case 0xb2:
+               return handle_lpswe(vcpu);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static int handle_epsw(struct kvm_vcpu *vcpu)
@@ -1105,25 +1111,22 @@ static int handle_essa(struct kvm_vcpu *vcpu)
        return 0;
 }
 
-static const intercept_handler_t b9_handlers[256] = {
-       [0x8a] = handle_ipte_interlock,
-       [0x8d] = handle_epsw,
-       [0x8e] = handle_ipte_interlock,
-       [0x8f] = handle_ipte_interlock,
-       [0xab] = handle_essa,
-       [0xaf] = handle_pfmf,
-};
-
 int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)
 {
-       intercept_handler_t handler;
-
-       /* This is handled just as for the B2 instructions. */
-       handler = b9_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
-       if (handler)
-               return handler(vcpu);
-
-       return -EOPNOTSUPP;
+       switch (vcpu->arch.sie_block->ipa & 0x00ff) {
+       case 0x8a:
+       case 0x8e:
+       case 0x8f:
+               return handle_ipte_interlock(vcpu);
+       case 0x8d:
+               return handle_epsw(vcpu);
+       case 0xab:
+               return handle_essa(vcpu);
+       case 0xaf:
+               return handle_pfmf(vcpu);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
@@ -1271,22 +1274,20 @@ static int handle_stctg(struct kvm_vcpu *vcpu)
        return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
 }
 
-static const intercept_handler_t eb_handlers[256] = {
-       [0x2f] = handle_lctlg,
-       [0x25] = handle_stctg,
-       [0x60] = handle_ri,
-       [0x61] = handle_ri,
-       [0x62] = handle_ri,
-};
-
 int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
 {
-       intercept_handler_t handler;
-
-       handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff];
-       if (handler)
-               return handler(vcpu);
-       return -EOPNOTSUPP;
+       switch (vcpu->arch.sie_block->ipb & 0x000000ff) {
+       case 0x25:
+               return handle_stctg(vcpu);
+       case 0x2f:
+               return handle_lctlg(vcpu);
+       case 0x60:
+       case 0x61:
+       case 0x62:
+               return handle_ri(vcpu);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static int handle_tprot(struct kvm_vcpu *vcpu)
@@ -1346,10 +1347,12 @@ out_unlock:
 
 int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
 {
-       /* For e5xx... instructions we only handle TPROT */
-       if ((vcpu->arch.sie_block->ipa & 0x00ff) == 0x01)
+       switch (vcpu->arch.sie_block->ipa & 0x00ff) {
+       case 0x01:
                return handle_tprot(vcpu);
-       return -EOPNOTSUPP;
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static int handle_sckpf(struct kvm_vcpu *vcpu)
@@ -1380,17 +1383,14 @@ static int handle_ptff(struct kvm_vcpu *vcpu)
        return 0;
 }
 
-static const intercept_handler_t x01_handlers[256] = {
-       [0x04] = handle_ptff,
-       [0x07] = handle_sckpf,
-};
-
 int kvm_s390_handle_01(struct kvm_vcpu *vcpu)
 {
-       intercept_handler_t handler;
-
-       handler = x01_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
-       if (handler)
-               return handler(vcpu);
-       return -EOPNOTSUPP;
+       switch (vcpu->arch.sie_block->ipa & 0x00ff) {
+       case 0x04:
+               return handle_ptff(vcpu);
+       case 0x07:
+               return handle_sckpf(vcpu);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
index ec772700ff9659350543534272a92eb531bbd181..8961e3970901d4b06c87b20f147115b683ad5170 100644 (file)
@@ -821,6 +821,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
 {
        struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
        struct kvm_s390_sie_block *scb_o = vsie_page->scb_o;
+       int guest_bp_isolation;
        int rc;
 
        handle_last_fault(vcpu, vsie_page);
@@ -831,6 +832,20 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                s390_handle_mcck();
 
        srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+
+       /* save current guest state of bp isolation override */
+       guest_bp_isolation = test_thread_flag(TIF_ISOLATE_BP_GUEST);
+
+       /*
+        * The guest is running with BPBC, so we have to force it on for our
+        * nested guest. This is done by enabling BPBC globally, so the BPBC
+        * control in the SCB (which the nested guest can modify) is simply
+        * ignored.
+        */
+       if (test_kvm_facility(vcpu->kvm, 82) &&
+           vcpu->arch.sie_block->fpf & FPF_BPBC)
+               set_thread_flag(TIF_ISOLATE_BP_GUEST);
+
        local_irq_disable();
        guest_enter_irqoff();
        local_irq_enable();
@@ -840,6 +855,11 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        local_irq_disable();
        guest_exit_irqoff();
        local_irq_enable();
+
+       /* restore guest state for bp isolation override */
+       if (!guest_bp_isolation)
+               clear_thread_flag(TIF_ISOLATE_BP_GUEST);
+
        vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 
        if (rc == -EINTR) {
index c1236b187824e222a2c7fddd417272369767b06b..eb7f43f235211257bca63e83ad0e33d9fa4d7ba3 100644 (file)
@@ -430,6 +430,7 @@ config GOLDFISH
 config RETPOLINE
        bool "Avoid speculative indirect branches in kernel"
        default y
+       select STACK_VALIDATION if HAVE_STACK_VALIDATION
        help
          Compile kernel with the retpoline compiler options to guard against
          kernel-to-user data leaks by avoiding speculative indirect
index fad55160dcb94a28e60d537d3d69d471a1e10e2e..498c1b8123006add6ad685a1fea6239208509810 100644 (file)
@@ -232,10 +232,9 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 
 # Avoid indirect branches in kernel to deal with Spectre
 ifdef CONFIG_RETPOLINE
-    RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register)
-    ifneq ($(RETPOLINE_CFLAGS),)
-        KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE
-    endif
+ifneq ($(RETPOLINE_CFLAGS),)
+  KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE
+endif
 endif
 
 archscripts: scripts_basic
index dce7092ab24a247c1165f80b17c687d255023a05..be63330c551129cb6bf0fcf07d8bf6d4600cb098 100644 (file)
@@ -97,7 +97,7 @@ For 32-bit we have the following conventions - kernel is built with
 
 #define SIZEOF_PTREGS  21*8
 
-.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax
+.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
        /*
         * Push registers and sanitize registers of values that a
         * speculation attack might otherwise want to exploit. The
@@ -105,32 +105,41 @@ For 32-bit we have the following conventions - kernel is built with
         * could be put to use in a speculative execution gadget.
         * Interleave XOR with PUSH for better uop scheduling:
         */
+       .if \save_ret
+       pushq   %rsi            /* pt_regs->si */
+       movq    8(%rsp), %rsi   /* temporarily store the return address in %rsi */
+       movq    %rdi, 8(%rsp)   /* pt_regs->di (overwriting original return address) */
+       .else
        pushq   %rdi            /* pt_regs->di */
        pushq   %rsi            /* pt_regs->si */
+       .endif
        pushq   \rdx            /* pt_regs->dx */
        pushq   %rcx            /* pt_regs->cx */
        pushq   \rax            /* pt_regs->ax */
        pushq   %r8             /* pt_regs->r8 */
-       xorq    %r8, %r8        /* nospec   r8 */
+       xorl    %r8d, %r8d      /* nospec   r8 */
        pushq   %r9             /* pt_regs->r9 */
-       xorq    %r9, %r9        /* nospec   r9 */
+       xorl    %r9d, %r9d      /* nospec   r9 */
        pushq   %r10            /* pt_regs->r10 */
-       xorq    %r10, %r10      /* nospec   r10 */
+       xorl    %r10d, %r10d    /* nospec   r10 */
        pushq   %r11            /* pt_regs->r11 */
-       xorq    %r11, %r11      /* nospec   r11*/
+       xorl    %r11d, %r11d    /* nospec   r11*/
        pushq   %rbx            /* pt_regs->rbx */
        xorl    %ebx, %ebx      /* nospec   rbx*/
        pushq   %rbp            /* pt_regs->rbp */
        xorl    %ebp, %ebp      /* nospec   rbp*/
        pushq   %r12            /* pt_regs->r12 */
-       xorq    %r12, %r12      /* nospec   r12*/
+       xorl    %r12d, %r12d    /* nospec   r12*/
        pushq   %r13            /* pt_regs->r13 */
-       xorq    %r13, %r13      /* nospec   r13*/
+       xorl    %r13d, %r13d    /* nospec   r13*/
        pushq   %r14            /* pt_regs->r14 */
-       xorq    %r14, %r14      /* nospec   r14*/
+       xorl    %r14d, %r14d    /* nospec   r14*/
        pushq   %r15            /* pt_regs->r15 */
-       xorq    %r15, %r15      /* nospec   r15*/
+       xorl    %r15d, %r15d    /* nospec   r15*/
        UNWIND_HINT_REGS
+       .if \save_ret
+       pushq   %rsi            /* return address on top of stack */
+       .endif
 .endm
 
 .macro POP_REGS pop_rdi=1 skip_r11rcx=0
@@ -172,12 +181,7 @@ For 32-bit we have the following conventions - kernel is built with
  */
 .macro ENCODE_FRAME_POINTER ptregs_offset=0
 #ifdef CONFIG_FRAME_POINTER
-       .if \ptregs_offset
-               leaq \ptregs_offset(%rsp), %rbp
-       .else
-               mov %rsp, %rbp
-       .endif
-       orq     $0x1, %rbp
+       leaq 1+\ptregs_offset(%rsp), %rbp
 #endif
 .endm
 
index 16c2c022540d42b9fc51ee7489383775bd319ac1..6ad064c8cf35e6fdfc9c384212a6f76c780ffd69 100644 (file)
@@ -252,8 +252,7 @@ ENTRY(__switch_to_asm)
         * exist, overwrite the RSB with entries which capture
         * speculative execution to prevent attack.
         */
-       /* Clobbers %ebx */
-       FILL_RETURN_BUFFER RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
+       FILL_RETURN_BUFFER %ebx, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
 #endif
 
        /* restore callee-saved registers */
index 8971bd64d515c5bb4a9b95108fd802b8418764f2..d5c7f18f79aceabf2f7c43769255cd38b3142bc3 100644 (file)
@@ -364,8 +364,7 @@ ENTRY(__switch_to_asm)
         * exist, overwrite the RSB with entries which capture
         * speculative execution to prevent attack.
         */
-       /* Clobbers %rbx */
-       FILL_RETURN_BUFFER RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
+       FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
 #endif
 
        /* restore callee-saved registers */
@@ -449,9 +448,19 @@ END(irq_entries_start)
  *
  * The invariant is that, if irq_count != -1, then the IRQ stack is in use.
  */
-.macro ENTER_IRQ_STACK regs=1 old_rsp
+.macro ENTER_IRQ_STACK regs=1 old_rsp save_ret=0
        DEBUG_ENTRY_ASSERT_IRQS_OFF
+
+       .if \save_ret
+       /*
+        * If save_ret is set, the original stack contains one additional
+        * entry -- the return address. Therefore, move the address one
+        * entry below %rsp to \old_rsp.
+        */
+       leaq    8(%rsp), \old_rsp
+       .else
        movq    %rsp, \old_rsp
+       .endif
 
        .if \regs
        UNWIND_HINT_REGS base=\old_rsp
@@ -497,6 +506,15 @@ END(irq_entries_start)
        .if \regs
        UNWIND_HINT_REGS indirect=1
        .endif
+
+       .if \save_ret
+       /*
+        * Push the return address to the stack. This return address can
+        * be found at the "real" original RSP, which was offset by 8 at
+        * the beginning of this macro.
+        */
+       pushq   -8(\old_rsp)
+       .endif
 .endm
 
 /*
@@ -520,27 +538,65 @@ END(irq_entries_start)
 .endm
 
 /*
- * Interrupt entry/exit.
- *
- * Interrupt entry points save only callee clobbered registers in fast path.
+ * Interrupt entry helper function.
  *
- * Entry runs with interrupts off.
+ * Entry runs with interrupts off. Stack layout at entry:
+ * +----------------------------------------------------+
+ * | regs->ss                                          |
+ * | regs->rsp                                         |
+ * | regs->eflags                                      |
+ * | regs->cs                                          |
+ * | regs->ip                                          |
+ * +----------------------------------------------------+
+ * | regs->orig_ax = ~(interrupt number)               |
+ * +----------------------------------------------------+
+ * | return address                                    |
+ * +----------------------------------------------------+
  */
-
-/* 0(%rsp): ~(interrupt number) */
-       .macro interrupt func
+ENTRY(interrupt_entry)
+       UNWIND_HINT_FUNC
+       ASM_CLAC
        cld
 
-       testb   $3, CS-ORIG_RAX(%rsp)
+       testb   $3, CS-ORIG_RAX+8(%rsp)
        jz      1f
        SWAPGS
-       call    switch_to_thread_stack
+
+       /*
+        * Switch to the thread stack. The IRET frame and orig_ax are
+        * on the stack, as well as the return address. RDI..R12 are
+        * not (yet) on the stack and space has not (yet) been
+        * allocated for them.
+        */
+       pushq   %rdi
+
+       /* Need to switch before accessing the thread stack. */
+       SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
+       movq    %rsp, %rdi
+       movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
+
+        /*
+         * We have RDI, return address, and orig_ax on the stack on
+         * top of the IRET frame. That means offset=24
+         */
+       UNWIND_HINT_IRET_REGS base=%rdi offset=24
+
+       pushq   7*8(%rdi)               /* regs->ss */
+       pushq   6*8(%rdi)               /* regs->rsp */
+       pushq   5*8(%rdi)               /* regs->eflags */
+       pushq   4*8(%rdi)               /* regs->cs */
+       pushq   3*8(%rdi)               /* regs->ip */
+       pushq   2*8(%rdi)               /* regs->orig_ax */
+       pushq   8(%rdi)                 /* return address */
+       UNWIND_HINT_FUNC
+
+       movq    (%rdi), %rdi
 1:
 
-       PUSH_AND_CLEAR_REGS
-       ENCODE_FRAME_POINTER
+       PUSH_AND_CLEAR_REGS save_ret=1
+       ENCODE_FRAME_POINTER 8
 
-       testb   $3, CS(%rsp)
+       testb   $3, CS+8(%rsp)
        jz      1f
 
        /*
@@ -548,7 +604,7 @@ END(irq_entries_start)
         *
         * We need to tell lockdep that IRQs are off.  We can't do this until
         * we fix gsbase, and we should do it before enter_from_user_mode
-        * (which can take locks).  Since TRACE_IRQS_OFF idempotent,
+        * (which can take locks).  Since TRACE_IRQS_OFF is idempotent,
         * the simplest way to handle it is to just call it twice if
         * we enter from user mode.  There's no reason to optimize this since
         * TRACE_IRQS_OFF is a no-op if lockdep is off.
@@ -558,12 +614,15 @@ END(irq_entries_start)
        CALL_enter_from_user_mode
 
 1:
-       ENTER_IRQ_STACK old_rsp=%rdi
+       ENTER_IRQ_STACK old_rsp=%rdi save_ret=1
        /* We entered an interrupt context - irqs are off: */
        TRACE_IRQS_OFF
 
-       call    \func   /* rdi points to pt_regs */
-       .endm
+       ret
+END(interrupt_entry)
+
+
+/* Interrupt entry/exit. */
 
        /*
         * The interrupt stubs push (~vector+0x80) onto the stack and
@@ -571,9 +630,10 @@ END(irq_entries_start)
         */
        .p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
-       ASM_CLAC
        addq    $-0x80, (%rsp)                  /* Adjust vector to [-256, -1] range */
-       interrupt do_IRQ
+       call    interrupt_entry
+       UNWIND_HINT_REGS indirect=1
+       call    do_IRQ  /* rdi points to pt_regs */
        /* 0(%rsp): old RSP */
 ret_from_intr:
        DISABLE_INTERRUPTS(CLBR_ANY)
@@ -766,10 +826,11 @@ END(common_interrupt)
 .macro apicinterrupt3 num sym do_sym
 ENTRY(\sym)
        UNWIND_HINT_IRET_REGS
-       ASM_CLAC
        pushq   $~(\num)
 .Lcommon_\sym:
-       interrupt \do_sym
+       call    interrupt_entry
+       UNWIND_HINT_REGS indirect=1
+       call    \do_sym /* rdi points to pt_regs */
        jmp     ret_from_intr
 END(\sym)
 .endm
@@ -832,34 +893,6 @@ apicinterrupt IRQ_WORK_VECTOR                      irq_work_interrupt              smp_irq_work_interrupt
  */
 #define CPU_TSS_IST(x) PER_CPU_VAR(cpu_tss_rw) + (TSS_ist + ((x) - 1) * 8)
 
-/*
- * Switch to the thread stack.  This is called with the IRET frame and
- * orig_ax on the stack.  (That is, RDI..R12 are not on the stack and
- * space has not been allocated for them.)
- */
-ENTRY(switch_to_thread_stack)
-       UNWIND_HINT_FUNC
-
-       pushq   %rdi
-       /* Need to switch before accessing the thread stack. */
-       SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
-       movq    %rsp, %rdi
-       movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
-       UNWIND_HINT sp_offset=16 sp_reg=ORC_REG_DI
-
-       pushq   7*8(%rdi)               /* regs->ss */
-       pushq   6*8(%rdi)               /* regs->rsp */
-       pushq   5*8(%rdi)               /* regs->eflags */
-       pushq   4*8(%rdi)               /* regs->cs */
-       pushq   3*8(%rdi)               /* regs->ip */
-       pushq   2*8(%rdi)               /* regs->orig_ax */
-       pushq   8(%rdi)                 /* return address */
-       UNWIND_HINT_FUNC
-
-       movq    (%rdi), %rdi
-       ret
-END(switch_to_thread_stack)
-
 .macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1
 ENTRY(\sym)
        UNWIND_HINT_IRET_REGS offset=\has_error_code*8
@@ -875,12 +908,8 @@ ENTRY(\sym)
        pushq   $-1                             /* ORIG_RAX: no syscall to restart */
        .endif
 
-       /* Save all registers in pt_regs */
-       PUSH_AND_CLEAR_REGS
-       ENCODE_FRAME_POINTER
-
        .if \paranoid < 2
-       testb   $3, CS(%rsp)                    /* If coming from userspace, switch stacks */
+       testb   $3, CS-ORIG_RAX(%rsp)           /* If coming from userspace, switch stacks */
        jnz     .Lfrom_usermode_switch_stack_\@
        .endif
 
@@ -1130,13 +1159,15 @@ idtentry machine_check          do_mce                  has_error_code=0        paranoid=1
 #endif
 
 /*
- * Switch gs if needed.
+ * Save all registers in pt_regs, and switch gs if needed.
  * Use slow, but surefire "are we in kernel?" check.
  * Return: ebx=0: need swapgs on exit, ebx=1: otherwise
  */
 ENTRY(paranoid_entry)
        UNWIND_HINT_FUNC
        cld
+       PUSH_AND_CLEAR_REGS save_ret=1
+       ENCODE_FRAME_POINTER 8
        movl    $1, %ebx
        movl    $MSR_GS_BASE, %ecx
        rdmsr
@@ -1181,12 +1212,14 @@ ENTRY(paranoid_exit)
 END(paranoid_exit)
 
 /*
- * Switch gs if needed.
+ * Save all registers in pt_regs, and switch GS if needed.
  * Return: EBX=0: came from user mode; EBX=1: otherwise
  */
 ENTRY(error_entry)
-       UNWIND_HINT_REGS offset=8
+       UNWIND_HINT_FUNC
        cld
+       PUSH_AND_CLEAR_REGS save_ret=1
+       ENCODE_FRAME_POINTER 8
        testb   $3, CS+8(%rsp)
        jz      .Lerror_kernelspace
 
@@ -1577,8 +1610,6 @@ end_repeat_nmi:
         * frame to point back to repeat_nmi.
         */
        pushq   $-1                             /* ORIG_RAX: no syscall to restart */
-       PUSH_AND_CLEAR_REGS
-       ENCODE_FRAME_POINTER
 
        /*
         * Use paranoid_entry to handle SWAPGS, but no need to use paranoid_exit
index fd65e016e4133f5634545062d098fc25fb5c0b1d..e811dd9c5e99e1a1e61d20cce0fb9ba3cf23f535 100644 (file)
@@ -85,25 +85,25 @@ ENTRY(entry_SYSENTER_compat)
        pushq   %rcx                    /* pt_regs->cx */
        pushq   $-ENOSYS                /* pt_regs->ax */
        pushq   $0                      /* pt_regs->r8  = 0 */
-       xorq    %r8, %r8                /* nospec   r8 */
+       xorl    %r8d, %r8d              /* nospec   r8 */
        pushq   $0                      /* pt_regs->r9  = 0 */
-       xorq    %r9, %r9                /* nospec   r9 */
+       xorl    %r9d, %r9d              /* nospec   r9 */
        pushq   $0                      /* pt_regs->r10 = 0 */
-       xorq    %r10, %r10              /* nospec   r10 */
+       xorl    %r10d, %r10d            /* nospec   r10 */
        pushq   $0                      /* pt_regs->r11 = 0 */
-       xorq    %r11, %r11              /* nospec   r11 */
+       xorl    %r11d, %r11d            /* nospec   r11 */
        pushq   %rbx                    /* pt_regs->rbx */
        xorl    %ebx, %ebx              /* nospec   rbx */
        pushq   %rbp                    /* pt_regs->rbp (will be overwritten) */
        xorl    %ebp, %ebp              /* nospec   rbp */
        pushq   $0                      /* pt_regs->r12 = 0 */
-       xorq    %r12, %r12              /* nospec   r12 */
+       xorl    %r12d, %r12d            /* nospec   r12 */
        pushq   $0                      /* pt_regs->r13 = 0 */
-       xorq    %r13, %r13              /* nospec   r13 */
+       xorl    %r13d, %r13d            /* nospec   r13 */
        pushq   $0                      /* pt_regs->r14 = 0 */
-       xorq    %r14, %r14              /* nospec   r14 */
+       xorl    %r14d, %r14d            /* nospec   r14 */
        pushq   $0                      /* pt_regs->r15 = 0 */
-       xorq    %r15, %r15              /* nospec   r15 */
+       xorl    %r15d, %r15d            /* nospec   r15 */
        cld
 
        /*
@@ -224,25 +224,25 @@ GLOBAL(entry_SYSCALL_compat_after_hwframe)
        pushq   %rbp                    /* pt_regs->cx (stashed in bp) */
        pushq   $-ENOSYS                /* pt_regs->ax */
        pushq   $0                      /* pt_regs->r8  = 0 */
-       xorq    %r8, %r8                /* nospec   r8 */
+       xorl    %r8d, %r8d              /* nospec   r8 */
        pushq   $0                      /* pt_regs->r9  = 0 */
-       xorq    %r9, %r9                /* nospec   r9 */
+       xorl    %r9d, %r9d              /* nospec   r9 */
        pushq   $0                      /* pt_regs->r10 = 0 */
-       xorq    %r10, %r10              /* nospec   r10 */
+       xorl    %r10d, %r10d            /* nospec   r10 */
        pushq   $0                      /* pt_regs->r11 = 0 */
-       xorq    %r11, %r11              /* nospec   r11 */
+       xorl    %r11d, %r11d            /* nospec   r11 */
        pushq   %rbx                    /* pt_regs->rbx */
        xorl    %ebx, %ebx              /* nospec   rbx */
        pushq   %rbp                    /* pt_regs->rbp (will be overwritten) */
        xorl    %ebp, %ebp              /* nospec   rbp */
        pushq   $0                      /* pt_regs->r12 = 0 */
-       xorq    %r12, %r12              /* nospec   r12 */
+       xorl    %r12d, %r12d            /* nospec   r12 */
        pushq   $0                      /* pt_regs->r13 = 0 */
-       xorq    %r13, %r13              /* nospec   r13 */
+       xorl    %r13d, %r13d            /* nospec   r13 */
        pushq   $0                      /* pt_regs->r14 = 0 */
-       xorq    %r14, %r14              /* nospec   r14 */
+       xorl    %r14d, %r14d            /* nospec   r14 */
        pushq   $0                      /* pt_regs->r15 = 0 */
-       xorq    %r15, %r15              /* nospec   r15 */
+       xorl    %r15d, %r15d            /* nospec   r15 */
 
        /*
         * User mode is traced as though IRQs are on, and SYSENTER
@@ -298,9 +298,9 @@ sysret32_from_system_call:
         */
        SWITCH_TO_USER_CR3_NOSTACK scratch_reg=%r8 scratch_reg2=%r9
 
-       xorq    %r8, %r8
-       xorq    %r9, %r9
-       xorq    %r10, %r10
+       xorl    %r8d, %r8d
+       xorl    %r9d, %r9d
+       xorl    %r10d, %r10d
        swapgs
        sysretl
 END(entry_SYSCALL_compat)
@@ -347,10 +347,23 @@ ENTRY(entry_INT80_compat)
         */
        movl    %eax, %eax
 
+       /* switch to thread stack expects orig_ax and rdi to be pushed */
        pushq   %rax                    /* pt_regs->orig_ax */
+       pushq   %rdi                    /* pt_regs->di */
+
+       /* Need to switch before accessing the thread stack. */
+       SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
+       movq    %rsp, %rdi
+       movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
+
+       pushq   6*8(%rdi)               /* regs->ss */
+       pushq   5*8(%rdi)               /* regs->rsp */
+       pushq   4*8(%rdi)               /* regs->eflags */
+       pushq   3*8(%rdi)               /* regs->cs */
+       pushq   2*8(%rdi)               /* regs->ip */
+       pushq   1*8(%rdi)               /* regs->orig_ax */
 
-       /* switch to thread stack expects orig_ax to be pushed */
-       call    switch_to_thread_stack
+       movq    (%rdi), %rdi            /* restore %rdi */
 
        pushq   %rdi                    /* pt_regs->di */
        pushq   %rsi                    /* pt_regs->si */
@@ -358,25 +371,25 @@ ENTRY(entry_INT80_compat)
        pushq   %rcx                    /* pt_regs->cx */
        pushq   $-ENOSYS                /* pt_regs->ax */
        pushq   $0                      /* pt_regs->r8  = 0 */
-       xorq    %r8, %r8                /* nospec   r8 */
+       xorl    %r8d, %r8d              /* nospec   r8 */
        pushq   $0                      /* pt_regs->r9  = 0 */
-       xorq    %r9, %r9                /* nospec   r9 */
+       xorl    %r9d, %r9d              /* nospec   r9 */
        pushq   $0                      /* pt_regs->r10 = 0 */
-       xorq    %r10, %r10              /* nospec   r10 */
+       xorl    %r10d, %r10d            /* nospec   r10 */
        pushq   $0                      /* pt_regs->r11 = 0 */
-       xorq    %r11, %r11              /* nospec   r11 */
+       xorl    %r11d, %r11d            /* nospec   r11 */
        pushq   %rbx                    /* pt_regs->rbx */
        xorl    %ebx, %ebx              /* nospec   rbx */
        pushq   %rbp                    /* pt_regs->rbp */
        xorl    %ebp, %ebp              /* nospec   rbp */
        pushq   %r12                    /* pt_regs->r12 */
-       xorq    %r12, %r12              /* nospec   r12 */
+       xorl    %r12d, %r12d            /* nospec   r12 */
        pushq   %r13                    /* pt_regs->r13 */
-       xorq    %r13, %r13              /* nospec   r13 */
+       xorl    %r13d, %r13d            /* nospec   r13 */
        pushq   %r14                    /* pt_regs->r14 */
-       xorq    %r14, %r14              /* nospec   r14 */
+       xorl    %r14d, %r14d            /* nospec   r14 */
        pushq   %r15                    /* pt_regs->r15 */
-       xorq    %r15, %r15              /* nospec   r15 */
+       xorl    %r15d, %r15d            /* nospec   r15 */
        cld
 
        /*
index 4d4015ddcf2633e9e8388216f9e9c8639e2eced8..c356098b6fb92b8ff7d42b2fd813c2a8551d3db1 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _ASM_X86_MACH_DEFAULT_APM_H
 #define _ASM_X86_MACH_DEFAULT_APM_H
 
+#include <asm/nospec-branch.h>
+
 #ifdef APM_ZERO_SEGS
 #      define APM_DO_ZERO_SEGS \
                "pushl %%ds\n\t" \
@@ -32,6 +34,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
         * N.B. We do NOT need a cld after the BIOS call
         * because we always save and restore the flags.
         */
+       firmware_restrict_branch_speculation_start();
        __asm__ __volatile__(APM_DO_ZERO_SEGS
                "pushl %%edi\n\t"
                "pushl %%ebp\n\t"
@@ -44,6 +47,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
                  "=S" (*esi)
                : "a" (func), "b" (ebx_in), "c" (ecx_in)
                : "memory", "cc");
+       firmware_restrict_branch_speculation_end();
 }
 
 static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
@@ -56,6 +60,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
         * N.B. We do NOT need a cld after the BIOS call
         * because we always save and restore the flags.
         */
+       firmware_restrict_branch_speculation_start();
        __asm__ __volatile__(APM_DO_ZERO_SEGS
                "pushl %%edi\n\t"
                "pushl %%ebp\n\t"
@@ -68,6 +73,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
                  "=S" (si)
                : "a" (func), "b" (ebx_in), "c" (ecx_in)
                : "memory", "cc");
+       firmware_restrict_branch_speculation_end();
        return error;
 }
 
index 4d111616524b2ee3c8d929ec98dd329b332811aa..1908214b91257f1d2442e2e6fc08b2f4c4f5bf65 100644 (file)
@@ -38,7 +38,4 @@ INDIRECT_THUNK(dx)
 INDIRECT_THUNK(si)
 INDIRECT_THUNK(di)
 INDIRECT_THUNK(bp)
-asmlinkage void __fill_rsb(void);
-asmlinkage void __clear_rsb(void);
-
 #endif /* CONFIG_RETPOLINE */
index 0dfe4d3f74e24d6655fc40f0460b9e489fb9ef69..f41079da38c55f8a2e891b044ac9ffb73919c37e 100644 (file)
 #define X86_FEATURE_SEV                        ( 7*32+20) /* AMD Secure Encrypted Virtualization */
 
 #define X86_FEATURE_USE_IBPB           ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
+#define X86_FEATURE_USE_IBRS_FW                ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW         ( 8*32+ 0) /* Intel TPR Shadow */
index 85f6ccb80b91771029f347f1875f7a6d923ef184..a399c1ebf6f0e6d974da0b773248b9c0cfe811a9 100644 (file)
@@ -6,6 +6,7 @@
 #include <asm/pgtable.h>
 #include <asm/processor-flags.h>
 #include <asm/tlb.h>
+#include <asm/nospec-branch.h>
 
 /*
  * We map the EFI regions needed for runtime services non-contiguously,
 
 extern asmlinkage unsigned long efi_call_phys(void *, ...);
 
-#define arch_efi_call_virt_setup()     kernel_fpu_begin()
-#define arch_efi_call_virt_teardown()  kernel_fpu_end()
+#define arch_efi_call_virt_setup()                                     \
+({                                                                     \
+       kernel_fpu_begin();                                             \
+       firmware_restrict_branch_speculation_start();                   \
+})
+
+#define arch_efi_call_virt_teardown()                                  \
+({                                                                     \
+       firmware_restrict_branch_speculation_end();                     \
+       kernel_fpu_end();                                               \
+})
+
 
 /*
  * Wrap all the virtual calls in a way that forces the parameters on the stack.
@@ -73,6 +84,7 @@ struct efi_scratch {
        efi_sync_low_kernel_mappings();                                 \
        preempt_disable();                                              \
        __kernel_fpu_begin();                                           \
+       firmware_restrict_branch_speculation_start();                   \
                                                                        \
        if (efi_scratch.use_pgd) {                                      \
                efi_scratch.prev_cr3 = __read_cr3();                    \
@@ -91,6 +103,7 @@ struct efi_scratch {
                __flush_tlb_all();                                      \
        }                                                               \
                                                                        \
+       firmware_restrict_branch_speculation_end();                     \
        __kernel_fpu_end();                                             \
        preempt_enable();                                               \
 })
index dd6f57a54a2626c080c8505cd670ef8c54c7bf56..b605a5b6a30c38f1bdcf647be241516b5e1310b8 100644 (file)
@@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
        u64 smi_count;
        bool tpr_access_reporting;
        u64 ia32_xss;
+       u64 microcode_version;
 
        /*
         * Paging state of the vcpu
@@ -1095,6 +1096,8 @@ struct kvm_x86_ops {
        int (*mem_enc_op)(struct kvm *kvm, void __user *argp);
        int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
        int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
+
+       int (*get_msr_feature)(struct kvm_msr_entry *entry);
 };
 
 struct kvm_arch_async_pf {
@@ -1464,7 +1467,4 @@ static inline int kvm_cpu_get_apicid(int mps_cpu)
 #define put_smstate(type, buf, offset, val)                      \
        *(type *)((buf) + (offset) - 0x7e00) = val
 
-void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
-               unsigned long start, unsigned long end);
-
 #endif /* _ASM_X86_KVM_HOST_H */
index 55520cec8b27d69727092e6fd81d3a0c0f4db252..7fb1047d61c7b5175906eddc903d23866e8a7bef 100644 (file)
@@ -37,7 +37,12 @@ struct cpu_signature {
 
 struct device;
 
-enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+enum ucode_state {
+       UCODE_OK        = 0,
+       UCODE_UPDATED,
+       UCODE_NFOUND,
+       UCODE_ERROR,
+};
 
 struct microcode_ops {
        enum ucode_state (*request_microcode_user) (int cpu,
@@ -54,7 +59,7 @@ struct microcode_ops {
         * are being called.
         * See also the "Synchronization" section in microcode_core.c.
         */
-       int (*apply_microcode) (int cpu);
+       enum ucode_state (*apply_microcode) (int cpu);
        int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
 };
 
index c931b88982a0ff59e3b67947cc606e452f327dc0..1de72ce514cd5561dbafea43996d909f449f8766 100644 (file)
@@ -74,6 +74,7 @@ static inline void *ldt_slot_va(int slot)
        return (void *)(LDT_BASE_ADDR + LDT_SLOT_STRIDE * slot);
 #else
        BUG();
+       return (void *)fix_to_virt(FIX_HOLE);
 #endif
 }
 
index 81a1be3265711acea06a2538b6b1fdd332b0ab19..d0dabeae05059883844ae2228af62c27885cdbfa 100644 (file)
@@ -8,6 +8,50 @@
 #include <asm/cpufeatures.h>
 #include <asm/msr-index.h>
 
+/*
+ * Fill the CPU return stack buffer.
+ *
+ * Each entry in the RSB, if used for a speculative 'ret', contains an
+ * infinite 'pause; lfence; jmp' loop to capture speculative execution.
+ *
+ * This is required in various cases for retpoline and IBRS-based
+ * mitigations for the Spectre variant 2 vulnerability. Sometimes to
+ * eliminate potentially bogus entries from the RSB, and sometimes
+ * purely to ensure that it doesn't get empty, which on some CPUs would
+ * allow predictions from other (unwanted!) sources to be used.
+ *
+ * We define a CPP macro such that it can be used from both .S files and
+ * inline assembly. It's possible to do a .macro and then include that
+ * from C via asm(".include <asm/nospec-branch.h>") but let's not go there.
+ */
+
+#define RSB_CLEAR_LOOPS                32      /* To forcibly overwrite all entries */
+#define RSB_FILL_LOOPS         16      /* To avoid underflow */
+
+/*
+ * Google experimented with loop-unrolling and this turned out to be
+ * the optimal version â€” two calls, each with their own speculation
+ * trap should their return address end up getting used, in a loop.
+ */
+#define __FILL_RETURN_BUFFER(reg, nr, sp)      \
+       mov     $(nr/2), reg;                   \
+771:                                           \
+       call    772f;                           \
+773:   /* speculation trap */                  \
+       pause;                                  \
+       lfence;                                 \
+       jmp     773b;                           \
+772:                                           \
+       call    774f;                           \
+775:   /* speculation trap */                  \
+       pause;                                  \
+       lfence;                                 \
+       jmp     775b;                           \
+774:                                           \
+       dec     reg;                            \
+       jnz     771b;                           \
+       add     $(BITS_PER_LONG/8) * nr, sp;
+
 #ifdef __ASSEMBLY__
 
 /*
        .popsection
 .endm
 
+/*
+ * This should be used immediately before an indirect jump/call. It tells
+ * objtool the subsequent indirect jump/call is vouched safe for retpoline
+ * builds.
+ */
+.macro ANNOTATE_RETPOLINE_SAFE
+       .Lannotate_\@:
+       .pushsection .discard.retpoline_safe
+       _ASM_PTR .Lannotate_\@
+       .popsection
+.endm
+
 /*
  * These are the bare retpoline primitives for indirect jmp and call.
  * Do not use these directly; they only exist to make the ALTERNATIVE
 .macro JMP_NOSPEC reg:req
 #ifdef CONFIG_RETPOLINE
        ANNOTATE_NOSPEC_ALTERNATIVE
-       ALTERNATIVE_2 __stringify(jmp *\reg),                           \
+       ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *\reg),  \
                __stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE, \
-               __stringify(lfence; jmp *\reg), X86_FEATURE_RETPOLINE_AMD
+               __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *\reg), X86_FEATURE_RETPOLINE_AMD
 #else
        jmp     *\reg
 #endif
 .macro CALL_NOSPEC reg:req
 #ifdef CONFIG_RETPOLINE
        ANNOTATE_NOSPEC_ALTERNATIVE
-       ALTERNATIVE_2 __stringify(call *\reg),                          \
+       ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *\reg), \
                __stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\
-               __stringify(lfence; call *\reg), X86_FEATURE_RETPOLINE_AMD
+               __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *\reg), X86_FEATURE_RETPOLINE_AMD
 #else
        call    *\reg
 #endif
 .endm
 
-/* This clobbers the BX register */
-.macro FILL_RETURN_BUFFER nr:req ftr:req
+ /*
+  * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP
+  * monstrosity above, manually.
+  */
+.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req
 #ifdef CONFIG_RETPOLINE
-       ALTERNATIVE "", "call __clear_rsb", \ftr
+       ANNOTATE_NOSPEC_ALTERNATIVE
+       ALTERNATIVE "jmp .Lskip_rsb_\@",                                \
+               __stringify(__FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP))    \
+               \ftr
+.Lskip_rsb_\@:
 #endif
 .endm
 
        ".long 999b - .\n\t"                                    \
        ".popsection\n\t"
 
+#define ANNOTATE_RETPOLINE_SAFE                                        \
+       "999:\n\t"                                              \
+       ".pushsection .discard.retpoline_safe\n\t"              \
+       _ASM_PTR " 999b\n\t"                                    \
+       ".popsection\n\t"
+
 #if defined(CONFIG_X86_64) && defined(RETPOLINE)
 
 /*
 # define CALL_NOSPEC                                           \
        ANNOTATE_NOSPEC_ALTERNATIVE                             \
        ALTERNATIVE(                                            \
+       ANNOTATE_RETPOLINE_SAFE                                 \
        "call *%[thunk_target]\n",                              \
        "call __x86_indirect_thunk_%V[thunk_target]\n",         \
        X86_FEATURE_RETPOLINE)
@@ -156,26 +226,54 @@ extern char __indirect_thunk_end[];
 static inline void vmexit_fill_RSB(void)
 {
 #ifdef CONFIG_RETPOLINE
-       alternative_input("",
-                         "call __fill_rsb",
-                         X86_FEATURE_RETPOLINE,
-                         ASM_NO_INPUT_CLOBBER(_ASM_BX, "memory"));
+       unsigned long loops;
+
+       asm volatile (ANNOTATE_NOSPEC_ALTERNATIVE
+                     ALTERNATIVE("jmp 910f",
+                                 __stringify(__FILL_RETURN_BUFFER(%0, RSB_CLEAR_LOOPS, %1)),
+                                 X86_FEATURE_RETPOLINE)
+                     "910:"
+                     : "=r" (loops), ASM_CALL_CONSTRAINT
+                     : : "memory" );
 #endif
 }
 
+#define alternative_msr_write(_msr, _val, _feature)            \
+       asm volatile(ALTERNATIVE("",                            \
+                                "movl %[msr], %%ecx\n\t"       \
+                                "movl %[val], %%eax\n\t"       \
+                                "movl $0, %%edx\n\t"           \
+                                "wrmsr",                       \
+                                _feature)                      \
+                    : : [msr] "i" (_msr), [val] "i" (_val)     \
+                    : "eax", "ecx", "edx", "memory")
+
 static inline void indirect_branch_prediction_barrier(void)
 {
-       asm volatile(ALTERNATIVE("",
-                                "movl %[msr], %%ecx\n\t"
-                                "movl %[val], %%eax\n\t"
-                                "movl $0, %%edx\n\t"
-                                "wrmsr",
-                                X86_FEATURE_USE_IBPB)
-                    : : [msr] "i" (MSR_IA32_PRED_CMD),
-                        [val] "i" (PRED_CMD_IBPB)
-                    : "eax", "ecx", "edx", "memory");
+       alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB,
+                             X86_FEATURE_USE_IBPB);
 }
 
+/*
+ * With retpoline, we must use IBRS to restrict branch prediction
+ * before calling into firmware.
+ *
+ * (Implemented as CPP macros due to header hell.)
+ */
+#define firmware_restrict_branch_speculation_start()                   \
+do {                                                                   \
+       preempt_disable();                                              \
+       alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS,       \
+                             X86_FEATURE_USE_IBRS_FW);                 \
+} while (0)
+
+#define firmware_restrict_branch_speculation_end()                     \
+do {                                                                   \
+       alternative_msr_write(MSR_IA32_SPEC_CTRL, 0,                    \
+                             X86_FEATURE_USE_IBRS_FW);                 \
+       preempt_enable();                                               \
+} while (0)
+
 #endif /* __ASSEMBLY__ */
 
 /*
index 554841fab717aef09d2b5cc57410a6eed8c2df0c..c83a2f418cea097bb2c5a9545409c5e6efcbbc50 100644 (file)
@@ -7,6 +7,7 @@
 #ifdef CONFIG_PARAVIRT
 #include <asm/pgtable_types.h>
 #include <asm/asm.h>
+#include <asm/nospec-branch.h>
 
 #include <asm/paravirt_types.h>
 
@@ -879,23 +880,27 @@ extern void default_banner(void);
 
 #define INTERRUPT_RETURN                                               \
        PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE,       \
-                 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret))
+                 ANNOTATE_RETPOLINE_SAFE;                                      \
+                 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret);)
 
 #define DISABLE_INTERRUPTS(clobbers)                                   \
        PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \
                  PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE);            \
+                 ANNOTATE_RETPOLINE_SAFE;                                      \
                  call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable);    \
                  PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
 
 #define ENABLE_INTERRUPTS(clobbers)                                    \
        PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers,  \
                  PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE);            \
+                 ANNOTATE_RETPOLINE_SAFE;                                      \
                  call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable);     \
                  PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
 
 #ifdef CONFIG_X86_32
 #define GET_CR0_INTO_EAX                               \
        push %ecx; push %edx;                           \
+       ANNOTATE_RETPOLINE_SAFE;                                \
        call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
        pop %edx; pop %ecx
 #else  /* !CONFIG_X86_32 */
@@ -917,21 +922,25 @@ extern void default_banner(void);
  */
 #define SWAPGS                                                         \
        PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE,     \
-                 call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs)          \
+                 ANNOTATE_RETPOLINE_SAFE;                                      \
+                 call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs);         \
                 )
 
 #define GET_CR2_INTO_RAX                               \
-       call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2)
+       ANNOTATE_RETPOLINE_SAFE;                                \
+       call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2);
 
 #define USERGS_SYSRET64                                                        \
        PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64),       \
                  CLBR_NONE,                                            \
-                 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64))
+                 ANNOTATE_RETPOLINE_SAFE;                                      \
+                 jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64);)
 
 #ifdef CONFIG_DEBUG_ENTRY
 #define SAVE_FLAGS(clobbers)                                        \
        PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_save_fl), clobbers, \
                  PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE);        \
+                 ANNOTATE_RETPOLINE_SAFE;                                  \
                  call PARA_INDIRECT(pv_irq_ops+PV_IRQ_save_fl);    \
                  PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
 #endif
index f624f1f10316c248911585f757ea5bd257e98434..180bc0bff0fbd98195b8e81ce9aa7232dde06ee2 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/desc_defs.h>
 #include <asm/kmap_types.h>
 #include <asm/pgtable_types.h>
+#include <asm/nospec-branch.h>
 
 struct page;
 struct thread_struct;
@@ -392,7 +393,9 @@ int paravirt_disable_iospace(void);
  * offset into the paravirt_patch_template structure, and can therefore be
  * freely converted back into a structure offset.
  */
-#define PARAVIRT_CALL  "call *%c[paravirt_opptr];"
+#define PARAVIRT_CALL                                  \
+       ANNOTATE_RETPOLINE_SAFE                         \
+       "call *%c[paravirt_opptr];"
 
 /*
  * These macros are intended to wrap calls through one of the paravirt
index 63c2552b6b6547b71bd7aa0934bc3c8c2cb54dc1..b444d83cfc952fc121d77599a938bbcc6c0d864b 100644 (file)
@@ -350,14 +350,14 @@ static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set)
 {
        pmdval_t v = native_pmd_val(pmd);
 
-       return __pmd(v | set);
+       return native_make_pmd(v | set);
 }
 
 static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear)
 {
        pmdval_t v = native_pmd_val(pmd);
 
-       return __pmd(v & ~clear);
+       return native_make_pmd(v & ~clear);
 }
 
 static inline pmd_t pmd_mkold(pmd_t pmd)
@@ -409,14 +409,14 @@ static inline pud_t pud_set_flags(pud_t pud, pudval_t set)
 {
        pudval_t v = native_pud_val(pud);
 
-       return __pud(v | set);
+       return native_make_pud(v | set);
 }
 
 static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear)
 {
        pudval_t v = native_pud_val(pud);
 
-       return __pud(v & ~clear);
+       return native_make_pud(v & ~clear);
 }
 
 static inline pud_t pud_mkold(pud_t pud)
index 3696398a9475fe78500c8c0a62922620d975453c..246f15b4e64ced7b9f70fd789d1a2270214fb7a2 100644 (file)
@@ -323,6 +323,11 @@ static inline pudval_t native_pud_val(pud_t pud)
 #else
 #include <asm-generic/pgtable-nopud.h>
 
+static inline pud_t native_make_pud(pudval_t val)
+{
+       return (pud_t) { .p4d.pgd = native_make_pgd(val) };
+}
+
 static inline pudval_t native_pud_val(pud_t pud)
 {
        return native_pgd_val(pud.p4d.pgd);
@@ -344,6 +349,11 @@ static inline pmdval_t native_pmd_val(pmd_t pmd)
 #else
 #include <asm-generic/pgtable-nopmd.h>
 
+static inline pmd_t native_make_pmd(pmdval_t val)
+{
+       return (pmd_t) { .pud.p4d.pgd = native_make_pgd(val) };
+}
+
 static inline pmdval_t native_pmd_val(pmd_t pmd)
 {
        return native_pgd_val(pmd.pud.p4d.pgd);
index 1bd9ed87606f45f5a22f2510bde9ba34029a0551..b0ccd4847a58ab671476f412905a1df912029f1a 100644 (file)
@@ -977,4 +977,5 @@ bool xen_set_default_idle(void);
 
 void stop_this_cpu(void *dummy);
 void df_debug(struct pt_regs *regs, long error_code);
+void microcode_check(void);
 #endif /* _ASM_X86_PROCESSOR_H */
index 4e44250e7d0d75c6db385dbf151583b31d3e8c19..d65171120e909341516bbde5a5f9f99877c18141 100644 (file)
@@ -67,13 +67,13 @@ static __always_inline __must_check
 bool refcount_sub_and_test(unsigned int i, refcount_t *r)
 {
        GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl", REFCOUNT_CHECK_LT_ZERO,
-                                 r->refs.counter, "er", i, "%0", e);
+                                 r->refs.counter, "er", i, "%0", e, "cx");
 }
 
 static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
 {
        GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl", REFCOUNT_CHECK_LT_ZERO,
-                                r->refs.counter, "%0", e);
+                                r->refs.counter, "%0", e, "cx");
 }
 
 static __always_inline __must_check
index f91c365e57c36d2454806ff21a2d336dae5c6863..4914a3e7c8035538a167c0dc23a2a33afd4a1ca2 100644 (file)
@@ -2,8 +2,7 @@
 #ifndef _ASM_X86_RMWcc
 #define _ASM_X86_RMWcc
 
-#define __CLOBBERS_MEM         "memory"
-#define __CLOBBERS_MEM_CC_CX   "memory", "cc", "cx"
+#define __CLOBBERS_MEM(clb...) "memory", ## clb
 
 #if !defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(CC_HAVE_ASM_GOTO)
 
@@ -40,18 +39,19 @@ do {                                                                        \
 #endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */
 
 #define GEN_UNARY_RMWcc(op, var, arg0, cc)                             \
-       __GEN_RMWcc(op " " arg0, var, cc, __CLOBBERS_MEM)
+       __GEN_RMWcc(op " " arg0, var, cc, __CLOBBERS_MEM())
 
-#define GEN_UNARY_SUFFIXED_RMWcc(op, suffix, var, arg0, cc)            \
+#define GEN_UNARY_SUFFIXED_RMWcc(op, suffix, var, arg0, cc, clobbers...)\
        __GEN_RMWcc(op " " arg0 "\n\t" suffix, var, cc,                 \
-                   __CLOBBERS_MEM_CC_CX)
+                   __CLOBBERS_MEM(clobbers))
 
 #define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
        __GEN_RMWcc(op __BINARY_RMWcc_ARG arg0, var, cc,                \
-                   __CLOBBERS_MEM, vcon (val))
+                   __CLOBBERS_MEM(), vcon (val))
 
-#define GEN_BINARY_SUFFIXED_RMWcc(op, suffix, var, vcon, val, arg0, cc)        \
+#define GEN_BINARY_SUFFIXED_RMWcc(op, suffix, var, vcon, val, arg0, cc,        \
+                                 clobbers...)                          \
        __GEN_RMWcc(op __BINARY_RMWcc_ARG arg0 "\n\t" suffix, var, cc,  \
-                   __CLOBBERS_MEM_CC_CX, vcon (val))
+                   __CLOBBERS_MEM(clobbers), vcon (val))
 
 #endif /* _ASM_X86_RMWcc */
index 7a2ade4aa235380a8c28af6934d30566bb24de73..6cfa9c8cb7d650bef22010de0eca622a86364a73 100644 (file)
@@ -26,6 +26,7 @@
 #define KVM_FEATURE_PV_EOI             6
 #define KVM_FEATURE_PV_UNHALT          7
 #define KVM_FEATURE_PV_TLB_FLUSH       9
+#define KVM_FEATURE_ASYNC_PF_VMEXIT    10
 
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.
index 8ad2e410974f2d4b71a44f033e8c046671b89622..7c5538769f7e43f7bac9c8ff9a30b6a26ac89433 100644 (file)
@@ -1603,7 +1603,7 @@ static void __init delay_with_tsc(void)
        do {
                rep_nop();
                now = rdtsc();
-       } while ((now - start) < 40000000000UL / HZ &&
+       } while ((now - start) < 40000000000ULL / HZ &&
                time_before_eq(jiffies, end));
 }
 
index d71c8b54b696d4593ffb15ff894468ad3e524a50..bfca937bdcc36ce8d9523f03dcc92e93d3c39d5c 100644 (file)
@@ -300,6 +300,15 @@ retpoline_auto:
                setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
                pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n");
        }
+
+       /*
+        * Retpoline means the kernel is safe because it has no indirect
+        * branches. But firmware isn't, so use IBRS to protect that.
+        */
+       if (boot_cpu_has(X86_FEATURE_IBRS)) {
+               setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
+               pr_info("Enabling Restricted Speculation for firmware calls\n");
+       }
 }
 
 #undef pr_fmt
@@ -326,8 +335,9 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
        if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
                return sprintf(buf, "Not affected\n");
 
-       return sprintf(buf, "%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+       return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
                       boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
+                      boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
                       spectre_v2_module_string());
 }
 #endif
index 824aee0117bb5402d52fb5c8958e98b0bebfdf0c..348cf48212405077bd731e25cf7a41de585ba61d 100644 (file)
@@ -1749,3 +1749,33 @@ static int __init init_cpu_syscore(void)
        return 0;
 }
 core_initcall(init_cpu_syscore);
+
+/*
+ * The microcode loader calls this upon late microcode load to recheck features,
+ * only when microcode has been updated. Caller holds microcode_mutex and CPU
+ * hotplug lock.
+ */
+void microcode_check(void)
+{
+       struct cpuinfo_x86 info;
+
+       perf_check_microcode();
+
+       /* Reload CPUID max function as it might've changed. */
+       info.cpuid_level = cpuid_eax(0);
+
+       /*
+        * Copy all capability leafs to pick up the synthetic ones so that
+        * memcmp() below doesn't fail on that. The ones coming from CPUID will
+        * get overwritten in get_cpu_cap().
+        */
+       memcpy(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability));
+
+       get_cpu_cap(&info);
+
+       if (!memcmp(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability)))
+               return;
+
+       pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
+       pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
+}
index 330b8462d426faad0dccdc480f34eec34cd8b92f..a998e1a7d46fdc7f2bdb4b58b11b49ab28ddc638 100644 (file)
@@ -498,7 +498,7 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
        return patch_size;
 }
 
-static int apply_microcode_amd(int cpu)
+static enum ucode_state apply_microcode_amd(int cpu)
 {
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct microcode_amd *mc_amd;
@@ -512,7 +512,7 @@ static int apply_microcode_amd(int cpu)
 
        p = find_patch(cpu);
        if (!p)
-               return 0;
+               return UCODE_NFOUND;
 
        mc_amd  = p->data;
        uci->mc = p->data;
@@ -523,13 +523,13 @@ static int apply_microcode_amd(int cpu)
        if (rev >= mc_amd->hdr.patch_id) {
                c->microcode = rev;
                uci->cpu_sig.rev = rev;
-               return 0;
+               return UCODE_OK;
        }
 
        if (__apply_microcode_amd(mc_amd)) {
                pr_err("CPU%d: update failed for patch_level=0x%08x\n",
                        cpu, mc_amd->hdr.patch_id);
-               return -1;
+               return UCODE_ERROR;
        }
        pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
                mc_amd->hdr.patch_id);
@@ -537,7 +537,7 @@ static int apply_microcode_amd(int cpu)
        uci->cpu_sig.rev = mc_amd->hdr.patch_id;
        c->microcode = mc_amd->hdr.patch_id;
 
-       return 0;
+       return UCODE_UPDATED;
 }
 
 static int install_equiv_cpu_table(const u8 *buf)
index 319dd65f98a25530d3a55cb6ea1cf61f6c2004bc..aa1b9a422f2be0daf18a7084837165172ef0fafb 100644 (file)
@@ -374,7 +374,7 @@ static int collect_cpu_info(int cpu)
 }
 
 struct apply_microcode_ctx {
-       int err;
+       enum ucode_state err;
 };
 
 static void apply_microcode_local(void *arg)
@@ -489,31 +489,30 @@ static void __exit microcode_dev_exit(void)
 /* fake device for request_firmware */
 static struct platform_device  *microcode_pdev;
 
-static int reload_for_cpu(int cpu)
+static enum ucode_state reload_for_cpu(int cpu)
 {
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        enum ucode_state ustate;
-       int err = 0;
 
        if (!uci->valid)
-               return err;
+               return UCODE_OK;
 
        ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
-       if (ustate == UCODE_OK)
-               apply_microcode_on_target(cpu);
-       else
-               if (ustate == UCODE_ERROR)
-                       err = -EINVAL;
-       return err;
+       if (ustate != UCODE_OK)
+               return ustate;
+
+       return apply_microcode_on_target(cpu);
 }
 
 static ssize_t reload_store(struct device *dev,
                            struct device_attribute *attr,
                            const char *buf, size_t size)
 {
+       enum ucode_state tmp_ret = UCODE_OK;
+       bool do_callback = false;
        unsigned long val;
+       ssize_t ret = 0;
        int cpu;
-       ssize_t ret = 0, tmp_ret;
 
        ret = kstrtoul(buf, 0, &val);
        if (ret)
@@ -526,15 +525,21 @@ static ssize_t reload_store(struct device *dev,
        mutex_lock(&microcode_mutex);
        for_each_online_cpu(cpu) {
                tmp_ret = reload_for_cpu(cpu);
-               if (tmp_ret != 0)
+               if (tmp_ret > UCODE_NFOUND) {
                        pr_warn("Error reloading microcode on CPU %d\n", cpu);
 
-               /* save retval of the first encountered reload error */
-               if (!ret)
-                       ret = tmp_ret;
+                       /* set retval for the first encountered reload error */
+                       if (!ret)
+                               ret = -EINVAL;
+               }
+
+               if (tmp_ret == UCODE_UPDATED)
+                       do_callback = true;
        }
-       if (!ret)
-               perf_check_microcode();
+
+       if (!ret && do_callback)
+               microcode_check();
+
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
index a15db2b4e0d66a8b5c4d2468359eeafb85401151..923054a6b76013a1474372b7810749f577b0c811 100644 (file)
@@ -772,7 +772,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
        return 0;
 }
 
-static int apply_microcode_intel(int cpu)
+static enum ucode_state apply_microcode_intel(int cpu)
 {
        struct microcode_intel *mc;
        struct ucode_cpu_info *uci;
@@ -782,7 +782,7 @@ static int apply_microcode_intel(int cpu)
 
        /* We should bind the task to the CPU */
        if (WARN_ON(raw_smp_processor_id() != cpu))
-               return -1;
+               return UCODE_ERROR;
 
        uci = ucode_cpu_info + cpu;
        mc = uci->mc;
@@ -790,7 +790,7 @@ static int apply_microcode_intel(int cpu)
                /* Look for a newer patch in our cache: */
                mc = find_patch(uci);
                if (!mc)
-                       return 0;
+                       return UCODE_NFOUND;
        }
 
        /* write microcode via MSR 0x79 */
@@ -801,7 +801,7 @@ static int apply_microcode_intel(int cpu)
        if (rev != mc->hdr.rev) {
                pr_err("CPU%d update to revision 0x%x failed\n",
                       cpu, mc->hdr.rev);
-               return -1;
+               return UCODE_ERROR;
        }
 
        if (rev != prev_rev) {
@@ -818,7 +818,7 @@ static int apply_microcode_intel(int cpu)
        uci->cpu_sig.rev = rev;
        c->microcode = rev;
 
-       return 0;
+       return UCODE_UPDATED;
 }
 
 static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
index 04a625f0fcda322dab7c9d8459a19ee56b71c936..0f545b3cf926787bd986d763c843498540ef530d 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/nops.h>
 #include "../entry/calling.h"
 #include <asm/export.h>
+#include <asm/nospec-branch.h>
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/asm-offsets.h>
@@ -134,6 +135,7 @@ ENTRY(secondary_startup_64)
 
        /* Ensure I am executing from virtual addresses */
        movq    $1f, %rax
+       ANNOTATE_RETPOLINE_SAFE
        jmp     *%rax
 1:
        UNWIND_HINT_EMPTY
index 4e37d1a851a62df3f9f841f3bbd66827af0c1920..bc1a27280c4bf77899afad4b85bf53212d385cab 100644 (file)
@@ -49,7 +49,7 @@
 
 static int kvmapf = 1;
 
-static int parse_no_kvmapf(char *arg)
+static int __init parse_no_kvmapf(char *arg)
 {
         kvmapf = 0;
         return 0;
@@ -58,7 +58,7 @@ static int parse_no_kvmapf(char *arg)
 early_param("no-kvmapf", parse_no_kvmapf);
 
 static int steal_acc = 1;
-static int parse_no_stealacc(char *arg)
+static int __init parse_no_stealacc(char *arg)
 {
         steal_acc = 0;
         return 0;
@@ -67,7 +67,7 @@ static int parse_no_stealacc(char *arg)
 early_param("no-steal-acc", parse_no_stealacc);
 
 static int kvmclock_vsyscall = 1;
-static int parse_no_kvmclock_vsyscall(char *arg)
+static int __init parse_no_kvmclock_vsyscall(char *arg)
 {
         kvmclock_vsyscall = 0;
         return 0;
@@ -341,10 +341,10 @@ static void kvm_guest_cpu_init(void)
 #endif
                pa |= KVM_ASYNC_PF_ENABLED;
 
-               /* Async page fault support for L1 hypervisor is optional */
-               if (wrmsr_safe(MSR_KVM_ASYNC_PF_EN,
-                       (pa | KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT) & 0xffffffff, pa >> 32) < 0)
-                       wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
+               if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF_VMEXIT))
+                       pa |= KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;
+
+               wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
                __this_cpu_write(apf_reason.enabled, 1);
                printk(KERN_INFO"KVM setup async PF for cpu %d\n",
                       smp_processor_id());
@@ -545,7 +545,8 @@ static void __init kvm_guest_init(void)
                pv_time_ops.steal_clock = kvm_steal_clock;
        }
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH))
+       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
+           !kvm_para_has_feature(KVM_FEATURE_STEAL_TIME))
                pv_mmu_ops.flush_tlb_others = kvm_flush_tlb_others;
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
@@ -633,7 +634,8 @@ static __init int kvm_setup_pv_tlb_flush(void)
 {
        int cpu;
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH)) {
+       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
+           !kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
                for_each_possible_cpu(cpu) {
                        zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu),
                                GFP_KERNEL, cpu_to_node(cpu));
index 1f9188f5357cb38e45295c07ba5f2e902563257e..feb28fee6cea7f9fbad1a4b06ee9932ac8690d75 100644 (file)
@@ -5,7 +5,6 @@
 #include <asm/unwind.h>
 #include <asm/orc_types.h>
 #include <asm/orc_lookup.h>
-#include <asm/sections.h>
 
 #define orc_warn(fmt, ...) \
        printk_deferred_once(KERN_WARNING pr_fmt("WARNING: " fmt), ##__VA_ARGS__)
@@ -148,7 +147,7 @@ static struct orc_entry *orc_find(unsigned long ip)
        }
 
        /* vmlinux .init slow lookup: */
-       if (ip >= (unsigned long)_sinittext && ip < (unsigned long)_einittext)
+       if (init_kernel_text(ip))
                return __orc_find(__start_orc_unwind_ip, __start_orc_unwind,
                                  __stop_orc_unwind_ip - __start_orc_unwind_ip, ip);
 
index a0c5a69bc7c4a324078db14ad27753443d65aa85..b671fc2d0422717f06ca6291b2a76742ee45537a 100644 (file)
@@ -607,7 +607,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                             (1 << KVM_FEATURE_PV_EOI) |
                             (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
                             (1 << KVM_FEATURE_PV_UNHALT) |
-                            (1 << KVM_FEATURE_PV_TLB_FLUSH);
+                            (1 << KVM_FEATURE_PV_TLB_FLUSH) |
+                            (1 << KVM_FEATURE_ASYNC_PF_VMEXIT);
 
                if (sched_info_on())
                        entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
index 924ac8ce9d5004f9db4126a81f178c2bf0e6ff40..391dda8d43b7a44d3cedd0b41edbb51ba7171bf4 100644 (file)
@@ -2002,14 +2002,13 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 
 void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
 {
-       struct kvm_lapic *apic;
+       struct kvm_lapic *apic = vcpu->arch.apic;
        int i;
 
-       apic_debug("%s\n", __func__);
+       if (!apic)
+               return;
 
-       ASSERT(vcpu);
-       apic = vcpu->arch.apic;
-       ASSERT(apic != NULL);
+       apic_debug("%s\n", __func__);
 
        /* Stop the timer in case it's a reset to an active apic */
        hrtimer_cancel(&apic->lapic_timer.timer);
@@ -2165,7 +2164,6 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
         */
        vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE;
        static_key_slow_inc(&apic_sw_disabled.key); /* sw disabled at reset */
-       kvm_lapic_reset(vcpu, false);
        kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
 
        return 0;
@@ -2569,7 +2567,6 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
 
        pe = xchg(&apic->pending_events, 0);
        if (test_bit(KVM_APIC_INIT, &pe)) {
-               kvm_lapic_reset(vcpu, true);
                kvm_vcpu_reset(vcpu, true);
                if (kvm_vcpu_is_bsp(apic->vcpu))
                        vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
index 46ff304140c71fad1fa818324c0cda017257d2a5..f551962ac29488431b80d56aaabcec7a576a791f 100644 (file)
@@ -3029,7 +3029,7 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
                return RET_PF_RETRY;
        }
 
-       return -EFAULT;
+       return RET_PF_EMULATE;
 }
 
 static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
index b3e488a748281aa5f3d319861ae2ab4bfca3e65c..be9c839e2c89967d689485dbb8e51763980dd151 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/debugreg.h>
 #include <asm/kvm_para.h>
 #include <asm/irq_remapping.h>
+#include <asm/microcode.h>
 #include <asm/nospec-branch.h>
 
 #include <asm/virtext.h>
@@ -178,6 +179,8 @@ struct vcpu_svm {
        uint64_t sysenter_eip;
        uint64_t tsc_aux;
 
+       u64 msr_decfg;
+
        u64 next_rip;
 
        u64 host_user_msrs[NR_HOST_SAVE_USER_MSRS];
@@ -300,6 +303,8 @@ module_param(vgif, int, 0444);
 static int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT);
 module_param(sev, int, 0444);
 
+static u8 rsm_ins_bytes[] = "\x0f\xaa";
+
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa);
 static void svm_complete_interrupts(struct vcpu_svm *svm);
@@ -1383,6 +1388,7 @@ static void init_vmcb(struct vcpu_svm *svm)
        set_intercept(svm, INTERCEPT_SKINIT);
        set_intercept(svm, INTERCEPT_WBINVD);
        set_intercept(svm, INTERCEPT_XSETBV);
+       set_intercept(svm, INTERCEPT_RSM);
 
        if (!kvm_mwait_in_guest()) {
                set_intercept(svm, INTERCEPT_MONITOR);
@@ -1902,6 +1908,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        u32 dummy;
        u32 eax = 1;
 
+       vcpu->arch.microcode_version = 0x01000065;
        svm->spec_ctrl = 0;
 
        if (!init_event) {
@@ -3699,6 +3706,12 @@ static int emulate_on_interception(struct vcpu_svm *svm)
        return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
 }
 
+static int rsm_interception(struct vcpu_svm *svm)
+{
+       return x86_emulate_instruction(&svm->vcpu, 0, 0,
+                                      rsm_ins_bytes, 2) == EMULATE_DONE;
+}
+
 static int rdpmc_interception(struct vcpu_svm *svm)
 {
        int err;
@@ -3860,6 +3873,22 @@ static int cr8_write_interception(struct vcpu_svm *svm)
        return 0;
 }
 
+static int svm_get_msr_feature(struct kvm_msr_entry *msr)
+{
+       msr->data = 0;
+
+       switch (msr->index) {
+       case MSR_F10H_DECFG:
+               if (boot_cpu_has(X86_FEATURE_LFENCE_RDTSC))
+                       msr->data |= MSR_F10H_DECFG_LFENCE_SERIALIZE;
+               break;
+       default:
+               return 1;
+       }
+
+       return 0;
+}
+
 static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -3935,9 +3964,6 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
                msr_info->data = svm->spec_ctrl;
                break;
-       case MSR_IA32_UCODE_REV:
-               msr_info->data = 0x01000065;
-               break;
        case MSR_F15H_IC_CFG: {
 
                int family, model;
@@ -3955,6 +3981,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        msr_info->data = 0x1E;
                }
                break;
+       case MSR_F10H_DECFG:
+               msr_info->data = svm->msr_decfg;
+               break;
        default:
                return kvm_get_msr_common(vcpu, msr_info);
        }
@@ -4133,6 +4162,24 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
        case MSR_VM_IGNNE:
                vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
                break;
+       case MSR_F10H_DECFG: {
+               struct kvm_msr_entry msr_entry;
+
+               msr_entry.index = msr->index;
+               if (svm_get_msr_feature(&msr_entry))
+                       return 1;
+
+               /* Check the supported bits */
+               if (data & ~msr_entry.data)
+                       return 1;
+
+               /* Don't allow the guest to change a bit, #GP */
+               if (!msr->host_initiated && (data ^ msr_entry.data))
+                       return 1;
+
+               svm->msr_decfg = data;
+               break;
+       }
        case MSR_IA32_APICBASE:
                if (kvm_vcpu_apicv_active(vcpu))
                        avic_update_vapic_bar(to_svm(vcpu), data);
@@ -4541,7 +4588,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_MWAIT]                        = mwait_interception,
        [SVM_EXIT_XSETBV]                       = xsetbv_interception,
        [SVM_EXIT_NPF]                          = npf_interception,
-       [SVM_EXIT_RSM]                          = emulate_on_interception,
+       [SVM_EXIT_RSM]                          = rsm_interception,
        [SVM_EXIT_AVIC_INCOMPLETE_IPI]          = avic_incomplete_ipi_interception,
        [SVM_EXIT_AVIC_UNACCELERATED_ACCESS]    = avic_unaccelerated_access_interception,
 };
@@ -5355,7 +5402,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
         * being speculatively taken.
         */
        if (svm->spec_ctrl)
-               wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
+               native_wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
 
        asm volatile (
                "push %%" _ASM_BP "; \n\t"
@@ -5464,11 +5511,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
         * If the L02 MSR bitmap does not intercept the MSR, then we need to
         * save it.
         */
-       if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))
-               rdmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
+       if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
+               svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
 
        if (svm->spec_ctrl)
-               wrmsrl(MSR_IA32_SPEC_CTRL, 0);
+               native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
 
        /* Eliminate branch target predictions from guest mode */
        vmexit_fill_RSB();
@@ -6236,16 +6283,18 @@ e_free:
 
 static int sev_launch_measure(struct kvm *kvm, struct kvm_sev_cmd *argp)
 {
+       void __user *measure = (void __user *)(uintptr_t)argp->data;
        struct kvm_sev_info *sev = &kvm->arch.sev_info;
        struct sev_data_launch_measure *data;
        struct kvm_sev_launch_measure params;
+       void __user *p = NULL;
        void *blob = NULL;
        int ret;
 
        if (!sev_guest(kvm))
                return -ENOTTY;
 
-       if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data, sizeof(params)))
+       if (copy_from_user(&params, measure, sizeof(params)))
                return -EFAULT;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -6256,17 +6305,13 @@ static int sev_launch_measure(struct kvm *kvm, struct kvm_sev_cmd *argp)
        if (!params.len)
                goto cmd;
 
-       if (params.uaddr) {
+       p = (void __user *)(uintptr_t)params.uaddr;
+       if (p) {
                if (params.len > SEV_FW_BLOB_MAX_SIZE) {
                        ret = -EINVAL;
                        goto e_free;
                }
 
-               if (!access_ok(VERIFY_WRITE, params.uaddr, params.len)) {
-                       ret = -EFAULT;
-                       goto e_free;
-               }
-
                ret = -ENOMEM;
                blob = kmalloc(params.len, GFP_KERNEL);
                if (!blob)
@@ -6290,13 +6335,13 @@ cmd:
                goto e_free_blob;
 
        if (blob) {
-               if (copy_to_user((void __user *)(uintptr_t)params.uaddr, blob, params.len))
+               if (copy_to_user(p, blob, params.len))
                        ret = -EFAULT;
        }
 
 done:
        params.len = data->len;
-       if (copy_to_user((void __user *)(uintptr_t)argp->data, &params, sizeof(params)))
+       if (copy_to_user(measure, &params, sizeof(params)))
                ret = -EFAULT;
 e_free_blob:
        kfree(blob);
@@ -6597,7 +6642,7 @@ static int sev_launch_secret(struct kvm *kvm, struct kvm_sev_cmd *argp)
        struct page **pages;
        void *blob, *hdr;
        unsigned long n;
-       int ret;
+       int ret, offset;
 
        if (!sev_guest(kvm))
                return -ENOTTY;
@@ -6623,6 +6668,10 @@ static int sev_launch_secret(struct kvm *kvm, struct kvm_sev_cmd *argp)
        if (!data)
                goto e_unpin_memory;
 
+       offset = params.guest_uaddr & (PAGE_SIZE - 1);
+       data->guest_address = __sme_page_pa(pages[0]) + offset;
+       data->guest_len = params.guest_len;
+
        blob = psp_copy_user_blob(params.trans_uaddr, params.trans_len);
        if (IS_ERR(blob)) {
                ret = PTR_ERR(blob);
@@ -6637,8 +6686,8 @@ static int sev_launch_secret(struct kvm *kvm, struct kvm_sev_cmd *argp)
                ret = PTR_ERR(hdr);
                goto e_free_blob;
        }
-       data->trans_address = __psp_pa(blob);
-       data->trans_len = params.trans_len;
+       data->hdr_address = __psp_pa(hdr);
+       data->hdr_len = params.hdr_len;
 
        data->handle = sev->handle;
        ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_SECRET, data, &argp->error);
@@ -6821,6 +6870,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .vcpu_unblocking = svm_vcpu_unblocking,
 
        .update_bp_intercept = update_bp_intercept,
+       .get_msr_feature = svm_get_msr_feature,
        .get_msr = svm_get_msr,
        .set_msr = svm_set_msr,
        .get_segment_base = svm_get_segment_base,
index 3dec126aa3022eb11f49d5de695d3658183a48ee..051dab74e4e928ac7bf90598c0b9a9a8d8855f13 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/apic.h>
 #include <asm/irq_remapping.h>
 #include <asm/mmu_context.h>
+#include <asm/microcode.h>
 #include <asm/nospec-branch.h>
 
 #include "trace.h"
@@ -3226,6 +3227,11 @@ static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
        return !(val & ~valid_bits);
 }
 
+static int vmx_get_msr_feature(struct kvm_msr_entry *msr)
+{
+       return 1;
+}
+
 /*
  * Reads an msr value (of 'msr_index') into 'pdata'.
  * Returns 0 on success, non-0 otherwise.
@@ -4485,7 +4491,8 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
                              SECONDARY_EXEC_DESC);
                hw_cr4 &= ~X86_CR4_UMIP;
-       } else
+       } else if (!is_guest_mode(vcpu) ||
+                  !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC))
                vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
                                SECONDARY_EXEC_DESC);
 
@@ -5765,6 +5772,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        vmx->rmode.vm86_active = 0;
        vmx->spec_ctrl = 0;
 
+       vcpu->arch.microcode_version = 0x100000000ULL;
        vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
        kvm_set_cr8(vcpu, 0);
 
@@ -9452,7 +9460,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
         * being speculatively taken.
         */
        if (vmx->spec_ctrl)
-               wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
+               native_wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
 
        vmx->__launched = vmx->loaded_vmcs->launched;
        asm(
@@ -9587,11 +9595,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
         * If the L02 MSR bitmap does not intercept the MSR, then we need to
         * save it.
         */
-       if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))
-               rdmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
+       if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
+               vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
 
        if (vmx->spec_ctrl)
-               wrmsrl(MSR_IA32_SPEC_CTRL, 0);
+               native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
 
        /* Eliminate branch target predictions from guest mode */
        vmexit_fill_RSB();
@@ -11199,7 +11207,12 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
        if (ret)
                return ret;
 
-       if (vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT)
+       /*
+        * If we're entering a halted L2 vcpu and the L2 vcpu won't be woken
+        * by event injection, halt vcpu.
+        */
+       if ((vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) &&
+           !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK))
                return kvm_vcpu_halt(vcpu);
 
        vmx->nested.nested_run_pending = 1;
@@ -12290,6 +12303,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .vcpu_put = vmx_vcpu_put,
 
        .update_bp_intercept = update_exception_bitmap,
+       .get_msr_feature = vmx_get_msr_feature,
        .get_msr = vmx_get_msr,
        .set_msr = vmx_set_msr,
        .get_segment_base = vmx_get_segment_base,
index c8a0b545ac20c71a464738a1dd0cd7e1c3df388e..18b5ca7a31974757f0dfdd43f5d7e0805f4f3aaa 100644 (file)
@@ -1049,6 +1049,45 @@ static u32 emulated_msrs[] = {
 
 static unsigned num_emulated_msrs;
 
+/*
+ * List of msr numbers which are used to expose MSR-based features that
+ * can be used by a hypervisor to validate requested CPU features.
+ */
+static u32 msr_based_features[] = {
+       MSR_F10H_DECFG,
+       MSR_IA32_UCODE_REV,
+};
+
+static unsigned int num_msr_based_features;
+
+static int kvm_get_msr_feature(struct kvm_msr_entry *msr)
+{
+       switch (msr->index) {
+       case MSR_IA32_UCODE_REV:
+               rdmsrl(msr->index, msr->data);
+               break;
+       default:
+               if (kvm_x86_ops->get_msr_feature(msr))
+                       return 1;
+       }
+       return 0;
+}
+
+static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
+{
+       struct kvm_msr_entry msr;
+       int r;
+
+       msr.index = index;
+       r = kvm_get_msr_feature(&msr);
+       if (r)
+               return r;
+
+       *data = msr.data;
+
+       return 0;
+}
+
 bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
        if (efer & efer_reserved_bits)
@@ -2222,7 +2261,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
        switch (msr) {
        case MSR_AMD64_NB_CFG:
-       case MSR_IA32_UCODE_REV:
        case MSR_IA32_UCODE_WRITE:
        case MSR_VM_HSAVE_PA:
        case MSR_AMD64_PATCH_LOADER:
@@ -2230,6 +2268,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_AMD64_DC_CFG:
                break;
 
+       case MSR_IA32_UCODE_REV:
+               if (msr_info->host_initiated)
+                       vcpu->arch.microcode_version = data;
+               break;
        case MSR_EFER:
                return set_efer(vcpu, data);
        case MSR_K7_HWCR:
@@ -2525,7 +2567,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = 0;
                break;
        case MSR_IA32_UCODE_REV:
-               msr_info->data = 0x100000000ULL;
+               msr_info->data = vcpu->arch.microcode_version;
                break;
        case MSR_MTRRcap:
        case 0x200 ... 0x2ff:
@@ -2680,13 +2722,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
                    int (*do_msr)(struct kvm_vcpu *vcpu,
                                  unsigned index, u64 *data))
 {
-       int i, idx;
+       int i;
 
-       idx = srcu_read_lock(&vcpu->kvm->srcu);
        for (i = 0; i < msrs->nmsrs; ++i)
                if (do_msr(vcpu, entries[i].index, &entries[i].data))
                        break;
-       srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
        return i;
 }
@@ -2785,6 +2825,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_SET_BOOT_CPU_ID:
        case KVM_CAP_SPLIT_IRQCHIP:
        case KVM_CAP_IMMEDIATE_EXIT:
+       case KVM_CAP_GET_MSR_FEATURES:
                r = 1;
                break;
        case KVM_CAP_ADJUST_CLOCK:
@@ -2899,6 +2940,31 @@ long kvm_arch_dev_ioctl(struct file *filp,
                        goto out;
                r = 0;
                break;
+       case KVM_GET_MSR_FEATURE_INDEX_LIST: {
+               struct kvm_msr_list __user *user_msr_list = argp;
+               struct kvm_msr_list msr_list;
+               unsigned int n;
+
+               r = -EFAULT;
+               if (copy_from_user(&msr_list, user_msr_list, sizeof(msr_list)))
+                       goto out;
+               n = msr_list.nmsrs;
+               msr_list.nmsrs = num_msr_based_features;
+               if (copy_to_user(user_msr_list, &msr_list, sizeof(msr_list)))
+                       goto out;
+               r = -E2BIG;
+               if (n < msr_list.nmsrs)
+                       goto out;
+               r = -EFAULT;
+               if (copy_to_user(user_msr_list->indices, &msr_based_features,
+                                num_msr_based_features * sizeof(u32)))
+                       goto out;
+               r = 0;
+               break;
+       }
+       case KVM_GET_MSRS:
+               r = msr_io(NULL, argp, do_get_msr_feature, 1);
+               break;
        }
        default:
                r = -EINVAL;
@@ -3636,12 +3702,18 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = 0;
                break;
        }
-       case KVM_GET_MSRS:
+       case KVM_GET_MSRS: {
+               int idx = srcu_read_lock(&vcpu->kvm->srcu);
                r = msr_io(vcpu, argp, do_get_msr, 1);
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
-       case KVM_SET_MSRS:
+       }
+       case KVM_SET_MSRS: {
+               int idx = srcu_read_lock(&vcpu->kvm->srcu);
                r = msr_io(vcpu, argp, do_set_msr, 0);
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
+       }
        case KVM_TPR_ACCESS_REPORTING: {
                struct kvm_tpr_access_ctl tac;
 
@@ -4464,6 +4536,19 @@ static void kvm_init_msr_list(void)
                j++;
        }
        num_emulated_msrs = j;
+
+       for (i = j = 0; i < ARRAY_SIZE(msr_based_features); i++) {
+               struct kvm_msr_entry msr;
+
+               msr.index = msr_based_features[i];
+               if (kvm_get_msr_feature(&msr))
+                       continue;
+
+               if (j < i)
+                       msr_based_features[j] = msr_based_features[i];
+               j++;
+       }
+       num_msr_based_features = j;
 }
 
 static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
@@ -8017,6 +8102,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
 void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 {
+       kvm_lapic_reset(vcpu, init_event);
+
        vcpu->arch.hflags = 0;
 
        vcpu->arch.smi_pending = 0;
@@ -8460,10 +8547,8 @@ int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
                        return r;
        }
 
-       if (!size) {
-               r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
-               WARN_ON(r < 0);
-       }
+       if (!size)
+               vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
 
        return 0;
 }
index 91e9700cc6dcd2152f7488740ad3f9a6e1b766c4..25a972c61b0ae9816a817eb9681f4cd374e9e32a 100644 (file)
@@ -28,7 +28,6 @@ lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o insn-eval.o
 lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
 lib-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
 lib-$(CONFIG_RETPOLINE) += retpoline.o
-OBJECT_FILES_NON_STANDARD_retpoline.o :=y
 
 obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
 
index 480edc3a5e03002dd6f0a0316477cbd7b0971cc8..c909961e678a594bd3812cb14936bdf035af2bb9 100644 (file)
@@ -7,7 +7,6 @@
 #include <asm/alternative-asm.h>
 #include <asm/export.h>
 #include <asm/nospec-branch.h>
-#include <asm/bitsperlong.h>
 
 .macro THUNK reg
        .section .text.__x86.indirect_thunk
@@ -47,58 +46,3 @@ GENERATE_THUNK(r13)
 GENERATE_THUNK(r14)
 GENERATE_THUNK(r15)
 #endif
-
-/*
- * Fill the CPU return stack buffer.
- *
- * Each entry in the RSB, if used for a speculative 'ret', contains an
- * infinite 'pause; lfence; jmp' loop to capture speculative execution.
- *
- * This is required in various cases for retpoline and IBRS-based
- * mitigations for the Spectre variant 2 vulnerability. Sometimes to
- * eliminate potentially bogus entries from the RSB, and sometimes
- * purely to ensure that it doesn't get empty, which on some CPUs would
- * allow predictions from other (unwanted!) sources to be used.
- *
- * Google experimented with loop-unrolling and this turned out to be
- * the optimal version - two calls, each with their own speculation
- * trap should their return address end up getting used, in a loop.
- */
-.macro STUFF_RSB nr:req sp:req
-       mov     $(\nr / 2), %_ASM_BX
-       .align 16
-771:
-       call    772f
-773:                                           /* speculation trap */
-       pause
-       lfence
-       jmp     773b
-       .align 16
-772:
-       call    774f
-775:                                           /* speculation trap */
-       pause
-       lfence
-       jmp     775b
-       .align 16
-774:
-       dec     %_ASM_BX
-       jnz     771b
-       add     $((BITS_PER_LONG/8) * \nr), \sp
-.endm
-
-#define RSB_FILL_LOOPS         16      /* To avoid underflow */
-
-ENTRY(__fill_rsb)
-       STUFF_RSB RSB_FILL_LOOPS, %_ASM_SP
-       ret
-END(__fill_rsb)
-EXPORT_SYMBOL_GPL(__fill_rsb)
-
-#define RSB_CLEAR_LOOPS                32      /* To forcibly overwrite all entries */
-
-ENTRY(__clear_rsb)
-       STUFF_RSB RSB_CLEAR_LOOPS, %_ASM_SP
-       ret
-END(__clear_rsb)
-EXPORT_SYMBOL_GPL(__clear_rsb)
index 800de815519cd1061c090e70fab09bd62bbd8ddd..c88573d90f3e9d3a521049d4655fd4857b99be3d 100644 (file)
@@ -1248,10 +1248,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
        tsk = current;
        mm = tsk->mm;
 
-       /*
-        * Detect and handle instructions that would cause a page fault for
-        * both a tracked kernel page and a userspace page.
-        */
        prefetchw(&mm->mmap_sem);
 
        if (unlikely(kmmio_fault(regs, address)))
index 01f682cf77a8b36bff9a2b45a8f8beb734b4b6c4..40a6085063d6fe87958f260bf9cbc1be3b647424 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/page.h>
 #include <asm/processor-flags.h>
 #include <asm/msr-index.h>
+#include <asm/nospec-branch.h>
 
        .text
        .code64
@@ -59,6 +60,7 @@ ENTRY(sme_encrypt_execute)
        movq    %rax, %r8               /* Workarea encryption routine */
        addq    $PAGE_SIZE, %r8         /* Workarea intermediate copy buffer */
 
+       ANNOTATE_RETPOLINE_SAFE
        call    *%rax                   /* Call the encryption routine */
 
        pop     %r12
index de53bd15df5a865589e7eda181a1771fbe7297e4..24bb7598774e6aa94203e601f41329d31308692e 100644 (file)
@@ -102,7 +102,7 @@ ENTRY(startup_32)
         * don't we'll eventually crash trying to execute encrypted
         * instructions.
         */
-       bt      $TH_FLAGS_SME_ACTIVE_BIT, pa_tr_flags
+       btl     $TH_FLAGS_SME_ACTIVE_BIT, pa_tr_flags
        jnc     .Ldone
        movl    $MSR_K8_SYSCFG, %ecx
        rdmsr
index c047f42552e1a61ed0a5787d904681974cc05af1..3c2c2530737efc717c9945ee1e2990e5b5bfd4c5 100644 (file)
@@ -1376,8 +1376,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
 
        if (!xen_initial_domain()) {
                add_preferred_console("xenboot", 0, NULL);
-               add_preferred_console("tty", 0, NULL);
-               add_preferred_console("hvc", 0, NULL);
                if (pci_xen)
                        x86_init.pci.arch_init = pci_xen_init;
        } else {
@@ -1410,6 +1408,10 @@ asmlinkage __visible void __init xen_start_kernel(void)
 
                xen_boot_params_init_edd();
        }
+
+       add_preferred_console("tty", 0, NULL);
+       add_preferred_console("hvc", 0, NULL);
+
 #ifdef CONFIG_PCI
        /* PCI BIOS service won't work from a PV guest. */
        pci_probe &= ~PCI_PROBE_BIOS;
index 4117524ca45bc76cceb163c42f752ffd8d7e1659..c2033a232a443a3b54def7e9d88b646a7ac950d5 100644 (file)
@@ -812,7 +812,6 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
        struct gendisk *disk;
        struct request_queue *q;
        struct blkcg_gq *blkg;
-       struct module *owner;
        unsigned int major, minor;
        int key_len, part, ret;
        char *body;
@@ -904,9 +903,7 @@ fail_unlock:
        spin_unlock_irq(q->queue_lock);
        rcu_read_unlock();
 fail:
-       owner = disk->fops->owner;
-       put_disk(disk);
-       module_put(owner);
+       put_disk_and_module(disk);
        /*
         * If queue was bypassing, we should retry.  Do so after a
         * short msleep().  It isn't strictly necessary but queue
@@ -931,13 +928,9 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep);
 void blkg_conf_finish(struct blkg_conf_ctx *ctx)
        __releases(ctx->disk->queue->queue_lock) __releases(rcu)
 {
-       struct module *owner;
-
        spin_unlock_irq(ctx->disk->queue->queue_lock);
        rcu_read_unlock();
-       owner = ctx->disk->fops->owner;
-       put_disk(ctx->disk);
-       module_put(owner);
+       put_disk_and_module(ctx->disk);
 }
 EXPORT_SYMBOL_GPL(blkg_conf_finish);
 
index 2d1a7bbe063437bfacfca43ad479c305fccf56c7..6d82c4f7fadd9466f84a2405352f8296597eaa09 100644 (file)
@@ -2434,7 +2434,7 @@ blk_qc_t submit_bio(struct bio *bio)
                unsigned int count;
 
                if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
-                       count = queue_logical_block_size(bio->bi_disk->queue);
+                       count = queue_logical_block_size(bio->bi_disk->queue) >> 9;
                else
                        count = bio_sectors(bio);
 
index 357492712b0ea85362d2bbd6b2aa1687459cba66..16e83e6df404a24fd1a59baeb77b9c7b7cc9890c 100644 (file)
@@ -712,7 +712,6 @@ static void __blk_mq_requeue_request(struct request *rq)
 
        trace_block_rq_requeue(q, rq);
        wbt_requeue(q->rq_wb, &rq->issue_stat);
-       blk_mq_sched_requeue_request(rq);
 
        if (blk_mq_rq_state(rq) != MQ_RQ_IDLE) {
                blk_mq_rq_update_state(rq, MQ_RQ_IDLE);
@@ -725,6 +724,9 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list)
 {
        __blk_mq_requeue_request(rq);
 
+       /* this request will be re-inserted to io scheduler queue */
+       blk_mq_sched_requeue_request(rq);
+
        BUG_ON(blk_queued_rq(rq));
        blk_mq_add_to_requeue_list(rq, true, kick_requeue_list);
 }
index 88a53c188cb7338e74a9a55a44d8d0e5a2a758da..9656f9e9f99e20af13f1e175aba15f9447d9ef87 100644 (file)
@@ -547,7 +547,7 @@ static int exact_lock(dev_t devt, void *data)
 {
        struct gendisk *p = data;
 
-       if (!get_disk(p))
+       if (!get_disk_and_module(p))
                return -1;
        return 0;
 }
@@ -717,6 +717,11 @@ void del_gendisk(struct gendisk *disk)
        blk_integrity_del(disk);
        disk_del_events(disk);
 
+       /*
+        * Block lookups of the disk until all bdevs are unhashed and the
+        * disk is marked as dead (GENHD_FL_UP cleared).
+        */
+       down_write(&disk->lookup_sem);
        /* invalidate stuff */
        disk_part_iter_init(&piter, disk,
                             DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE);
@@ -731,6 +736,7 @@ void del_gendisk(struct gendisk *disk)
        bdev_unhash_inode(disk_devt(disk));
        set_capacity(disk, 0);
        disk->flags &= ~GENHD_FL_UP;
+       up_write(&disk->lookup_sem);
 
        if (!(disk->flags & GENHD_FL_HIDDEN))
                sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
@@ -809,16 +815,28 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
 
                spin_lock_bh(&ext_devt_lock);
                part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
-               if (part && get_disk(part_to_disk(part))) {
+               if (part && get_disk_and_module(part_to_disk(part))) {
                        *partno = part->partno;
                        disk = part_to_disk(part);
                }
                spin_unlock_bh(&ext_devt_lock);
        }
 
-       if (disk && unlikely(disk->flags & GENHD_FL_HIDDEN)) {
-               put_disk(disk);
+       if (!disk)
+               return NULL;
+
+       /*
+        * Synchronize with del_gendisk() to not return disk that is being
+        * destroyed.
+        */
+       down_read(&disk->lookup_sem);
+       if (unlikely((disk->flags & GENHD_FL_HIDDEN) ||
+                    !(disk->flags & GENHD_FL_UP))) {
+               up_read(&disk->lookup_sem);
+               put_disk_and_module(disk);
                disk = NULL;
+       } else {
+               up_read(&disk->lookup_sem);
        }
        return disk;
 }
@@ -1418,6 +1436,7 @@ struct gendisk *__alloc_disk_node(int minors, int node_id)
                        kfree(disk);
                        return NULL;
                }
+               init_rwsem(&disk->lookup_sem);
                disk->node_id = node_id;
                if (disk_expand_part_tbl(disk, 0)) {
                        free_part_stats(&disk->part0);
@@ -1453,7 +1472,7 @@ struct gendisk *__alloc_disk_node(int minors, int node_id)
 }
 EXPORT_SYMBOL(__alloc_disk_node);
 
-struct kobject *get_disk(struct gendisk *disk)
+struct kobject *get_disk_and_module(struct gendisk *disk)
 {
        struct module *owner;
        struct kobject *kobj;
@@ -1471,17 +1490,30 @@ struct kobject *get_disk(struct gendisk *disk)
        return kobj;
 
 }
-
-EXPORT_SYMBOL(get_disk);
+EXPORT_SYMBOL(get_disk_and_module);
 
 void put_disk(struct gendisk *disk)
 {
        if (disk)
                kobject_put(&disk_to_dev(disk)->kobj);
 }
-
 EXPORT_SYMBOL(put_disk);
 
+/*
+ * This is a counterpart of get_disk_and_module() and thus also of
+ * get_gendisk().
+ */
+void put_disk_and_module(struct gendisk *disk)
+{
+       if (disk) {
+               struct module *owner = disk->fops->owner;
+
+               put_disk(disk);
+               module_put(owner);
+       }
+}
+EXPORT_SYMBOL(put_disk_and_module);
+
 static void set_disk_ro_uevent(struct gendisk *gd, int ro)
 {
        char event[] = "DISK_RO=1";
index 1668506d8ed80607b6e3c279fa22195fb73571de..3884d810efd27fc73bb07659b91296ea46265252 100644 (file)
@@ -225,7 +225,7 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
 
        if (start + len > i_size_read(bdev->bd_inode))
                return -EINVAL;
-       truncate_inode_pages_range(mapping, start, start + len);
+       truncate_inode_pages_range(mapping, start, start + len - 1);
        return blkdev_issue_discard(bdev, start >> 9, len >> 9,
                                    GFP_KERNEL, flags);
 }
index f95c60774ce8ca613417d3ccf54bee52010752ee..0d6d25e32e1f44fda0049bb3e213b85a3debfa1f 100644 (file)
@@ -833,6 +833,7 @@ static struct elevator_type kyber_sched = {
                .limit_depth = kyber_limit_depth,
                .prepare_request = kyber_prepare_request,
                .finish_request = kyber_finish_request,
+               .requeue_request = kyber_finish_request,
                .completed_request = kyber_completed_request,
                .dispatch_request = kyber_dispatch_request,
                .has_work = kyber_has_work,
index c56f211c84400662f3e18c137b51c3f5406e20fd..8ec0ba9f538619f177eef3416711689323161a65 100644 (file)
@@ -535,13 +535,22 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
        spin_unlock(&dd->lock);
 }
 
+/*
+ * Nothing to do here. This is defined only to ensure that .finish_request
+ * method is called upon request completion.
+ */
+static void dd_prepare_request(struct request *rq, struct bio *bio)
+{
+}
+
 /*
  * For zoned block devices, write unlock the target zone of
  * completed write requests. Do this while holding the zone lock
  * spinlock so that the zone is never unlocked while deadline_fifo_request()
- * while deadline_next_request() are executing.
+ * or deadline_next_request() are executing. This function is called for
+ * all requests, whether or not these requests complete successfully.
  */
-static void dd_completed_request(struct request *rq)
+static void dd_finish_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
@@ -756,7 +765,8 @@ static struct elevator_type mq_deadline = {
        .ops.mq = {
                .insert_requests        = dd_insert_requests,
                .dispatch_request       = dd_dispatch_request,
-               .completed_request      = dd_completed_request,
+               .prepare_request        = dd_prepare_request,
+               .finish_request         = dd_finish_request,
                .next_request           = elv_rb_latter_request,
                .former_request         = elv_rb_former_request,
                .bio_merge              = dd_bio_merge,
index 91622db9aedffd997947642a5872802312346869..08dabcd8b6aefc6844bbb9d9e9c001e6ff71fb33 100644 (file)
@@ -51,6 +51,12 @@ const char *bdevname(struct block_device *bdev, char *buf)
 
 EXPORT_SYMBOL(bdevname);
 
+const char *bio_devname(struct bio *bio, char *buf)
+{
+       return disk_name(bio->bi_disk, bio->bi_partno, buf);
+}
+EXPORT_SYMBOL(bio_devname);
+
 /*
  * There's very little reason to use this, you should really
  * have a struct block_device just about everywhere and use
index e5aa62fcf5a8380d02866b7d9c31aa0a72f6573e..3aaf6af3ec23d7d54d5f45deb97ede64bec7d3db 100644 (file)
@@ -1758,7 +1758,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
        if (unit[drive].type->code == FD_NODRIVE)
                return NULL;
        *part = 0;
-       return get_disk(unit[drive].gendisk);
+       return get_disk_and_module(unit[drive].gendisk);
 }
 
 static int __init amiga_floppy_probe(struct platform_device *pdev)
index 8bc3b9fd8dd2be0df64d166dbc4c2b65eef03305..dfb2c2622e5a64d77e85ca9d14059c25f1840878 100644 (file)
@@ -1917,7 +1917,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
        if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
                return NULL;
        *part = 0;
-       return get_disk(unit[drive].disk);
+       return get_disk_and_module(unit[drive].disk);
 }
 
 static int __init atari_floppy_init (void)
index 8028a3a7e7fd63cabb8ce47c021e90e26d09a7ba..deea78e485da05e90436d78c334da2b40e9c6bce 100644 (file)
@@ -456,7 +456,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data)
 
        mutex_lock(&brd_devices_mutex);
        brd = brd_init_one(MINOR(dev) / max_part, &new);
-       kobj = brd ? get_disk(brd->brd_disk) : NULL;
+       kobj = brd ? get_disk_and_module(brd->brd_disk) : NULL;
        mutex_unlock(&brd_devices_mutex);
 
        if (new)
index eae484acfbbc1d4c8228b5524b4d30070793620a..8ec7235fc93be49c48291725aec29f2c36818ade 100644 (file)
@@ -4505,7 +4505,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
        if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
        *part = 0;
-       return get_disk(disks[drive]);
+       return get_disk_and_module(disks[drive]);
 }
 
 static int __init do_floppy_init(void)
index d5fe720cf14940b668f8764de2bad6cf95549528..87855b5123a6307cb014f78af2ae07b43ef77cf4 100644 (file)
@@ -1922,7 +1922,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
        if (err < 0)
                kobj = NULL;
        else
-               kobj = get_disk(lo->lo_disk);
+               kobj = get_disk_and_module(lo->lo_disk);
        mutex_unlock(&loop_index_mutex);
 
        *part = 0;
index 5f2a4240a204d54fc6fe87e569dc6165d5190530..86258b00a1d4d1960a67fb021babc668884a72a7 100644 (file)
@@ -1591,7 +1591,7 @@ again:
                        if (new_index < 0) {
                                mutex_unlock(&nbd_index_mutex);
                                printk(KERN_ERR "nbd: failed to add new device\n");
-                               return ret;
+                               return new_index;
                        }
                        nbd = idr_find(&nbd_index_idr, new_index);
                }
index 531a0915066b313462d6208359ecea4102397215..c61d20c9f3f8092f3aed69d859f137e7d67aef33 100644 (file)
@@ -1122,7 +1122,7 @@ static int pkt_start_recovery(struct packet_data *pkt)
        pkt->sector = new_sector;
 
        bio_reset(pkt->bio);
-       bio_set_set(pkt->bio, pd->bdev);
+       bio_set_dev(pkt->bio, pd->bdev);
        bio_set_op_attrs(pkt->bio, REQ_OP_WRITE, 0);
        pkt->bio->bi_iter.bi_sector = new_sector;
        pkt->bio->bi_iter.bi_size = pkt->frames * CD_FRAMESIZE;
index 84434d3ea19b8f3a7500972219b952a6b84072a2..64e066eba72e03abec38d49036d0f3677aafb2a3 100644 (file)
@@ -799,7 +799,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
                return NULL;
 
        *part = 0;
-       return get_disk(swd->unit[drive].disk);
+       return get_disk_and_module(swd->unit[drive].disk);
 }
 
 static int swim_add_floppy(struct swim_priv *swd, enum drive_location location)
index 41c95c9b2ab436e5917eb6f83f055b91ee521044..8f9130ab5887273d8feba518fabb76524fa7b579 100644 (file)
@@ -332,7 +332,7 @@ static const struct block_device_operations z2_fops =
 static struct kobject *z2_find(dev_t dev, int *part, void *data)
 {
        *part = 0;
-       return get_disk(z2ram_gendisk);
+       return get_disk_and_module(z2ram_gendisk);
 }
 
 static struct request_queue *z2_queue;
index 4d46003c46cfe5f4599a17cf726cb3d86fd8399c..cdaeeea7999cd20759dca0d5cd7f88a3ff431440 100644 (file)
@@ -630,7 +630,7 @@ static int sysc_init_dts_quirks(struct sysc *ddata)
        for (i = 0; i < ARRAY_SIZE(sysc_dts_quirks); i++) {
                prop = of_get_property(np, sysc_dts_quirks[i].name, &len);
                if (!prop)
-                       break;
+                       continue;
 
                ddata->cfg.quirks |= sysc_dts_quirks[i].mask;
        }
index 4d1dc8b46877ca497a198a3d988d060b9235100a..f95b9c75175bcf27825b16891ca405886e51c379 100644 (file)
@@ -457,7 +457,7 @@ static int st33zp24_recv(struct tpm_chip *chip, unsigned char *buf,
                            size_t count)
 {
        int size = 0;
-       int expected;
+       u32 expected;
 
        if (!chip)
                return -EBUSY;
@@ -474,7 +474,7 @@ static int st33zp24_recv(struct tpm_chip *chip, unsigned char *buf,
        }
 
        expected = be32_to_cpu(*(__be32 *)(buf + 2));
-       if (expected > count) {
+       if (expected > count || expected < TPM_HEADER_SIZE) {
                size = -EIO;
                goto out;
        }
index 76df4fbcf089c2371b2ad8b08f31bf446b5c488b..9e80a953d6933ea05668636b6abcd444eff72b0a 100644 (file)
@@ -1190,6 +1190,10 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
                        break;
 
                recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+               if (recd > num_bytes) {
+                       total = -EFAULT;
+                       break;
+               }
 
                rlength = be32_to_cpu(tpm_cmd.header.out.length);
                if (rlength < offsetof(struct tpm_getrandom_out, rng_data) +
index c17e75348a991e355236f2040f931e940541049f..a700f8f9ead797df39de4b5ef946fb5c2c65c95b 100644 (file)
@@ -683,6 +683,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
        if (!rc) {
                data_len = be16_to_cpup(
                        (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
+               if (data_len < MIN_KEY_SIZE ||  data_len > MAX_KEY_SIZE + 1) {
+                       rc = -EFAULT;
+                       goto out;
+               }
 
                rlength = be32_to_cpu(((struct tpm2_cmd *)&buf)
                                        ->header.out.length);
index c1dd39eaaeebb1f474d2d9f8b0d1e98e3559f27f..6116cd05e2287999c69ea4c5432098f159a44379 100644 (file)
@@ -473,7 +473,8 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
 static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 {
        int size = 0;
-       int expected, status;
+       int status;
+       u32 expected;
 
        if (count < TPM_HEADER_SIZE) {
                size = -EIO;
@@ -488,7 +489,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
        }
 
        expected = be32_to_cpu(*(__be32 *)(buf + 2));
-       if ((size_t) expected > count) {
+       if (((size_t) expected > count) || (expected < TPM_HEADER_SIZE)) {
                size = -EIO;
                goto out;
        }
index c6428771841f814a891719fab16e92d7e0723fc7..caa86b19c76dd7007a3975756dec8fe069a31db3 100644 (file)
@@ -281,7 +281,11 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
        struct device *dev = chip->dev.parent;
        struct i2c_client *client = to_i2c_client(dev);
        s32 rc;
-       int expected, status, burst_count, retries, size = 0;
+       int status;
+       int burst_count;
+       int retries;
+       int size = 0;
+       u32 expected;
 
        if (count < TPM_HEADER_SIZE) {
                i2c_nuvoton_ready(chip);    /* return to idle */
@@ -323,7 +327,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
                 * to machine native
                 */
                expected = be32_to_cpu(*(__be32 *) (buf + 2));
-               if (expected > count) {
+               if (expected > count || expected < size) {
                        dev_err(dev, "%s() expected > count\n", __func__);
                        size = -EIO;
                        continue;
index 183a5f54d875d072b98e7aead6563f3dd3d95a62..da074e3db19be5c895f80a403aabb992e9a14d29 100644 (file)
@@ -270,7 +270,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        int size = 0;
-       int expected, status;
+       int status;
+       u32 expected;
 
        if (count < TPM_HEADER_SIZE) {
                size = -EIO;
@@ -285,7 +286,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
        }
 
        expected = be32_to_cpu(*(__be32 *) (buf + 2));
-       if (expected > count) {
+       if (expected > count || expected < TPM_HEADER_SIZE) {
                size = -EIO;
                goto out;
        }
index 3a88e33b0cfed86e487888bc203d9823fcdeb9c0..fb586e09682d84704a28748673cdc4c571c28105 100644 (file)
@@ -44,10 +44,10 @@ config ARM_DT_BL_CPUFREQ
 
 config ARM_SCPI_CPUFREQ
        tristate "SCPI based CPUfreq driver"
-       depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
+       depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
        help
-         This adds the CPUfreq driver support for ARM big.LITTLE platforms
-         using SCPI protocol for CPU power management.
+         This adds the CPUfreq driver support for ARM platforms using SCPI
+         protocol for CPU power management.
 
          This driver uses SCPI Message Protocol driver to interact with the
          firmware providing the CPU DVFS functionality.
index 7b596fa38ad2de4b7d9cf075ce69a876b4f2e35f..6bebc1f9f55aa65dc1718e47ddea4c0439b42cb0 100644 (file)
@@ -351,7 +351,13 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
 static int s3c_cpufreq_init(struct cpufreq_policy *policy)
 {
        policy->clk = clk_arm;
-       return cpufreq_generic_init(policy, ftab, cpu_cur.info->latency);
+
+       policy->cpuinfo.transition_latency = cpu_cur.info->latency;
+
+       if (ftab)
+               return cpufreq_table_validate_and_show(policy, ftab);
+
+       return 0;
 }
 
 static int __init s3c_cpufreq_initclks(void)
index c32a833e1b00542fd3f49bf758e96f57ee6fa478..d300a163945f53476b4a751f3c208d423717d55f 100644 (file)
@@ -51,15 +51,23 @@ static unsigned int scpi_cpufreq_get_rate(unsigned int cpu)
 static int
 scpi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
 {
+       unsigned long freq = policy->freq_table[index].frequency;
        struct scpi_data *priv = policy->driver_data;
-       u64 rate = policy->freq_table[index].frequency * 1000;
+       u64 rate = freq * 1000;
        int ret;
 
        ret = clk_set_rate(priv->clk, rate);
-       if (!ret && (clk_get_rate(priv->clk) != rate))
-               ret = -EIO;
 
-       return ret;
+       if (ret)
+               return ret;
+
+       if (clk_get_rate(priv->clk) != rate)
+               return -EIO;
+
+       arch_set_freq_scale(policy->related_cpus, freq,
+                           policy->cpuinfo.max_freq);
+
+       return 0;
 }
 
 static int
index fcfa5b1eae6169b44398b20442d95532d924821c..b3afb6cc9d72278b35eadb239e280b5aa311c3f9 100644 (file)
@@ -211,7 +211,7 @@ static int __sev_platform_shutdown_locked(int *error)
 {
        int ret;
 
-       ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, 0, error);
+       ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error);
        if (ret)
                return ret;
 
@@ -271,7 +271,7 @@ static int sev_ioctl_do_reset(struct sev_issue_cmd *argp)
                        return rc;
        }
 
-       return __sev_do_cmd_locked(SEV_CMD_FACTORY_RESET, 0, &argp->error);
+       return __sev_do_cmd_locked(SEV_CMD_FACTORY_RESET, NULL, &argp->error);
 }
 
 static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)
@@ -299,7 +299,7 @@ static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)
                        return rc;
        }
 
-       return __sev_do_cmd_locked(cmd, 0, &argp->error);
+       return __sev_do_cmd_locked(cmd, NULL, &argp->error);
 }
 
 static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp)
@@ -624,7 +624,7 @@ EXPORT_SYMBOL_GPL(sev_guest_decommission);
 
 int sev_guest_df_flush(int *error)
 {
-       return sev_do_cmd(SEV_CMD_DF_FLUSH, 0, error);
+       return sev_do_cmd(SEV_CMD_DF_FLUSH, NULL, error);
 }
 EXPORT_SYMBOL_GPL(sev_guest_df_flush);
 
index f34430f99fd805414085fea26540f3c152dd6b0c..872100215ca00f0f4703c025b8e52e637c85c710 100644 (file)
@@ -279,7 +279,7 @@ static const u32 correrrthrsld[] = {
  * sbridge structs
  */
 
-#define NUM_CHANNELS           4       /* Max channels per MC */
+#define NUM_CHANNELS           6       /* Max channels per MC */
 #define MAX_DIMMS              3       /* Max DIMMS per channel */
 #define KNL_MAX_CHAS           38      /* KNL max num. of Cache Home Agents */
 #define KNL_MAX_CHANNELS       6       /* KNL max num. of PCI channels */
index 564bb7a31da43b4e924daf7501c36ec9a4eb8fc2..84e5a9df234433b430fc950a04d80dc9cd43bad8 100644 (file)
@@ -241,6 +241,19 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
 
                desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
                                                &of_flags);
+               /*
+                * -EPROBE_DEFER in our case means that we found a
+                * valid GPIO property, but no controller has been
+                * registered so far.
+                *
+                * This means we don't need to look any further for
+                * alternate name conventions, and we should really
+                * preserve the return code for our user to be able to
+                * retry probing later.
+                */
+               if (IS_ERR(desc) && PTR_ERR(desc) == -EPROBE_DEFER)
+                       return desc;
+
                if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
                        break;
        }
@@ -250,7 +263,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
                desc = of_find_spi_gpio(dev, con_id, &of_flags);
 
        /* Special handling for regulator GPIOs if used */
-       if (IS_ERR(desc))
+       if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
                desc = of_find_regulator_gpio(dev, con_id, &of_flags);
 
        if (IS_ERR(desc))
index d5a2eefd6c3e9c634597dba673a6ee25a60c830d..74edba18b1596504ab76a45e71146dc7084e6c13 100644 (file)
@@ -1156,7 +1156,7 @@ static inline void amdgpu_set_ib_value(struct amdgpu_cs_parser *p,
 /*
  * Writeback
  */
-#define AMDGPU_MAX_WB 512      /* Reserve at most 512 WB slots for amdgpu-owned rings. */
+#define AMDGPU_MAX_WB 128      /* Reserve at most 128 WB slots for amdgpu-owned rings. */
 
 struct amdgpu_wb {
        struct amdgpu_bo        *wb_obj;
index 00a50cc5ec9a31a77b7476020e5f47089c83c5de..af1b879a9ee9bf38b30e3394715d764dc55aaee0 100644 (file)
@@ -492,7 +492,7 @@ static int amdgpu_device_wb_init(struct amdgpu_device *adev)
                memset(&adev->wb.used, 0, sizeof(adev->wb.used));
 
                /* clear wb memory */
-               memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t));
+               memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
        }
 
        return 0;
@@ -530,8 +530,9 @@ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
  */
 void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
 {
+       wb >>= 3;
        if (wb < adev->wb.num_wb)
-               __clear_bit(wb >> 3, adev->wb.used);
+               __clear_bit(wb, adev->wb.used);
 }
 
 /**
@@ -1455,11 +1456,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.hw)
                        continue;
-               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
-                       amdgpu_free_static_csa(adev);
-                       amdgpu_device_wb_fini(adev);
-                       amdgpu_device_vram_scratch_fini(adev);
-               }
 
                if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
                        adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
@@ -1486,6 +1482,13 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_blocks[i].status.sw)
                        continue;
+
+               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
+                       amdgpu_free_static_csa(adev);
+                       amdgpu_device_wb_fini(adev);
+                       amdgpu_device_vram_scratch_fini(adev);
+               }
+
                r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);
                /* XXX handle errors */
                if (r) {
@@ -2284,14 +2287,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
                        }
                        drm_modeset_unlock_all(dev);
-               } else {
-                       /*
-                        * There is no equivalent atomic helper to turn on
-                        * display, so we defined our own function for this,
-                        * once suspend resume is supported by the atomic
-                        * framework this will be reworked
-                        */
-                       amdgpu_dm_display_resume(adev);
                }
        }
 
@@ -2726,7 +2721,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        if (amdgpu_device_has_dc_support(adev)) {
                if (drm_atomic_helper_resume(adev->ddev, state))
                        dev_info(adev->dev, "drm resume failed:%d\n", r);
-               amdgpu_dm_display_resume(adev);
        } else {
                drm_helper_resume_force_mode(adev->ddev);
        }
index e14ab34d8262418084abdafe4015ad5ddee5c0a7..7c2be32c5aea6fd55a5747fd22d80e913d356c1c 100644 (file)
@@ -75,7 +75,7 @@ static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man,
 static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man)
 {
        struct amdgpu_gtt_mgr *mgr = man->priv;
-
+       spin_lock(&mgr->lock);
        drm_mm_takedown(&mgr->mm);
        spin_unlock(&mgr->lock);
        kfree(mgr);
index 56bcd59c3399a0a912ea1fa8f869c105b8827327..36483e0d3c9729e555163e9f9a0b1cfe7dc319a8 100644 (file)
@@ -257,7 +257,8 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
        r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq);
        if (r) {
                adev->irq.installed = false;
-               flush_work(&adev->hotplug_work);
+               if (!amdgpu_device_has_dc_support(adev))
+                       flush_work(&adev->hotplug_work);
                cancel_work_sync(&adev->reset_work);
                return r;
        }
@@ -282,7 +283,8 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)
                adev->irq.installed = false;
                if (adev->irq.msi_enabled)
                        pci_disable_msi(adev->pdev);
-               flush_work(&adev->hotplug_work);
+               if (!amdgpu_device_has_dc_support(adev))
+                       flush_work(&adev->hotplug_work);
                cancel_work_sync(&adev->reset_work);
        }
 
index 2719937e09d6bf00a4f78c47cd970ce5f5a51000..3b7e7af09ead1b8ea7ec8168b1252e71baaccb57 100644 (file)
@@ -634,7 +634,7 @@ static int gmc_v9_0_late_init(void *handle)
        for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i)
                BUG_ON(vm_inv_eng[i] > 16);
 
-       if (adev->asic_type == CHIP_VEGA10) {
+       if (adev->asic_type == CHIP_VEGA10 && !amdgpu_sriov_vf(adev)) {
                r = gmc_v9_0_ecc_available(adev);
                if (r == 1) {
                        DRM_INFO("ECC is active.\n");
@@ -682,7 +682,10 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
        adev->mc.vram_width = amdgpu_atomfirmware_get_vram_width(adev);
        if (!adev->mc.vram_width) {
                /* hbm memory channel size */
-               chansize = 128;
+               if (adev->flags & AMD_IS_APU)
+                       chansize = 64;
+               else
+                       chansize = 128;
 
                tmp = RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0);
                tmp &= DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK;
index e92fb372bc99738dad957334ba40d3a138c57636..91cf95a8c39c832d50b378bf7464a99f19c839c8 100644 (file)
@@ -238,31 +238,27 @@ static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring)
 static uint64_t sdma_v4_0_ring_get_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
-       u64 *wptr = NULL;
-       uint64_t local_wptr = 0;
+       u64 wptr;
 
        if (ring->use_doorbell) {
                /* XXX check if swapping is necessary on BE */
-               wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]);
-               DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr);
-               *wptr = (*wptr) >> 2;
-               DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr);
+               wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs]));
+               DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);
        } else {
                u32 lowbit, highbit;
                int me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1;
 
-               wptr = &local_wptr;
                lowbit = RREG32(sdma_v4_0_get_reg_offset(adev, me, mmSDMA0_GFX_RB_WPTR)) >> 2;
                highbit = RREG32(sdma_v4_0_get_reg_offset(adev, me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;
 
                DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",
                                me, highbit, lowbit);
-               *wptr = highbit;
-               *wptr = (*wptr) << 32;
-               *wptr |= lowbit;
+               wptr = highbit;
+               wptr = wptr << 32;
+               wptr |= lowbit;
        }
 
-       return *wptr;
+       return wptr >> 2;
 }
 
 /**
index b2bfedaf57f197b38e98dce034d12c1d3359ca64..9bab4842cd4411f8e282c083f526937b2979f6a0 100644 (file)
@@ -1618,7 +1618,7 @@ static const struct amdgpu_ring_funcs uvd_v6_0_enc_ring_vm_funcs = {
        .set_wptr = uvd_v6_0_enc_ring_set_wptr,
        .emit_frame_size =
                4 + /* uvd_v6_0_enc_ring_emit_pipeline_sync */
-               6 + /* uvd_v6_0_enc_ring_emit_vm_flush */
+               5 + /* uvd_v6_0_enc_ring_emit_vm_flush */
                5 + 5 + /* uvd_v6_0_enc_ring_emit_fence x2 vm fence */
                1, /* uvd_v6_0_enc_ring_insert_end */
        .emit_ib_size = 5, /* uvd_v6_0_enc_ring_emit_ib */
index 1ce4c98385e3a17385a00b076a699cd64462d4dd..862835dc054e1ce66c76f114c5c9ccc2cf098d38 100644 (file)
@@ -629,11 +629,13 @@ static int dm_resume(void *handle)
 {
        struct amdgpu_device *adev = handle;
        struct amdgpu_display_manager *dm = &adev->dm;
+       int ret = 0;
 
        /* power on hardware */
        dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
 
-       return 0;
+       ret = amdgpu_dm_display_resume(adev);
+       return ret;
 }
 
 int amdgpu_dm_display_resume(struct amdgpu_device *adev)
index 33d91e4474ea174f9bd7c48f35a5fe94d6b593b4..639421a00ab629eefce3b7333126632f4d2b0848 100644 (file)
@@ -1465,7 +1465,7 @@ void decide_link_settings(struct dc_stream_state *stream,
        /* MST doesn't perform link training for now
         * TODO: add MST specific link training routine
         */
-       if (is_mst_supported(link)) {
+       if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
                *link_setting = link->verified_link_cap;
                return;
        }
index 261811e0c094a81a0a1c0c1c6420f83d4db4a3bc..539c3e0a62922b7c7b774a1d8a115d6fcc4ab2b4 100644 (file)
@@ -197,7 +197,8 @@ bool dc_stream_set_cursor_attributes(
        for (i = 0; i < MAX_PIPES; i++) {
                struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
 
-               if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
+               if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm &&
+                   !pipe_ctx->plane_res.dpp) || !pipe_ctx->plane_res.ipp)
                        continue;
                if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
                        continue;
@@ -273,7 +274,8 @@ bool dc_stream_set_cursor_position(
                if (pipe_ctx->stream != stream ||
                                (!pipe_ctx->plane_res.mi  && !pipe_ctx->plane_res.hubp) ||
                                !pipe_ctx->plane_state ||
-                               (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
+                               (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) ||
+                               !pipe_ctx->plane_res.ipp)
                        continue;
 
                if (pipe_ctx->plane_state->address.type
index 41e42beff213905837c15db1841800b2021ec502..08e8a793714f26dc38e571a51b52f8421bb72444 100644 (file)
@@ -2756,10 +2756,13 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
                                    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
 
 
-       disable_mclk_switching = ((1 < info.display_count) ||
-                                 disable_mclk_switching_for_frame_lock ||
-                                 smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) ||
-                                 (mode_info.refresh_rate > 120));
+       if (info.display_count == 0)
+               disable_mclk_switching = false;
+       else
+               disable_mclk_switching = ((1 < info.display_count) ||
+                                         disable_mclk_switching_for_frame_lock ||
+                                         smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) ||
+                                         (mode_info.refresh_rate > 120));
 
        sclk = smu7_ps->performance_levels[0].engine_clock;
        mclk = smu7_ps->performance_levels[0].memory_clock;
@@ -4534,13 +4537,6 @@ static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr,
        int tmp_result, result = 0;
        uint32_t sclk_mask = 0, mclk_mask = 0;
 
-       if (hwmgr->chip_id == CHIP_FIJI) {
-               if (request->type == AMD_PP_GFX_PROFILE)
-                       smu7_enable_power_containment(hwmgr);
-               else if (request->type == AMD_PP_COMPUTE_PROFILE)
-                       smu7_disable_power_containment(hwmgr);
-       }
-
        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)
                return -EINVAL;
 
index 2d55dabc77d4112d0b1c50bf1e1ae38ac0505dd0..5f9c3efb532f6c48471b75a0e5510369b98fffff 100644 (file)
@@ -3168,10 +3168,13 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
        disable_mclk_switching_for_vr = PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR);
        force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh);
 
-       disable_mclk_switching = (info.display_count > 1) ||
-                                   disable_mclk_switching_for_frame_lock ||
-                                   disable_mclk_switching_for_vr ||
-                                   force_mclk_high;
+       if (info.display_count == 0)
+               disable_mclk_switching = false;
+       else
+               disable_mclk_switching = (info.display_count > 1) ||
+                       disable_mclk_switching_for_frame_lock ||
+                       disable_mclk_switching_for_vr ||
+                       force_mclk_high;
 
        sclk = vega10_ps->performance_levels[0].gfx_clock;
        mclk = vega10_ps->performance_levels[0].mem_clock;
index 5a13ff29f4f04af99c61fa07261a35a44ac0dd8e..c0530a1af5e39da421b87ba14d1b5f31f1a864f6 100644 (file)
@@ -121,6 +121,10 @@ int drm_mode_addfb(struct drm_device *dev,
        r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
        r.handles[0] = or->handle;
 
+       if (r.pixel_format == DRM_FORMAT_XRGB2101010 &&
+           dev->driver->driver_features & DRIVER_PREFER_XBGR_30BPP)
+               r.pixel_format = DRM_FORMAT_XBGR2101010;
+
        ret = drm_mode_addfb2(dev, &r, file_priv);
        if (ret)
                return ret;
index 4401068ff468ad36aef1d5df5277e2f008f01bb3..3ab1ace2a6bdd8a4be32828e58262d9ef9e20ae7 100644 (file)
@@ -505,6 +505,8 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
                list_add_tail(&vma->exec_link, &eb->unbound);
                if (drm_mm_node_allocated(&vma->node))
                        err = i915_vma_unbind(vma);
+               if (unlikely(err))
+                       vma->exec_flags = NULL;
        }
        return err;
 }
@@ -2410,7 +2412,7 @@ err_request:
        if (out_fence) {
                if (err == 0) {
                        fd_install(out_fence_fd, out_fence->file);
-                       args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */
+                       args->rsvd2 &= GENMASK_ULL(31, 0); /* keep in-fence */
                        args->rsvd2 |= (u64)out_fence_fd << 32;
                        out_fence_fd = -1;
                } else {
index e09d18df8b7f18ca0b17f65797e5cbdc4baec072..a3e93d46316a267571f199cfcbd665434f41003f 100644 (file)
@@ -476,8 +476,6 @@ void __i915_gem_request_submit(struct drm_i915_gem_request *request)
        GEM_BUG_ON(!irqs_disabled());
        lockdep_assert_held(&engine->timeline->lock);
 
-       trace_i915_gem_request_execute(request);
-
        /* Transfer from per-context onto the global per-engine timeline */
        timeline = engine->timeline;
        GEM_BUG_ON(timeline == request->timeline);
@@ -501,6 +499,8 @@ void __i915_gem_request_submit(struct drm_i915_gem_request *request)
        list_move_tail(&request->link, &timeline->requests);
        spin_unlock(&request->timeline->lock);
 
+       trace_i915_gem_request_execute(request);
+
        wake_up_all(&request->execute);
 }
 
index a2108e35c599982831cab1eab39c6b6721af1d80..33eb0c5b1d3244d944a9e80fa883352952cb5ac0 100644 (file)
@@ -2027,7 +2027,7 @@ enum i915_power_well_id {
 #define _CNL_PORT_TX_DW5_LN0_AE                0x162454
 #define _CNL_PORT_TX_DW5_LN0_B         0x162654
 #define _CNL_PORT_TX_DW5_LN0_C         0x162C54
-#define _CNL_PORT_TX_DW5_LN0_D         0x162ED4
+#define _CNL_PORT_TX_DW5_LN0_D         0x162E54
 #define _CNL_PORT_TX_DW5_LN0_F         0x162854
 #define CNL_PORT_TX_DW5_GRP(port)      _MMIO_PORT6(port, \
                                                    _CNL_PORT_TX_DW5_GRP_AE, \
@@ -2058,7 +2058,7 @@ enum i915_power_well_id {
 #define _CNL_PORT_TX_DW7_LN0_AE                0x16245C
 #define _CNL_PORT_TX_DW7_LN0_B         0x16265C
 #define _CNL_PORT_TX_DW7_LN0_C         0x162C5C
-#define _CNL_PORT_TX_DW7_LN0_D         0x162EDC
+#define _CNL_PORT_TX_DW7_LN0_D         0x162E5C
 #define _CNL_PORT_TX_DW7_LN0_F         0x16285C
 #define CNL_PORT_TX_DW7_GRP(port)      _MMIO_PORT6(port, \
                                                    _CNL_PORT_TX_DW7_GRP_AE, \
index 522d54fecb53489193eb2b72dbf9fdd41009ac67..4a01f62a392dd18569ca0f3503c87bd1bbbe59b9 100644 (file)
@@ -779,11 +779,11 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
 {
        struct intel_encoder *encoder;
 
-       if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map)))
-               return NULL;
-
        /* MST */
        if (pipe >= 0) {
+               if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map)))
+                       return NULL;
+
                encoder = dev_priv->av_enc_map[pipe];
                /*
                 * when bootup, audio driver may not know it is
index dd8d4352ed998e7f09d36a981098edae84830808..caddce88d2d8b3e5eaf0528c609fc2a190c8294f 100644 (file)
@@ -4477,6 +4477,7 @@ nv50_display_create(struct drm_device *dev)
        nouveau_display(dev)->fini = nv50_display_fini;
        disp->disp = &nouveau_display(dev)->disp;
        dev->mode_config.funcs = &nv50_disp_func;
+       dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP;
        if (nouveau_atomic)
                dev->driver->driver_features |= DRIVER_ATOMIC;
 
index 8d3e3d2e0090938c2ec895d0836871622fad0bd7..7828a5e1062999b1bae507440b6dd8847095546b 100644 (file)
@@ -1365,6 +1365,10 @@ int radeon_device_init(struct radeon_device *rdev,
        if ((rdev->flags & RADEON_IS_PCI) &&
            (rdev->family <= CHIP_RS740))
                rdev->need_dma32 = true;
+#ifdef CONFIG_PPC64
+       if (rdev->family == CHIP_CEDAR)
+               rdev->need_dma32 = true;
+#endif
 
        dma_bits = rdev->need_dma32 ? 32 : 40;
        r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
index 326ad068c15aa63ef38a6c85fbcc368ad52bd801..4b6542538ff91581272deadb6e971c50f2429033 100644 (file)
@@ -47,7 +47,6 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev);
 static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
 static void radeon_pm_update_profile(struct radeon_device *rdev);
 static void radeon_pm_set_clocks(struct radeon_device *rdev);
-static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev);
 
 int radeon_pm_get_type_index(struct radeon_device *rdev,
                             enum radeon_pm_state_type ps_type,
@@ -80,8 +79,6 @@ void radeon_pm_acpi_event_handler(struct radeon_device *rdev)
                                radeon_dpm_enable_bapm(rdev, rdev->pm.dpm.ac_power);
                }
                mutex_unlock(&rdev->pm.mutex);
-               /* allow new DPM state to be picked */
-               radeon_pm_compute_clocks_dpm(rdev);
        } else if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                if (rdev->pm.profile == PM_PROFILE_AUTO) {
                        mutex_lock(&rdev->pm.mutex);
@@ -885,8 +882,7 @@ static struct radeon_ps *radeon_dpm_pick_power_state(struct radeon_device *rdev,
                dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF;
        /* balanced states don't exist at the moment */
        if (dpm_state == POWER_STATE_TYPE_BALANCED)
-               dpm_state = rdev->pm.dpm.ac_power ?
-                       POWER_STATE_TYPE_PERFORMANCE : POWER_STATE_TYPE_BATTERY;
+               dpm_state = POWER_STATE_TYPE_PERFORMANCE;
 
 restart_search:
        /* Pick the best power state based on current conditions */
index 3c15cf24b50360918253ed5bcff4d4a73a1e6cd0..b3960118deb9eb22da1134ca9525e0c87dc17275 100644 (file)
@@ -260,7 +260,7 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
                                        const struct drm_display_mode *mode)
 {
        /* Configure the dot clock */
-       clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+       clk_set_rate_exclusive(tcon->dclk, mode->crtc_clock * 1000);
 
        /* Set the resolution */
        regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
@@ -335,6 +335,9 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
        regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
                           SUN4I_TCON_GCTL_IOMAP_MASK,
                           SUN4I_TCON_GCTL_IOMAP_TCON0);
+
+       /* Enable the output on the pins */
+       regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
 }
 
 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
@@ -418,7 +421,7 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
        WARN_ON(!tcon->quirks->has_channel_1);
 
        /* Configure the dot clock */
-       clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
+       clk_set_rate_exclusive(tcon->sclk1, mode->crtc_clock * 1000);
 
        /* Adjust clock delay */
        clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
index 5720a0d4ac0a9ebf242755921bc1ac6fea8c2630..677ac16c8a6dea750e80ec914973344d972bb765 100644 (file)
@@ -197,6 +197,9 @@ static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
        case VIRTGPU_PARAM_3D_FEATURES:
                value = vgdev->has_virgl_3d == true ? 1 : 0;
                break;
+       case VIRTGPU_PARAM_CAPSET_QUERY_FIX:
+               value = 1;
+               break;
        default:
                return -EINVAL;
        }
@@ -472,7 +475,7 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
 {
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct drm_virtgpu_get_caps *args = data;
-       int size;
+       unsigned size, host_caps_size;
        int i;
        int found_valid = -1;
        int ret;
@@ -481,6 +484,10 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
        if (vgdev->num_capsets == 0)
                return -ENOSYS;
 
+       /* don't allow userspace to pass 0 */
+       if (args->size == 0)
+               return -EINVAL;
+
        spin_lock(&vgdev->display_info_lock);
        for (i = 0; i < vgdev->num_capsets; i++) {
                if (vgdev->capsets[i].id == args->cap_set_id) {
@@ -496,11 +503,9 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
                return -EINVAL;
        }
 
-       size = vgdev->capsets[found_valid].max_size;
-       if (args->size > size) {
-               spin_unlock(&vgdev->display_info_lock);
-               return -EINVAL;
-       }
+       host_caps_size = vgdev->capsets[found_valid].max_size;
+       /* only copy to user the minimum of the host caps size or the guest caps size */
+       size = min(args->size, host_caps_size);
 
        list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
                if (cache_ent->id == args->cap_set_id &&
index 17fd55af4d9247ee89c0b581c5de3ab3437860a2..caa20eb5f26b03c7e02569e54dbb599fd2e73ec1 100644 (file)
@@ -928,7 +928,7 @@ static int exact_lock(dev_t dev, void *data)
 {
        struct gendisk *p = data;
 
-       if (!get_disk(p))
+       if (!get_disk_and_module(p))
                return -1;
        return 0;
 }
index 1a46b41dac7018bbf43e1dc610abeacab21cb7a1..6422846b546ed27122dc277bd65568421e6986fc 100644 (file)
@@ -659,11 +659,11 @@ static void do_bio_hook(struct search *s, struct bio *orig_bio)
 static void search_free(struct closure *cl)
 {
        struct search *s = container_of(cl, struct search, cl);
-       bio_complete(s);
 
        if (s->iop.bio)
                bio_put(s->iop.bio);
 
+       bio_complete(s);
        closure_debug_destroy(cl);
        mempool_free(s, s->d->c->search);
 }
index 312895788036705cb0426d1af5b5662a4797faf3..4d1d8dfb2d2a4d1de7d6ee59e2b8d802a68827e5 100644 (file)
@@ -1274,7 +1274,7 @@ static int flash_devs_run(struct cache_set *c)
        struct uuid_entry *u;
 
        for (u = c->uuids;
-            u < c->uuids + c->devices_max_used && !ret;
+            u < c->uuids + c->nr_uuids && !ret;
             u++)
                if (UUID_FLASH_ONLY(u))
                        ret = flash_dev_run(c, u);
index e40065bdbfc84ef8455dbcc88d6a3208a6780571..0a7e99d62c69048d7000d3dc6bbcaa3320c742b5 100644 (file)
@@ -157,7 +157,7 @@ static void multipath_status(struct seq_file *seq, struct mddev *mddev)
                seq_printf (seq, "%s", rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
        }
        rcu_read_unlock();
-       seq_printf (seq, "]");
+       seq_putc(seq, ']');
 }
 
 static int multipath_congested(struct mddev *mddev, int bits)
index bc67ab6844f02d540cf4ae3725ebdad13ee568b8..254e44e44668f5fff8cc2d95bdb3b682450a204f 100644 (file)
@@ -801,6 +801,9 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
        struct bio *bio;
        int ff = 0;
 
+       if (!page)
+               return;
+
        if (test_bit(Faulty, &rdev->flags))
                return;
 
@@ -5452,6 +5455,7 @@ int md_run(struct mddev *mddev)
         * the only valid external interface is through the md
         * device.
         */
+       mddev->has_superblocks = false;
        rdev_for_each(rdev, mddev) {
                if (test_bit(Faulty, &rdev->flags))
                        continue;
@@ -5465,6 +5469,9 @@ int md_run(struct mddev *mddev)
                                set_disk_ro(mddev->gendisk, 1);
                }
 
+               if (rdev->sb_page)
+                       mddev->has_superblocks = true;
+
                /* perform some consistency tests on the device.
                 * We don't want the data to overlap the metadata,
                 * Internal Bitmap issues have been handled elsewhere.
@@ -5497,8 +5504,10 @@ int md_run(struct mddev *mddev)
        }
        if (mddev->sync_set == NULL) {
                mddev->sync_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
-               if (!mddev->sync_set)
-                       return -ENOMEM;
+               if (!mddev->sync_set) {
+                       err = -ENOMEM;
+                       goto abort;
+               }
        }
 
        spin_lock(&pers_lock);
@@ -5511,7 +5520,8 @@ int md_run(struct mddev *mddev)
                else
                        pr_warn("md: personality for level %s is not loaded!\n",
                                mddev->clevel);
-               return -EINVAL;
+               err = -EINVAL;
+               goto abort;
        }
        spin_unlock(&pers_lock);
        if (mddev->level != pers->level) {
@@ -5524,7 +5534,8 @@ int md_run(struct mddev *mddev)
            pers->start_reshape == NULL) {
                /* This personality cannot handle reshaping... */
                module_put(pers->owner);
-               return -EINVAL;
+               err = -EINVAL;
+               goto abort;
        }
 
        if (pers->sync_request) {
@@ -5593,7 +5604,7 @@ int md_run(struct mddev *mddev)
                mddev->private = NULL;
                module_put(pers->owner);
                bitmap_destroy(mddev);
-               return err;
+               goto abort;
        }
        if (mddev->queue) {
                bool nonrot = true;
@@ -5655,6 +5666,18 @@ int md_run(struct mddev *mddev)
        sysfs_notify_dirent_safe(mddev->sysfs_action);
        sysfs_notify(&mddev->kobj, NULL, "degraded");
        return 0;
+
+abort:
+       if (mddev->bio_set) {
+               bioset_free(mddev->bio_set);
+               mddev->bio_set = NULL;
+       }
+       if (mddev->sync_set) {
+               bioset_free(mddev->sync_set);
+               mddev->sync_set = NULL;
+       }
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(md_run);
 
@@ -8049,6 +8072,7 @@ EXPORT_SYMBOL(md_done_sync);
 bool md_write_start(struct mddev *mddev, struct bio *bi)
 {
        int did_change = 0;
+
        if (bio_data_dir(bi) != WRITE)
                return true;
 
@@ -8081,6 +8105,8 @@ bool md_write_start(struct mddev *mddev, struct bio *bi)
        rcu_read_unlock();
        if (did_change)
                sysfs_notify_dirent_safe(mddev->sysfs_state);
+       if (!mddev->has_superblocks)
+               return true;
        wait_event(mddev->sb_wait,
                   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) ||
                   mddev->suspended);
@@ -8543,6 +8569,19 @@ void md_do_sync(struct md_thread *thread)
        set_mask_bits(&mddev->sb_flags, 0,
                      BIT(MD_SB_CHANGE_PENDING) | BIT(MD_SB_CHANGE_DEVS));
 
+       if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+                       !test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
+                       mddev->delta_disks > 0 &&
+                       mddev->pers->finish_reshape &&
+                       mddev->pers->size &&
+                       mddev->queue) {
+               mddev_lock_nointr(mddev);
+               md_set_array_sectors(mddev, mddev->pers->size(mddev, 0, 0));
+               mddev_unlock(mddev);
+               set_capacity(mddev->gendisk, mddev->array_sectors);
+               revalidate_disk(mddev->gendisk);
+       }
+
        spin_lock(&mddev->lock);
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
                /* We completed so min/max setting can be forgotten if used. */
@@ -8569,6 +8608,10 @@ static int remove_and_add_spares(struct mddev *mddev,
        int removed = 0;
        bool remove_some = false;
 
+       if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+               /* Mustn't remove devices when resync thread is running */
+               return 0;
+
        rdev_for_each(rdev, mddev) {
                if ((this == NULL || rdev == this) &&
                    rdev->raid_disk >= 0 &&
index 58cd20a5e85edb1db853661dcd749d99682a796c..fbc925cce8107019dcc4b2aa5310c7d100431a46 100644 (file)
@@ -468,6 +468,8 @@ struct mddev {
        void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
        struct md_cluster_info          *cluster_info;
        unsigned int                    good_device_nr; /* good device num within cluster raid */
+
+       bool    has_superblocks:1;
 };
 
 enum recovery_flags {
index f978eddc7a21c8bd442c9b4afafb275ce2c17a2c..fe872dc6712ed0c5c00caa60e5f152876f0b1025 100644 (file)
@@ -1809,6 +1809,17 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                        struct md_rdev *repl =
                                conf->mirrors[conf->raid_disks + number].rdev;
                        freeze_array(conf, 0);
+                       if (atomic_read(&repl->nr_pending)) {
+                               /* It means that some queued IO of retry_list
+                                * hold repl. Thus, we cannot set replacement
+                                * as NULL, avoiding rdev NULL pointer
+                                * dereference in sync_request_write and
+                                * handle_write_finished.
+                                */
+                               err = -EBUSY;
+                               unfreeze_array(conf);
+                               goto abort;
+                       }
                        clear_bit(Replacement, &repl->flags);
                        p->rdev = repl;
                        conf->mirrors[conf->raid_disks + number].rdev = NULL;
index c7294e7557e038bf5248e8c8bf9ce84cb6afad58..eb84bc68e2fd4c31cc996bc4d399183cd852b8f2 100644 (file)
 #define BARRIER_BUCKETS_NR_BITS                (PAGE_SHIFT - ilog2(sizeof(atomic_t)))
 #define BARRIER_BUCKETS_NR             (1<<BARRIER_BUCKETS_NR_BITS)
 
+/* Note: raid1_info.rdev can be set to NULL asynchronously by raid1_remove_disk.
+ * There are three safe ways to access raid1_info.rdev.
+ * 1/ when holding mddev->reconfig_mutex
+ * 2/ when resync/recovery is known to be happening - i.e. in code that is
+ *    called as part of performing resync/recovery.
+ * 3/ while holding rcu_read_lock(), use rcu_dereference to get the pointer
+ *    and if it is non-NULL, increment rdev->nr_pending before dropping the
+ *    RCU lock.
+ * When .rdev is set to NULL, the nr_pending count checked again and if it has
+ * been incremented, the pointer is put back in .rdev.
+ */
+
 struct raid1_info {
        struct md_rdev  *rdev;
        sector_t        head_position;
index 99c9207899a777c615880f286a6f617ffc4a70bf..c5e6c60fc0d41b53a578874087ae87259e3ebcce 100644 (file)
@@ -141,7 +141,7 @@ static void r10bio_pool_free(void *r10_bio, void *data)
 #define RESYNC_WINDOW (1024*1024)
 /* maximum number of concurrent requests, memory permitting */
 #define RESYNC_DEPTH (32*1024*1024/RESYNC_BLOCK_SIZE)
-#define CLUSTER_RESYNC_WINDOW (16 * RESYNC_WINDOW)
+#define CLUSTER_RESYNC_WINDOW (32 * RESYNC_WINDOW)
 #define CLUSTER_RESYNC_WINDOW_SECTORS (CLUSTER_RESYNC_WINDOW >> 9)
 
 /*
@@ -2655,7 +2655,8 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
                for (m = 0; m < conf->copies; m++) {
                        int dev = r10_bio->devs[m].devnum;
                        rdev = conf->mirrors[dev].rdev;
-                       if (r10_bio->devs[m].bio == NULL)
+                       if (r10_bio->devs[m].bio == NULL ||
+                               r10_bio->devs[m].bio->bi_end_io == NULL)
                                continue;
                        if (!r10_bio->devs[m].bio->bi_status) {
                                rdev_clear_badblocks(
@@ -2670,7 +2671,8 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
                                        md_error(conf->mddev, rdev);
                        }
                        rdev = conf->mirrors[dev].replacement;
-                       if (r10_bio->devs[m].repl_bio == NULL)
+                       if (r10_bio->devs[m].repl_bio == NULL ||
+                               r10_bio->devs[m].repl_bio->bi_end_io == NULL)
                                continue;
 
                        if (!r10_bio->devs[m].repl_bio->bi_status) {
@@ -3782,7 +3784,7 @@ static int raid10_run(struct mddev *mddev)
                if (fc > 1 || fo > 0) {
                        pr_err("only near layout is supported by clustered"
                                " raid10\n");
-                       goto out;
+                       goto out_free_conf;
                }
        }
 
@@ -4830,17 +4832,11 @@ static void raid10_finish_reshape(struct mddev *mddev)
                return;
 
        if (mddev->delta_disks > 0) {
-               sector_t size = raid10_size(mddev, 0, 0);
-               md_set_array_sectors(mddev, size);
                if (mddev->recovery_cp > mddev->resync_max_sectors) {
                        mddev->recovery_cp = mddev->resync_max_sectors;
                        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                }
-               mddev->resync_max_sectors = size;
-               if (mddev->queue) {
-                       set_capacity(mddev->gendisk, mddev->array_sectors);
-                       revalidate_disk(mddev->gendisk);
-               }
+               mddev->resync_max_sectors = mddev->array_sectors;
        } else {
                int d;
                rcu_read_lock();
index db2ac22ac1b42801a14e5eab8641109a3aa61505..e2e8840de9bfab734e9238bc59ca8e9058c7de0b 100644 (file)
@@ -2,6 +2,19 @@
 #ifndef _RAID10_H
 #define _RAID10_H
 
+/* Note: raid10_info.rdev can be set to NULL asynchronously by
+ * raid10_remove_disk.
+ * There are three safe ways to access raid10_info.rdev.
+ * 1/ when holding mddev->reconfig_mutex
+ * 2/ when resync/recovery/reshape is known to be happening - i.e. in code
+ *    that is called as part of performing resync/recovery/reshape.
+ * 3/ while holding rcu_read_lock(), use rcu_dereference to get the pointer
+ *    and if it is non-NULL, increment rdev->nr_pending before dropping the
+ *    RCU lock.
+ * When .rdev is set to NULL, the nr_pending count checked again and if it has
+ * been incremented, the pointer is put back in .rdev.
+ */
+
 struct raid10_info {
        struct md_rdev  *rdev, *replacement;
        sector_t        head_position;
index 0c76bcedfc1cbd8b0af33008652095e3862f22c9..a001808a2b77da16bc2ae3c1d4aa32b5f944a939 100644 (file)
@@ -44,6 +44,7 @@ extern void ppl_write_stripe_run(struct r5conf *conf);
 extern void ppl_stripe_write_finished(struct stripe_head *sh);
 extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add);
 extern void ppl_quiesce(struct r5conf *conf, int quiesce);
+extern int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio);
 
 static inline bool raid5_has_ppl(struct r5conf *conf)
 {
@@ -104,7 +105,7 @@ static inline int log_handle_flush_request(struct r5conf *conf, struct bio *bio)
        if (conf->log)
                ret = r5l_handle_flush_request(conf->log, bio);
        else if (raid5_has_ppl(conf))
-               ret = 0;
+               ret = ppl_handle_flush_request(conf->log, bio);
 
        return ret;
 }
index 2764c2290062862a607dca9145ef8f0e24cb5d89..42890a08375bc73b6bcdba7961e9c88062dded5d 100644 (file)
@@ -693,6 +693,16 @@ void ppl_quiesce(struct r5conf *conf, int quiesce)
        }
 }
 
+int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio)
+{
+       if (bio->bi_iter.bi_size == 0) {
+               bio_endio(bio);
+               return 0;
+       }
+       bio->bi_opf &= ~REQ_PREFLUSH;
+       return -EAGAIN;
+}
+
 void ppl_stripe_write_finished(struct stripe_head *sh)
 {
        struct ppl_io_unit *io;
index 50d01144b80535e2e937c16021cdeeba632b201e..b5d2601483e34fa97fc8cfb7faeff6f014c0e035 100644 (file)
@@ -2196,15 +2196,16 @@ static int grow_one_stripe(struct r5conf *conf, gfp_t gfp)
 static int grow_stripes(struct r5conf *conf, int num)
 {
        struct kmem_cache *sc;
+       size_t namelen = sizeof(conf->cache_name[0]);
        int devs = max(conf->raid_disks, conf->previous_raid_disks);
 
        if (conf->mddev->gendisk)
-               sprintf(conf->cache_name[0],
+               snprintf(conf->cache_name[0], namelen,
                        "raid%d-%s", conf->level, mdname(conf->mddev));
        else
-               sprintf(conf->cache_name[0],
+               snprintf(conf->cache_name[0], namelen,
                        "raid%d-%p", conf->level, conf->mddev);
-       sprintf(conf->cache_name[1], "%s-alt", conf->cache_name[0]);
+       snprintf(conf->cache_name[1], namelen, "%.27s-alt", conf->cache_name[0]);
 
        conf->active_name = 0;
        sc = kmem_cache_create(conf->cache_name[conf->active_name],
@@ -6764,9 +6765,7 @@ static void free_conf(struct r5conf *conf)
 
        log_exit(conf);
 
-       if (conf->shrinker.nr_deferred)
-               unregister_shrinker(&conf->shrinker);
-
+       unregister_shrinker(&conf->shrinker);
        free_thread_groups(conf);
        shrink_stripes(conf);
        raid5_free_percpu(conf);
@@ -8001,13 +8000,7 @@ static void raid5_finish_reshape(struct mddev *mddev)
 
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 
-               if (mddev->delta_disks > 0) {
-                       md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
-                       if (mddev->queue) {
-                               set_capacity(mddev->gendisk, mddev->array_sectors);
-                               revalidate_disk(mddev->gendisk);
-                       }
-               } else {
+               if (mddev->delta_disks <= 0) {
                        int d;
                        spin_lock_irq(&conf->device_lock);
                        mddev->degraded = raid5_calc_degraded(conf);
index 2e6123825095296555e8a73a52d63872f2fa2bff..3f8da26032accce9fdf492b58fc120a94ac31582 100644 (file)
@@ -450,6 +450,18 @@ enum {
  * HANDLE gets cleared if stripe_handle leaves nothing locked.
  */
 
+/* Note: disk_info.rdev can be set to NULL asynchronously by raid5_remove_disk.
+ * There are three safe ways to access disk_info.rdev.
+ * 1/ when holding mddev->reconfig_mutex
+ * 2/ when resync/recovery/reshape is known to be happening - i.e. in code that
+ *    is called as part of performing resync/recovery/reshape.
+ * 3/ while holding rcu_read_lock(), use rcu_dereference to get the pointer
+ *    and if it is non-NULL, increment rdev->nr_pending before dropping the RCU
+ *    lock.
+ * When .rdev is set to NULL, the nr_pending count checked again and if
+ * it has been incremented, the pointer is put back in .rdev.
+ */
+
 struct disk_info {
        struct md_rdev  *rdev, *replacement;
        struct page     *extra_page; /* extra page to use in prexor */
index 145e12bfb8190ab8274645c43493b9978fff6e1a..372c074bb1b90fa0d1010d697faa18a7005231d7 100644 (file)
@@ -147,6 +147,8 @@ config DVB_CORE
 config DVB_MMAP
        bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
        depends on DVB_CORE
+       depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE
+       select VIDEOBUF2_VMALLOC
        default n
        help
          This option enables DVB experimental memory-mapped API, with
index 5df05250de947d7cf2bc396dc5104851f52fcb36..17c32ea58395d78f9fafe5525bbfbf1bdfe4b690 100644 (file)
@@ -3,6 +3,9 @@ config VIDEOBUF2_CORE
        select DMA_SHARED_BUFFER
        tristate
 
+config VIDEOBUF2_V4L2
+       tristate
+
 config VIDEOBUF2_MEMOPS
        tristate
        select FRAME_VECTOR
index 19de5ccda20b3c9de62a616077cfd11c6d743c58..77bebe8b202f46695ef239caaec98a567e088a03 100644 (file)
@@ -1,5 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+videobuf2-common-objs := videobuf2-core.o
 
-obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o
+ifeq ($(CONFIG_TRACEPOINTS),y)
+  videobuf2-common-objs += vb2-trace.o
+endif
+
+obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-common.o
+obj-$(CONFIG_VIDEOBUF2_V4L2) += videobuf2-v4l2.o
 obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
 obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
 obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
index 3a105d82019a0288b37f7a7143b1e8c79adffb42..62b028ded9f784438175969610608e60f35a9353 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
-dvb-vb2-$(CONFIG_DVB_MMSP) := dvb_vb2.o
+dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o
 
 dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o                 \
                 dvb_ca_en50221.o dvb_frontend.o                \
index 6d53af00190e396fda03bab661b56d4e4a1fc4a2..61a750fae4653be8da2ee47e60ae94e36e2143e6 100644 (file)
@@ -128,11 +128,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
        struct dmx_frontend *front;
-#ifndef DVB_MMAP
        bool need_ringbuffer = false;
-#else
-       const bool need_ringbuffer = true;
-#endif
 
        dprintk("%s\n", __func__);
 
@@ -144,17 +140,31 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
                return -ENODEV;
        }
 
-#ifndef DVB_MMAP
+       dmxdev->may_do_mmap = 0;
+
+       /*
+        * The logic here is a little tricky due to the ifdef.
+        *
+        * The ringbuffer is used for both read and mmap.
+        *
+        * It is not needed, however, on two situations:
+        *      - Write devices (access with O_WRONLY);
+        *      - For duplex device nodes, opened with O_RDWR.
+        */
+
        if ((file->f_flags & O_ACCMODE) == O_RDONLY)
                need_ringbuffer = true;
-#else
-       if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+       else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
                if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
+#ifdef CONFIG_DVB_MMAP
+                       dmxdev->may_do_mmap = 1;
+                       need_ringbuffer = true;
+#else
                        mutex_unlock(&dmxdev->mutex);
                        return -EOPNOTSUPP;
+#endif
                }
        }
-#endif
 
        if (need_ringbuffer) {
                void *mem;
@@ -169,8 +179,9 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
                        return -ENOMEM;
                }
                dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
-               dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
-                            file->f_flags & O_NONBLOCK);
+               if (dmxdev->may_do_mmap)
+                       dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
+                                    file->f_flags & O_NONBLOCK);
                dvbdev->readers--;
        }
 
@@ -200,11 +211,6 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
-#ifndef DVB_MMAP
-       bool need_ringbuffer = false;
-#else
-       const bool need_ringbuffer = true;
-#endif
 
        mutex_lock(&dmxdev->mutex);
 
@@ -213,15 +219,14 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
                dmxdev->demux->connect_frontend(dmxdev->demux,
                                                dmxdev->dvr_orig_fe);
        }
-#ifndef DVB_MMAP
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY)
-               need_ringbuffer = true;
-#endif
 
-       if (need_ringbuffer) {
-               if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
-                       dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
-               dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
+       if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
+           dmxdev->may_do_mmap) {
+               if (dmxdev->may_do_mmap) {
+                       if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
+                               dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
+                       dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
+               }
                dvbdev->readers++;
                if (dmxdev->dvr_buffer.data) {
                        void *mem = dmxdev->dvr_buffer.data;
@@ -380,7 +385,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
 
 static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
                                       const u8 *buffer2, size_t buffer2_len,
-                                      struct dmx_section_filter *filter)
+                                      struct dmx_section_filter *filter,
+                                      u32 *buffer_flags)
 {
        struct dmxdev_filter *dmxdevfilter = filter->priv;
        int ret;
@@ -399,10 +405,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
        dprintk("section callback %*ph\n", 6, buffer1);
        if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
                ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
-                                         buffer1, buffer1_len);
+                                         buffer1, buffer1_len,
+                                         buffer_flags);
                if (ret == buffer1_len)
                        ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
-                                                 buffer2, buffer2_len);
+                                                 buffer2, buffer2_len,
+                                                 buffer_flags);
        } else {
                ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
                                              buffer1, buffer1_len);
@@ -422,11 +430,12 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 
 static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
                                  const u8 *buffer2, size_t buffer2_len,
-                                 struct dmx_ts_feed *feed)
+                                 struct dmx_ts_feed *feed,
+                                 u32 *buffer_flags)
 {
        struct dmxdev_filter *dmxdevfilter = feed->priv;
        struct dvb_ringbuffer *buffer;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
        struct dvb_vb2_ctx *ctx;
 #endif
        int ret;
@@ -440,20 +449,22 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
        if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
            dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
                buffer = &dmxdevfilter->buffer;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
                ctx = &dmxdevfilter->vb2_ctx;
 #endif
        } else {
                buffer = &dmxdevfilter->dev->dvr_buffer;
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
                ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
 #endif
        }
 
        if (dvb_vb2_is_streaming(ctx)) {
-               ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len);
+               ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len,
+                                         buffer_flags);
                if (ret == buffer1_len)
-                       ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len);
+                       ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len,
+                                                 buffer_flags);
        } else {
                if (buffer->error) {
                        spin_unlock(&dmxdevfilter->dev->lock);
@@ -802,6 +813,12 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
        mutex_init(&dmxdevfilter->mutex);
        file->private_data = dmxdevfilter;
 
+#ifdef CONFIG_DVB_MMAP
+       dmxdev->may_do_mmap = 1;
+#else
+       dmxdev->may_do_mmap = 0;
+#endif
+
        dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
        dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
                     file->f_flags & O_NONBLOCK);
@@ -1111,7 +1128,7 @@ static int dvb_demux_do_ioctl(struct file *file,
                mutex_unlock(&dmxdevfilter->mutex);
                break;
 
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
        case DMX_REQBUFS:
                if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
                        mutex_unlock(&dmxdev->mutex);
@@ -1160,7 +1177,7 @@ static int dvb_demux_do_ioctl(struct file *file,
                break;
 #endif
        default:
-               ret = -EINVAL;
+               ret = -ENOTTY;
                break;
        }
        mutex_unlock(&dmxdev->mutex);
@@ -1199,13 +1216,16 @@ static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
        return mask;
 }
 
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
 static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct dmxdev_filter *dmxdevfilter = file->private_data;
        struct dmxdev *dmxdev = dmxdevfilter->dev;
        int ret;
 
+       if (!dmxdev->may_do_mmap)
+               return -ENOTTY;
+
        if (mutex_lock_interruptible(&dmxdev->mutex))
                return -ERESTARTSYS;
 
@@ -1249,7 +1269,7 @@ static const struct file_operations dvb_demux_fops = {
        .release = dvb_demux_release,
        .poll = dvb_demux_poll,
        .llseek = default_llseek,
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
        .mmap = dvb_demux_mmap,
 #endif
 };
@@ -1280,7 +1300,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
                ret = dvb_dvr_set_buffer_size(dmxdev, arg);
                break;
 
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
        case DMX_REQBUFS:
                ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
                break;
@@ -1304,7 +1324,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
                break;
 #endif
        default:
-               ret = -EINVAL;
+               ret = -ENOTTY;
                break;
        }
        mutex_unlock(&dmxdev->mutex);
@@ -1322,11 +1342,6 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
        __poll_t mask = 0;
-#ifndef DVB_MMAP
-       bool need_ringbuffer = false;
-#else
-       const bool need_ringbuffer = true;
-#endif
 
        dprintk("%s\n", __func__);
 
@@ -1337,11 +1352,8 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
 
-#ifndef DVB_MMAP
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY)
-               need_ringbuffer = true;
-#endif
-       if (need_ringbuffer) {
+       if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
+           dmxdev->may_do_mmap) {
                if (dmxdev->dvr_buffer.error)
                        mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
 
@@ -1353,13 +1365,16 @@ static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
        return mask;
 }
 
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
 static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dmxdev *dmxdev = dvbdev->priv;
        int ret;
 
+       if (!dmxdev->may_do_mmap)
+               return -ENOTTY;
+
        if (dmxdev->exit)
                return -ENODEV;
 
@@ -1381,7 +1396,7 @@ static const struct file_operations dvb_dvr_fops = {
        .release = dvb_dvr_release,
        .poll = dvb_dvr_poll,
        .llseek = default_llseek,
-#ifdef DVB_MMAP
+#ifdef CONFIG_DVB_MMAP
        .mmap = dvb_dvr_mmap,
 #endif
 };
index 210eed0269b085d5b8c99d5f8941928cf0613a30..f45091246bdca90d870dc0a10bd35e8fd4d73eea 100644 (file)
@@ -55,6 +55,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
                dprintk(x);                             \
 } while (0)
 
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
+#  define dprintk_sect_loss(x...) dprintk(x)
+#else
+#  define dprintk_sect_loss(x...)
+#endif
+
+#define set_buf_flags(__feed, __flag)                  \
+       do {                                            \
+               (__feed)->buffer_flags |= (__flag);     \
+       } while (0)
+
 /******************************************************************************
  * static inlined helper functions
  ******************************************************************************/
@@ -104,31 +115,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
 {
        int count = payload(buf);
        int p;
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
        int ccok;
        u8 cc;
-#endif
 
        if (count == 0)
                return -1;
 
        p = 188 - count;
 
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
        cc = buf[3] & 0x0f;
        ccok = ((feed->cc + 1) & 0x0f) == cc;
        feed->cc = cc;
-       if (!ccok)
-               dprintk("missed packet: %d instead of %d!\n",
-                       cc, (feed->cc + 1) & 0x0f);
-#endif
+       if (!ccok) {
+               set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
+               dprintk_sect_loss("missed packet: %d instead of %d!\n",
+                                 cc, (feed->cc + 1) & 0x0f);
+       }
 
        if (buf[1] & 0x40)      // PUSI ?
                feed->peslen = 0xfffa;
 
        feed->peslen += count;
 
-       return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts);
+       return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts,
+                          &feed->buffer_flags);
 }
 
 static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
@@ -150,7 +160,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
                return 0;
 
        return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
-                           NULL, 0, &f->filter);
+                           NULL, 0, &f->filter, &feed->buffer_flags);
 }
 
 static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
@@ -169,8 +179,10 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
        if (sec->check_crc) {
                section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
                if (section_syntax_indicator &&
-                   demux->check_crc32(feed, sec->secbuf, sec->seclen))
+                   demux->check_crc32(feed, sec->secbuf, sec->seclen)) {
+                       set_buf_flags(feed, DMX_BUFFER_FLAG_HAD_CRC32_DISCARD);
                        return -1;
+               }
        }
 
        do {
@@ -187,7 +199,6 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 {
        struct dmx_section_feed *sec = &feed->feed.sec;
 
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
        if (sec->secbufp < sec->tsfeedp) {
                int n = sec->tsfeedp - sec->secbufp;
 
@@ -197,12 +208,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
                 * but just first and last.
                 */
                if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
-                       dprintk("section ts padding loss: %d/%d\n",
-                              n, sec->tsfeedp);
-                       dprintk("pad data: %*ph\n", n, sec->secbuf);
+                       set_buf_flags(feed,
+                                     DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
+                       dprintk_sect_loss("section ts padding loss: %d/%d\n",
+                                         n, sec->tsfeedp);
+                       dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf);
                }
        }
-#endif
 
        sec->tsfeedp = sec->secbufp = sec->seclen = 0;
        sec->secbuf = sec->secbuf_base;
@@ -237,11 +249,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
                return 0;
 
        if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
-               dprintk("section buffer full loss: %d/%d\n",
-                       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
-                       DMX_MAX_SECFEED_SIZE);
-#endif
+               set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
+               dprintk_sect_loss("section buffer full loss: %d/%d\n",
+                                 sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
+                                 DMX_MAX_SECFEED_SIZE);
                len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
        }
 
@@ -269,12 +280,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
                sec->seclen = seclen;
                sec->crc_val = ~0;
                /* dump [secbuf .. secbuf+seclen) */
-               if (feed->pusi_seen)
+               if (feed->pusi_seen) {
                        dvb_dmx_swfilter_section_feed(feed);
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
-               else
-                       dprintk("pusi not seen, discarding section data\n");
-#endif
+               } else {
+                       set_buf_flags(feed,
+                                     DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
+                       dprintk_sect_loss("pusi not seen, discarding section data\n");
+               }
                sec->secbufp += seclen; /* secbufp and secbuf moving together is */
                sec->secbuf += seclen;  /* redundant but saves pointer arithmetic */
        }
@@ -307,18 +319,22 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
        }
 
        if (!ccok || dc_i) {
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
-               if (dc_i)
-                       dprintk("%d frame with disconnect indicator\n",
+               if (dc_i) {
+                       set_buf_flags(feed,
+                                     DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR);
+                       dprintk_sect_loss("%d frame with disconnect indicator\n",
                                cc);
-               else
-                       dprintk("discontinuity: %d instead of %d. %d bytes lost\n",
+               } else {
+                       set_buf_flags(feed,
+                                     DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
+                       dprintk_sect_loss("discontinuity: %d instead of %d. %d bytes lost\n",
                                cc, (feed->cc + 1) & 0x0f, count + 4);
+               }
                /*
-                * those bytes under sume circumstances will again be reported
+                * those bytes under some circumstances will again be reported
                 * in the following dvb_dmx_swfilter_section_new
                 */
-#endif
+
                /*
                 * Discontinuity detected. Reset pusi_seen to
                 * stop feeding of suspicious data until next PUSI=1 arrives
@@ -326,6 +342,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
                 * FIXME: does it make sense if the MPEG-TS is the one
                 *      reporting discontinuity?
                 */
+
                feed->pusi_seen = false;
                dvb_dmx_swfilter_section_new(feed);
        }
@@ -345,11 +362,11 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
                        dvb_dmx_swfilter_section_new(feed);
                        dvb_dmx_swfilter_section_copy_dump(feed, after,
                                                           after_len);
+               } else if (count > 0) {
+                       set_buf_flags(feed,
+                                     DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
+                       dprintk_sect_loss("PUSI=1 but %d bytes lost\n", count);
                }
-#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
-               else if (count > 0)
-                       dprintk("PUSI=1 but %d bytes lost\n", count);
-#endif
        } else {
                /* PUSI=0 (is not set), no section boundary */
                dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
@@ -369,7 +386,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
                        if (feed->ts_type & TS_PAYLOAD_ONLY)
                                dvb_dmx_swfilter_payload(feed, buf);
                        else
-                               feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
+                               feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
+                                           &feed->buffer_flags);
                }
                /* Used only on full-featured devices */
                if (feed->ts_type & TS_DECODER)
@@ -430,6 +448,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
        }
 
        if (buf[1] & 0x80) {
+               list_for_each_entry(feed, &demux->feed_list, list_head) {
+                       if ((feed->pid != pid) && (feed->pid != 0x2000))
+                               continue;
+                       set_buf_flags(feed, DMX_BUFFER_FLAG_TEI);
+               }
                dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n",
                                pid, buf[1]);
                /* data in this packet can't be trusted - drop it unless
@@ -445,6 +468,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                                                (demux->cnt_storage[pid] + 1) & 0xf;
 
                                if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
+                                       list_for_each_entry(feed, &demux->feed_list, list_head) {
+                                               if ((feed->pid != pid) && (feed->pid != 0x2000))
+                                                       continue;
+                                               set_buf_flags(feed,
+                                                             DMX_BUFFER_PKT_COUNTER_MISMATCH);
+                                       }
+
                                        dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
                                                        pid, demux->cnt_storage[pid],
                                                        buf[3] & 0xf);
@@ -466,7 +496,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                if (feed->pid == pid)
                        dvb_dmx_swfilter_packet_type(feed, buf);
                else if (feed->pid == 0x2000)
-                       feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
+                       feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
+                                   &feed->buffer_flags);
        }
 }
 
@@ -585,7 +616,8 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
 
        spin_lock_irqsave(&demux->lock, flags);
 
-       demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts);
+       demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts,
+                          &demux->feed->buffer_flags);
 
        spin_unlock_irqrestore(&demux->lock, flags);
 }
@@ -785,6 +817,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
        feed->demux = demux;
        feed->pid = 0xffff;
        feed->peslen = 0xfffa;
+       feed->buffer_flags = 0;
 
        (*ts_feed) = &feed->feed.ts;
        (*ts_feed)->parent = dmx;
@@ -1042,6 +1075,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
        dvbdmxfeed->cb.sec = callback;
        dvbdmxfeed->demux = dvbdmx;
        dvbdmxfeed->pid = 0xffff;
+       dvbdmxfeed->buffer_flags = 0;
        dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
        dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
        dvbdmxfeed->feed.sec.tsfeedp = 0;
index b6c7eec863b9232b5fb30d07b809a01298d85c22..ba39f9942e1db06f0eeadc6473287f641ff4af85 100644 (file)
@@ -883,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
 
 static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
                               const u8 *buffer2, size_t buffer2_len,
-                              struct dmx_ts_feed *feed)
+                              struct dmx_ts_feed *feed,
+                              u32 *buffer_flags)
 {
        struct net_device *dev = feed->priv;
 
@@ -992,7 +993,7 @@ static void dvb_net_sec(struct net_device *dev,
 
 static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
                 const u8 *buffer2, size_t buffer2_len,
-                struct dmx_section_filter *filter)
+                struct dmx_section_filter *filter, u32 *buffer_flags)
 {
        struct net_device *dev = filter->priv;
 
index 763145d74e836aba5ae400e20522cce0c84a308d..b811adf88afa3424d14b6584969928d2b5cdae54 100644 (file)
@@ -256,7 +256,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
 }
 
 int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
-                       const unsigned char *src, int len)
+                       const unsigned char *src, int len,
+                       enum dmx_buffer_flags *buffer_flags)
 {
        unsigned long flags = 0;
        void *vbuf = NULL;
@@ -264,15 +265,17 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
        unsigned char *psrc = (unsigned char *)src;
        int ll = 0;
 
-       dprintk(3, "[%s] %d bytes are rcvd\n", ctx->name, len);
-       if (!src) {
-               dprintk(3, "[%s]:NULL pointer src\n", ctx->name);
-               /**normal case: This func is called twice from demux driver
-                * once with valid src pointer, second time with NULL pointer
-                */
+       /*
+        * normal case: This func is called twice from demux driver
+        * one with valid src pointer, second time with NULL pointer
+        */
+       if (!src || !len)
                return 0;
-       }
        spin_lock_irqsave(&ctx->slock, flags);
+       if (buffer_flags && *buffer_flags) {
+               ctx->flags |= *buffer_flags;
+               *buffer_flags = 0;
+       }
        while (todo) {
                if (!ctx->buf) {
                        if (list_empty(&ctx->dvb_q)) {
@@ -395,6 +398,7 @@ int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 
 int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
+       unsigned long flags;
        int ret;
 
        ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking);
@@ -402,7 +406,16 @@ int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
                dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
                return ret;
        }
-       dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
+
+       spin_lock_irqsave(&ctx->slock, flags);
+       b->count = ctx->count++;
+       b->flags = ctx->flags;
+       ctx->flags = 0;
+       spin_unlock_irqrestore(&ctx->slock, flags);
+
+       dprintk(5, "[%s] index=%d, count=%d, flags=%d\n",
+               ctx->name, b->index, ctx->count, b->flags);
+
 
        return 0;
 }
index 50bce68ffd6646526fa86e1eaa5c65692b02a7b6..65d157fe76d19dad45ac94fa9eb21cbdad5dd575 100644 (file)
@@ -1262,11 +1262,12 @@ static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan)
  * New users must use I2C client binding directly!
  */
 struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg,
-               struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter)
+                                     struct i2c_adapter *i2c,
+                                     struct i2c_adapter **tuner_i2c_adapter)
 {
        struct i2c_client *client;
        struct i2c_board_info board_info;
-       struct m88ds3103_platform_data pdata;
+       struct m88ds3103_platform_data pdata = {};
 
        pdata.clk = cfg->clock;
        pdata.i2c_wr_max = cfg->i2c_wr_max;
@@ -1409,6 +1410,8 @@ static int m88ds3103_probe(struct i2c_client *client,
        case M88DS3103_CHIP_ID:
                break;
        default:
+               ret = -ENODEV;
+               dev_err(&client->dev, "Unknown device. Chip_id=%02x\n", dev->chip_id);
                goto err_kfree;
        }
 
index 3c1851984b907a54b22920dec24e865731006f96..2476d812f669476a286672de807009df8f4980fb 100644 (file)
@@ -505,80 +505,77 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
        /* FIXME: Current api doesn't handle all VBI types, those not
           yet supported are placed under #if 0 */
 #if 0
-       {0x010, /* Teletext, SECAM, WST System A */
+       [0] = {0x010, /* Teletext, SECAM, WST System A */
                {V4L2_SLICED_TELETEXT_SECAM,6,23,1},
                { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
                  0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
        },
 #endif
-       {0x030, /* Teletext, PAL, WST System B */
+       [1] = {0x030, /* Teletext, PAL, WST System B */
                {V4L2_SLICED_TELETEXT_B,6,22,1},
                { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
                  0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
        },
 #if 0
-       {0x050, /* Teletext, PAL, WST System C */
+       [2] = {0x050, /* Teletext, PAL, WST System C */
                {V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
                { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
                  0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
        },
-       {0x070, /* Teletext, NTSC, WST System B */
+       [3] = {0x070, /* Teletext, NTSC, WST System B */
                {V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
                { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
                  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
        },
-       {0x090, /* Tetetext, NTSC NABTS System C */
+       [4] = {0x090, /* Tetetext, NTSC NABTS System C */
                {V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
                { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
                  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
        },
-       {0x0b0, /* Teletext, NTSC-J, NABTS System D */
+       [5] = {0x0b0, /* Teletext, NTSC-J, NABTS System D */
                {V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
                { 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
                  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
        },
-       {0x0d0, /* Closed Caption, PAL/SECAM */
+       [6] = {0x0d0, /* Closed Caption, PAL/SECAM */
                {V4L2_SLICED_CAPTION_625,22,22,1},
                { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
                  0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
        },
 #endif
-       {0x0f0, /* Closed Caption, NTSC */
+       [7] = {0x0f0, /* Closed Caption, NTSC */
                {V4L2_SLICED_CAPTION_525,21,21,1},
                { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
                  0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
        },
-       {0x110, /* Wide Screen Signal, PAL/SECAM */
+       [8] = {0x110, /* Wide Screen Signal, PAL/SECAM */
                {V4L2_SLICED_WSS_625,23,23,1},
                { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
                  0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
        },
 #if 0
-       {0x130, /* Wide Screen Signal, NTSC C */
+       [9] = {0x130, /* Wide Screen Signal, NTSC C */
                {V4L2_SLICED_WSS_525,20,20,1},
                { 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
                  0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
        },
-       {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
+       [10] = {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
                {V4l2_SLICED_VITC_625,6,22,0},
                { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
                  0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
        },
-       {0x170, /* Vertical Interval Timecode (VITC), NTSC */
+       [11] = {0x170, /* Vertical Interval Timecode (VITC), NTSC */
                {V4l2_SLICED_VITC_525,10,20,0},
                { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
                  0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
        },
 #endif
-       {0x190, /* Video Program System (VPS), PAL */
+       [12] = {0x190, /* Video Program System (VPS), PAL */
                {V4L2_SLICED_VPS,16,16,0},
                { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
                  0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
        },
        /* 0x1d0 User programmable */
-
-       /* End of struct */
-       { (u16)-1 }
 };
 
 static int tvp5150_write_inittab(struct v4l2_subdev *sd,
@@ -591,10 +588,10 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int tvp5150_vdp_init(struct v4l2_subdev *sd,
-                               const struct i2c_vbi_ram_value *regs)
+static int tvp5150_vdp_init(struct v4l2_subdev *sd)
 {
        unsigned int i;
+       int j;
 
        /* Disable Full Field */
        tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
@@ -604,14 +601,17 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd,
                tvp5150_write(sd, i, 0xff);
 
        /* Load Ram Table */
-       while (regs->reg != (u16)-1) {
+       for (j = 0; j < ARRAY_SIZE(vbi_ram_default); j++) {
+               const struct i2c_vbi_ram_value *regs = &vbi_ram_default[j];
+
+               if (!regs->type.vbi_type)
+                       continue;
+
                tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
                tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
 
                for (i = 0; i < 16; i++)
                        tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
-
-               regs++;
        }
        return 0;
 }
@@ -620,19 +620,23 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd,
 static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
                                struct v4l2_sliced_vbi_cap *cap)
 {
-       const struct i2c_vbi_ram_value *regs = vbi_ram_default;
-       int line;
+       int line, i;
 
        dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n");
        memset(cap, 0, sizeof *cap);
 
-       while (regs->reg != (u16)-1 ) {
-               for (line=regs->type.ini_line;line<=regs->type.end_line;line++) {
+       for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
+               const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
+
+               if (!regs->type.vbi_type)
+                       continue;
+
+               for (line = regs->type.ini_line;
+                    line <= regs->type.end_line;
+                    line++) {
                        cap->service_lines[0][line] |= regs->type.vbi_type;
                }
                cap->service_set |= regs->type.vbi_type;
-
-               regs++;
        }
        return 0;
 }
@@ -651,14 +655,13 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
  *     MSB = field2
  */
 static int tvp5150_set_vbi(struct v4l2_subdev *sd,
-                       const struct i2c_vbi_ram_value *regs,
                        unsigned int type,u8 flags, int line,
                        const int fields)
 {
        struct tvp5150 *decoder = to_tvp5150(sd);
        v4l2_std_id std = decoder->norm;
        u8 reg;
-       int pos = 0;
+       int i, pos = 0;
 
        if (std == V4L2_STD_ALL) {
                dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n");
@@ -671,19 +674,19 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
        if (line < 6 || line > 27)
                return 0;
 
-       while (regs->reg != (u16)-1) {
+       for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
+               const struct i2c_vbi_ram_value *regs =  &vbi_ram_default[i];
+
+               if (!regs->type.vbi_type)
+                       continue;
+
                if ((type & regs->type.vbi_type) &&
                    (line >= regs->type.ini_line) &&
                    (line <= regs->type.end_line))
                        break;
-
-               regs++;
                pos++;
        }
 
-       if (regs->reg == (u16)-1)
-               return 0;
-
        type = pos | (flags & 0xf0);
        reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
 
@@ -696,8 +699,7 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
        return type;
 }
 
-static int tvp5150_get_vbi(struct v4l2_subdev *sd,
-                       const struct i2c_vbi_ram_value *regs, int line)
+static int tvp5150_get_vbi(struct v4l2_subdev *sd, int line)
 {
        struct tvp5150 *decoder = to_tvp5150(sd);
        v4l2_std_id std = decoder->norm;
@@ -726,8 +728,8 @@ static int tvp5150_get_vbi(struct v4l2_subdev *sd,
                        return 0;
                }
                pos = ret & 0x0f;
-               if (pos < 0x0f)
-                       type |= regs[pos].type.vbi_type;
+               if (pos < ARRAY_SIZE(vbi_ram_default))
+                       type |= vbi_ram_default[pos].type.vbi_type;
        }
 
        return type;
@@ -788,7 +790,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
        tvp5150_write_inittab(sd, tvp5150_init_default);
 
        /* Initializes VDP registers */
-       tvp5150_vdp_init(sd, vbi_ram_default);
+       tvp5150_vdp_init(sd);
 
        /* Selects decoder input */
        tvp5150_selmux(sd);
@@ -1121,8 +1123,8 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
                for (i = 0; i <= 23; i++) {
                        svbi->service_lines[1][i] = 0;
                        svbi->service_lines[0][i] =
-                               tvp5150_set_vbi(sd, vbi_ram_default,
-                                      svbi->service_lines[0][i], 0xf0, i, 3);
+                               tvp5150_set_vbi(sd, svbi->service_lines[0][i],
+                                               0xf0, i, 3);
                }
                /* Enables FIFO */
                tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
@@ -1148,7 +1150,7 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
 
        for (i = 0; i <= 23; i++) {
                svbi->service_lines[0][i] =
-                       tvp5150_get_vbi(sd, vbi_ram_default, i);
+                       tvp5150_get_vbi(sd, i);
                mask |= svbi->service_lines[0][i];
        }
        svbi->service_set = mask;
index dc8e577b2f748a4d287dacaf817beed1096e903e..d6816effb87866b80eae57d7c45004524d8cc031 100644 (file)
@@ -324,14 +324,15 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
                }
                return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
                                                  buffer2, buffer2_len,
-                                                 &dvbdmxfilter->filter);
+                                                 &dvbdmxfilter->filter, NULL);
        case DMX_TYPE_TS:
                if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
                        return 0;
                if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
                        return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
                                                         buffer2, buffer2_len,
-                                                        &dvbdmxfilter->feed->feed.ts);
+                                                        &dvbdmxfilter->feed->feed.ts,
+                                                        NULL);
                else
                        av7110_p2t_write(buffer1, buffer1_len,
                                         dvbdmxfilter->feed->pid,
index 4daba76ec240bc382e3b48e17f3d1cbafaaa6858..ef1bc17cdc4d37a8549b86d7085a8fdfd76abca3 100644 (file)
@@ -99,7 +99,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
                buf[4] = buf[5] = 0;
        if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
                return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
-                                        &dvbdmxfeed->feed.ts);
+                                        &dvbdmxfeed->feed.ts, NULL);
        else
                return dvb_filter_pes2ts(p2t, buf, len, 1);
 }
@@ -109,7 +109,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
        struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
 
        dvbdmxfeed->cb.ts(data, 188, NULL, 0,
-                         &dvbdmxfeed->feed.ts);
+                         &dvbdmxfeed->feed.ts, NULL);
        return 0;
 }
 
@@ -814,7 +814,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
                        memcpy(obuf + l, buf + c, TS_SIZE - l);
                        c = length;
                }
-               feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts);
+               feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, NULL);
                pes_start = 0;
        }
 }
index 70521e0b4c5348b6a1ab563e122b557fb58c111b..bfaa806633df740ee72047d5ea81158eedfcb4b0 100644 (file)
@@ -1,7 +1,7 @@
 
 config VIDEO_AU0828
        tristate "Auvitek AU0828 support"
-       depends on I2C && INPUT && DVB_CORE && USB
+       depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
        select I2C_ALGOBIT
        select VIDEO_TVEEPROM
        select VIDEOBUF2_VMALLOC
index a8900f5571f784014d273eb29058fa04ca08a55c..44ca66cb9b8f141e15d7ca0ccc0b7ae5c2abee60 100644 (file)
@@ -428,7 +428,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
        struct ttusb_dec *dec = priv;
 
        dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
-                                      &dec->audio_filter->feed->feed.ts);
+                                      &dec->audio_filter->feed->feed.ts, NULL);
 
        return 0;
 }
@@ -438,7 +438,7 @@ static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
        struct ttusb_dec *dec = priv;
 
        dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
-                                      &dec->video_filter->feed->feed.ts);
+                                      &dec->video_filter->feed->feed.ts, NULL);
 
        return 0;
 }
@@ -490,7 +490,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
 
                if (output_pva) {
                        dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
-                               &dec->video_filter->feed->feed.ts);
+                               &dec->video_filter->feed->feed.ts, NULL);
                        return;
                }
 
@@ -551,7 +551,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
        case 0x02:              /* MainAudioStream */
                if (output_pva) {
                        dec->audio_filter->feed->cb.ts(pva, length, NULL, 0,
-                               &dec->audio_filter->feed->feed.ts);
+                               &dec->audio_filter->feed->feed.ts, NULL);
                        return;
                }
 
@@ -589,7 +589,7 @@ static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
 
        if (filter)
                filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
-                                    &filter->filter);
+                                    &filter->filter, NULL);
 }
 
 static void ttusb_dec_process_packet(struct ttusb_dec *dec)
index bf52fbd07aeddc3f228cef870d05e9622699bd03..8e37e7c5e0f7e25aca250b8b052f274f2b8f3c09 100644 (file)
@@ -7,6 +7,7 @@ config VIDEO_V4L2
        tristate
        depends on (I2C || I2C=n) && VIDEO_DEV
        select RATIONAL
+       select VIDEOBUF2_V4L2 if VIDEOBUF2_CORE
        default (I2C || I2C=n) && VIDEO_DEV
 
 config VIDEO_ADV_DEBUG
index 80de2cb9c476a256634815155a4d033a428228af..7df54582e95689ef2c189652dd5c33ea735a8023 100644 (file)
@@ -13,7 +13,7 @@ ifeq ($(CONFIG_COMPAT),y)
 endif
 obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
 ifeq ($(CONFIG_TRACEPOINTS),y)
-  videodev-objs += vb2-trace.o v4l2-trace.o
+  videodev-objs += v4l2-trace.o
 endif
 videodev-$(CONFIG_MEDIA_CONTROLLER) += v4l2-mc.o
 
@@ -35,4 +35,3 @@ obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
 
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
 ccflags-y += -I$(srctree)/drivers/media/tuners
-
index 0a7bdbed3a6f0185ce35ec49d2e6ccce80592a9c..e9c1485c32b95c66c670e698557632964a946072 100644 (file)
 #define REG_TO_DCPU_MBOX       0x10
 #define REG_TO_HOST_MBOX       0x14
 
+/* Macros to process offsets returned by the DCPU */
+#define DRAM_MSG_ADDR_OFFSET   0x0
+#define DRAM_MSG_TYPE_OFFSET   0x1c
+#define DRAM_MSG_ADDR_MASK     ((1UL << DRAM_MSG_TYPE_OFFSET) - 1)
+#define DRAM_MSG_TYPE_MASK     ((1UL << \
+                                (BITS_PER_LONG - DRAM_MSG_TYPE_OFFSET)) - 1)
+
 /* Message RAM */
-#define DCPU_MSG_RAM(x)                (0x100 + (x) * sizeof(u32))
+#define DCPU_MSG_RAM_START     0x100
+#define DCPU_MSG_RAM(x)                (DCPU_MSG_RAM_START + (x) * sizeof(u32))
 
 /* DRAM Info Offsets & Masks */
 #define DRAM_INFO_INTERVAL     0x0
@@ -255,6 +263,40 @@ static unsigned int get_msg_chksum(const u32 msg[])
        return sum;
 }
 
+static void __iomem *get_msg_ptr(struct private_data *priv, u32 response,
+                                char *buf, ssize_t *size)
+{
+       unsigned int msg_type;
+       unsigned int offset;
+       void __iomem *ptr = NULL;
+
+       msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
+       offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
+
+       /*
+        * msg_type == 1: the offset is relative to the message RAM
+        * msg_type == 0: the offset is relative to the data RAM (this is the
+        *                previous way of passing data)
+        * msg_type is anything else: there's critical hardware problem
+        */
+       switch (msg_type) {
+       case 1:
+               ptr = priv->regs + DCPU_MSG_RAM_START + offset;
+               break;
+       case 0:
+               ptr = priv->dmem + offset;
+               break;
+       default:
+               dev_emerg(priv->dev, "invalid message reply from DCPU: %#x\n",
+                       response);
+               if (buf && size)
+                       *size = sprintf(buf,
+                               "FATAL: communication error with DCPU\n");
+       }
+
+       return ptr;
+}
+
 static int __send_command(struct private_data *priv, unsigned int cmd,
                          u32 result[])
 {
@@ -507,7 +549,7 @@ static ssize_t show_info(struct device *dev, struct device_attribute *devattr,
 {
        u32 response[MSG_FIELD_MAX];
        unsigned int info;
-       int ret;
+       ssize_t ret;
 
        ret = generic_show(DPFE_CMD_GET_INFO, response, dev, buf);
        if (ret)
@@ -528,18 +570,19 @@ static ssize_t show_refresh(struct device *dev,
        u32 response[MSG_FIELD_MAX];
        void __iomem *info;
        struct private_data *priv;
-       unsigned int offset;
        u8 refresh, sr_abort, ppre, thermal_offs, tuf;
        u32 mr4;
-       int ret;
+       ssize_t ret;
 
        ret = generic_show(DPFE_CMD_GET_REFRESH, response, dev, buf);
        if (ret)
                return ret;
 
        priv = dev_get_drvdata(dev);
-       offset = response[MSG_ARG0];
-       info = priv->dmem + offset;
+
+       info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
+       if (!info)
+               return ret;
 
        mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK;
 
@@ -561,7 +604,6 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
        u32 response[MSG_FIELD_MAX];
        struct private_data *priv;
        void __iomem *info;
-       unsigned int offset;
        unsigned long val;
        int ret;
 
@@ -574,8 +616,10 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
        if (ret)
                return ret;
 
-       offset = response[MSG_ARG0];
-       info = priv->dmem + offset;
+       info = get_msg_ptr(priv, response[MSG_ARG0], NULL, NULL);
+       if (!info)
+               return -EIO;
+
        writel_relaxed(val, info + DRAM_INFO_INTERVAL);
 
        return count;
@@ -587,23 +631,25 @@ static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr,
        u32 response[MSG_FIELD_MAX];
        struct private_data *priv;
        void __iomem *info;
-       unsigned int offset;
-       int ret;
+       ssize_t ret;
 
        ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf);
        if (ret)
                return ret;
 
-       offset = response[MSG_ARG0];
        priv = dev_get_drvdata(dev);
-       info = priv->dmem + offset;
+
+       info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
+       if (!info)
+               return ret;
 
        return sprintf(buf, "%#x %#x %#x %#x %#x\n",
                       readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK,
                       readl_relaxed(info + DRAM_VENDOR_MR6) & DRAM_VENDOR_MASK,
                       readl_relaxed(info + DRAM_VENDOR_MR7) & DRAM_VENDOR_MASK,
                       readl_relaxed(info + DRAM_VENDOR_MR8) & DRAM_VENDOR_MASK,
-                      readl_relaxed(info + DRAM_VENDOR_ERROR));
+                      readl_relaxed(info + DRAM_VENDOR_ERROR) &
+                                    DRAM_VENDOR_MASK);
 }
 
 static int brcmstb_dpfe_resume(struct platform_device *pdev)
index 908e4db03535b038d548563188c0a11ac1ce4761..42d6aa89a48a95ad82bc60445f73971ac48730d2 100644 (file)
@@ -848,7 +848,6 @@ int mmc_interrupt_hpi(struct mmc_card *card)
                return 1;
        }
 
-       mmc_claim_host(card->host);
        err = mmc_send_status(card, &status);
        if (err) {
                pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
@@ -890,7 +889,6 @@ int mmc_interrupt_hpi(struct mmc_card *card)
        } while (!err);
 
 out:
-       mmc_release_host(card->host);
        return err;
 }
 
@@ -932,9 +930,7 @@ static int mmc_read_bkops_status(struct mmc_card *card)
        int err;
        u8 *ext_csd;
 
-       mmc_claim_host(card->host);
        err = mmc_get_ext_csd(card, &ext_csd);
-       mmc_release_host(card->host);
        if (err)
                return err;
 
index 35026795be2803c7387203c5719f4442c15b7c50..fa41d9422d57e04e9b12ef097a74d52418bdd87b 100644 (file)
@@ -487,6 +487,7 @@ static unsigned long exynos_dwmmc_caps[4] = {
 
 static const struct dw_mci_drv_data exynos_drv_data = {
        .caps                   = exynos_dwmmc_caps,
+       .num_caps               = ARRAY_SIZE(exynos_dwmmc_caps),
        .init                   = dw_mci_exynos_priv_init,
        .set_ios                = dw_mci_exynos_set_ios,
        .parse_dt               = dw_mci_exynos_parse_dt,
index 73fd75c3c824904d7171a51f16943192f6c1bc03..89cdb3d533bb519f57e3a4c7d6a7570f54f3077c 100644 (file)
@@ -135,6 +135,9 @@ static int dw_mci_hi6220_parse_dt(struct dw_mci *host)
        if (priv->ctrl_id < 0)
                priv->ctrl_id = 0;
 
+       if (priv->ctrl_id >= TIMING_MODE)
+               return -EINVAL;
+
        host->priv = priv;
        return 0;
 }
@@ -207,6 +210,7 @@ static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
 
 static const struct dw_mci_drv_data hi6220_data = {
        .caps                   = dw_mci_hi6220_caps,
+       .num_caps               = ARRAY_SIZE(dw_mci_hi6220_caps),
        .switch_voltage         = dw_mci_hi6220_switch_voltage,
        .set_ios                = dw_mci_hi6220_set_ios,
        .parse_dt               = dw_mci_hi6220_parse_dt,
index a3f1c2b3014534515db2246b0921b1be3a8b9c7d..3392952129355b2752f3131c0ff38a96b4e9d088 100644 (file)
@@ -319,6 +319,7 @@ static const struct dw_mci_drv_data rk2928_drv_data = {
 
 static const struct dw_mci_drv_data rk3288_drv_data = {
        .caps                   = dw_mci_rk3288_dwmmc_caps,
+       .num_caps               = ARRAY_SIZE(dw_mci_rk3288_dwmmc_caps),
        .set_ios                = dw_mci_rk3288_set_ios,
        .execute_tuning         = dw_mci_rk3288_execute_tuning,
        .parse_dt               = dw_mci_rk3288_parse_dt,
index d38e94ae2b855ccdbcd8c74db19950b9b9ea310e..c06b5393312ff185ffa9487931578665c74efd62 100644 (file)
@@ -195,6 +195,7 @@ static unsigned long zx_dwmmc_caps[3] = {
 
 static const struct dw_mci_drv_data zx_drv_data = {
        .caps                   = zx_dwmmc_caps,
+       .num_caps               = ARRAY_SIZE(zx_dwmmc_caps),
        .execute_tuning         = dw_mci_zx_execute_tuning,
        .prepare_hs400_tuning   = dw_mci_zx_prepare_hs400_tuning,
        .parse_dt               = dw_mci_zx_parse_dt,
index 0aa39975f33b8fbf36f0995cb56ffe283c7ca1b2..d9b4acefed31e6303aa614577f6b455afa3c04ba 100644 (file)
@@ -165,6 +165,8 @@ static int dw_mci_regs_show(struct seq_file *s, void *v)
 {
        struct dw_mci *host = s->private;
 
+       pm_runtime_get_sync(host->dev);
+
        seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));
        seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));
        seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD));
@@ -172,6 +174,8 @@ static int dw_mci_regs_show(struct seq_file *s, void *v)
        seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));
        seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA));
 
+       pm_runtime_put_autosuspend(host->dev);
+
        return 0;
 }
 
@@ -2778,12 +2782,57 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static int dw_mci_init_slot_caps(struct dw_mci_slot *slot)
+{
+       struct dw_mci *host = slot->host;
+       const struct dw_mci_drv_data *drv_data = host->drv_data;
+       struct mmc_host *mmc = slot->mmc;
+       int ctrl_id;
+
+       if (host->pdata->caps)
+               mmc->caps = host->pdata->caps;
+
+       /*
+        * Support MMC_CAP_ERASE by default.
+        * It needs to use trim/discard/erase commands.
+        */
+       mmc->caps |= MMC_CAP_ERASE;
+
+       if (host->pdata->pm_caps)
+               mmc->pm_caps = host->pdata->pm_caps;
+
+       if (host->dev->of_node) {
+               ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
+               if (ctrl_id < 0)
+                       ctrl_id = 0;
+       } else {
+               ctrl_id = to_platform_device(host->dev)->id;
+       }
+
+       if (drv_data && drv_data->caps) {
+               if (ctrl_id >= drv_data->num_caps) {
+                       dev_err(host->dev, "invalid controller id %d\n",
+                               ctrl_id);
+                       return -EINVAL;
+               }
+               mmc->caps |= drv_data->caps[ctrl_id];
+       }
+
+       if (host->pdata->caps2)
+               mmc->caps2 = host->pdata->caps2;
+
+       /* Process SDIO IRQs through the sdio_irq_work. */
+       if (mmc->caps & MMC_CAP_SDIO_IRQ)
+               mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+
+       return 0;
+}
+
 static int dw_mci_init_slot(struct dw_mci *host)
 {
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
-       const struct dw_mci_drv_data *drv_data = host->drv_data;
-       int ctrl_id, ret;
+       int ret;
        u32 freq[2];
 
        mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
@@ -2817,38 +2866,13 @@ static int dw_mci_init_slot(struct dw_mci *host)
        if (!mmc->ocr_avail)
                mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
-       if (host->pdata->caps)
-               mmc->caps = host->pdata->caps;
-
-       /*
-        * Support MMC_CAP_ERASE by default.
-        * It needs to use trim/discard/erase commands.
-        */
-       mmc->caps |= MMC_CAP_ERASE;
-
-       if (host->pdata->pm_caps)
-               mmc->pm_caps = host->pdata->pm_caps;
-
-       if (host->dev->of_node) {
-               ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
-               if (ctrl_id < 0)
-                       ctrl_id = 0;
-       } else {
-               ctrl_id = to_platform_device(host->dev)->id;
-       }
-       if (drv_data && drv_data->caps)
-               mmc->caps |= drv_data->caps[ctrl_id];
-
-       if (host->pdata->caps2)
-               mmc->caps2 = host->pdata->caps2;
-
        ret = mmc_of_parse(mmc);
        if (ret)
                goto err_host_allocated;
 
-       /* Process SDIO IRQs through the sdio_irq_work. */
-       if (mmc->caps & MMC_CAP_SDIO_IRQ)
-               mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+       ret = dw_mci_init_slot_caps(slot);
+       if (ret)
+               goto err_host_allocated;
 
        /* Useful defaults if platform data is unset. */
        if (host->use_dma == TRANS_MODE_IDMAC) {
index e3124f06a47ef52840dc5abb77a7febd104b083d..1424bd490dd1bc1bcbd71dd4b2d803508db337b0 100644 (file)
@@ -543,6 +543,7 @@ struct dw_mci_slot {
 /**
  * dw_mci driver data - dw-mshc implementation specific driver data.
  * @caps: mmc subsystem specified capabilities of the controller(s).
+ * @num_caps: number of capabilities specified by @caps.
  * @init: early implementation specific initialization.
  * @set_ios: handle bus specific extensions.
  * @parse_dt: parse implementation specific device tree properties.
@@ -554,6 +555,7 @@ struct dw_mci_slot {
  */
 struct dw_mci_drv_data {
        unsigned long   *caps;
+       u32             num_caps;
        int             (*init)(struct dw_mci *host);
        void            (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
        int             (*parse_dt)(struct dw_mci *host);
index 6d1a983e622722b527d8a3c1b6cdea449c88d180..82c4f05f91d8781528a365d97b3033472df987f4 100644 (file)
@@ -654,9 +654,36 @@ static void byt_read_dsm(struct sdhci_pci_slot *slot)
        slot->chip->rpm_retune = intel_host->d3_retune;
 }
 
-static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
+static int intel_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+       int err = sdhci_execute_tuning(mmc, opcode);
+       struct sdhci_host *host = mmc_priv(mmc);
+
+       if (err)
+               return err;
+
+       /*
+        * Tuning can leave the IP in an active state (Buffer Read Enable bit
+        * set) which prevents the entry to low power states (i.e. S0i3). Data
+        * reset will clear it.
+        */
+       sdhci_reset(host, SDHCI_RESET_DATA);
+
+       return 0;
+}
+
+static void byt_probe_slot(struct sdhci_pci_slot *slot)
 {
+       struct mmc_host_ops *ops = &slot->host->mmc_host_ops;
+
        byt_read_dsm(slot);
+
+       ops->execute_tuning = intel_execute_tuning;
+}
+
+static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
+{
+       byt_probe_slot(slot);
        slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
                                 MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
                                 MMC_CAP_CMD_DURING_TFR |
@@ -779,7 +806,7 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
        int err;
 
-       byt_read_dsm(slot);
+       byt_probe_slot(slot);
 
        err = ni_set_max_freq(slot);
        if (err)
@@ -792,7 +819,7 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
-       byt_read_dsm(slot);
+       byt_probe_slot(slot);
        slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
                                 MMC_CAP_WAIT_WHILE_BUSY;
        return 0;
@@ -800,7 +827,7 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 
 static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 {
-       byt_read_dsm(slot);
+       byt_probe_slot(slot);
        slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY |
                                 MMC_CAP_AGGRESSIVE_PM | MMC_CAP_CD_WAKE;
        slot->cd_idx = 0;
index 8328d395e332919b5f5736dc2fc1a519b8951896..3127bc8633ca511889e8098d1a996c30c6d28b3f 100644 (file)
@@ -2005,7 +2005,10 @@ static void netback_changed(struct xenbus_device *dev,
        case XenbusStateInitialised:
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
+               break;
+
        case XenbusStateUnknown:
+               wake_up_all(&module_unload_q);
                break;
 
        case XenbusStateInitWait:
@@ -2136,7 +2139,9 @@ static int xennet_remove(struct xenbus_device *dev)
                xenbus_switch_state(dev, XenbusStateClosing);
                wait_event(module_unload_q,
                           xenbus_read_driver_state(dev->otherend) ==
-                          XenbusStateClosing);
+                          XenbusStateClosing ||
+                          xenbus_read_driver_state(dev->otherend) ==
+                          XenbusStateUnknown);
 
                xenbus_switch_state(dev, XenbusStateClosed);
                wait_event(module_unload_q,
index 0fe7ea35c2217406af6f8c071a417e08e98dab6a..817e5e2766da36b7312e6992952b073ae2e0111a 100644 (file)
@@ -2844,7 +2844,7 @@ out:
 }
 
 static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
-               struct nvme_id_ns *id, bool *new)
+               struct nvme_id_ns *id)
 {
        struct nvme_ctrl *ctrl = ns->ctrl;
        bool is_shared = id->nmic & (1 << 0);
@@ -2860,8 +2860,6 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
                        ret = PTR_ERR(head);
                        goto out_unlock;
                }
-
-               *new = true;
        } else {
                struct nvme_ns_ids ids;
 
@@ -2873,8 +2871,6 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
                        ret = -EINVAL;
                        goto out_unlock;
                }
-
-               *new = false;
        }
 
        list_add_tail(&ns->siblings, &head->list);
@@ -2945,7 +2941,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        struct nvme_id_ns *id;
        char disk_name[DISK_NAME_LEN];
        int node = dev_to_node(ctrl->dev), flags = GENHD_FL_EXT_DEVT;
-       bool new = true;
 
        ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node);
        if (!ns)
@@ -2971,7 +2966,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        if (id->ncap == 0)
                goto out_free_id;
 
-       if (nvme_init_ns_head(ns, nsid, id, &new))
+       if (nvme_init_ns_head(ns, nsid, id))
                goto out_free_id;
        nvme_setup_streams_ns(ctrl, ns);
        
@@ -3037,8 +3032,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
                pr_warn("%s: failed to register lightnvm sysfs group for identification\n",
                        ns->disk->disk_name);
 
-       if (new)
-               nvme_mpath_add_disk(ns->head);
+       nvme_mpath_add_disk(ns->head);
        nvme_mpath_add_disk_links(ns);
        return;
  out_unlink_ns:
index 5dd4ceefed8fe0d0897aa8dadb1d266174b2eb02..a1c58e35075e9e180cae240d6951c807bb7a4a82 100644 (file)
@@ -493,7 +493,7 @@ EXPORT_SYMBOL_GPL(nvmf_should_reconnect);
  */
 int nvmf_register_transport(struct nvmf_transport_ops *ops)
 {
-       if (!ops->create_ctrl || !ops->module)
+       if (!ops->create_ctrl)
                return -EINVAL;
 
        down_write(&nvmf_transports_rwsem);
index 3b211d9e58b8419855b29a87f1019b0d687714d4..b7e5c6db4d92fe61313fdb9120cef307204bfd70 100644 (file)
@@ -198,11 +198,16 @@ void nvme_mpath_add_disk(struct nvme_ns_head *head)
 {
        if (!head->disk)
                return;
-       device_add_disk(&head->subsys->dev, head->disk);
-       if (sysfs_create_group(&disk_to_dev(head->disk)->kobj,
-                       &nvme_ns_id_attr_group))
-               pr_warn("%s: failed to create sysfs group for identification\n",
-                       head->disk->disk_name);
+
+       mutex_lock(&head->subsys->lock);
+       if (!(head->disk->flags & GENHD_FL_UP)) {
+               device_add_disk(&head->subsys->dev, head->disk);
+               if (sysfs_create_group(&disk_to_dev(head->disk)->kobj,
+                               &nvme_ns_id_attr_group))
+                       pr_warn("%s: failed to create sysfs group for identification\n",
+                               head->disk->disk_name);
+       }
+       mutex_unlock(&head->subsys->lock);
 }
 
 void nvme_mpath_add_disk_links(struct nvme_ns *ns)
index 73036d2fbbd58da19fbcd880accafdcb3f8165e7..5933a5c732e8349731766eeb7b7c0b0b9b6bea6c 100644 (file)
@@ -1459,7 +1459,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
        nvmeq->cq_vector = qid - 1;
        result = adapter_alloc_cq(dev, qid, nvmeq);
        if (result < 0)
-               return result;
+               goto release_vector;
 
        result = adapter_alloc_sq(dev, qid, nvmeq);
        if (result < 0)
@@ -1473,9 +1473,12 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
        return result;
 
  release_sq:
+       dev->online_queues--;
        adapter_delete_sq(dev, qid);
  release_cq:
        adapter_delete_cq(dev, qid);
+ release_vector:
+       nvmeq->cq_vector = -1;
        return result;
 }
 
index 3a51ed50eff24a4c2541b6051a2918f41920467d..4d84a73ee12d06907ea94ef77e3e654d6e2b2033 100644 (file)
@@ -1051,7 +1051,7 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue,
        struct nvme_rdma_device *dev = queue->device;
        struct ib_device *ibdev = dev->dev;
 
-       if (!blk_rq_bytes(rq))
+       if (!blk_rq_payload_bytes(rq))
                return;
 
        if (req->mr) {
@@ -1166,7 +1166,7 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
 
        c->common.flags |= NVME_CMD_SGL_METABUF;
 
-       if (!blk_rq_bytes(rq))
+       if (!blk_rq_payload_bytes(rq))
                return nvme_rdma_set_sg_null(c);
 
        req->sg_table.sgl = req->first_sgl;
index 0bd737117a80a172745aab1868fb8a4ecf6f1e8c..a78029e4e5f481b58bd628537315d3e7e9882f1a 100644 (file)
@@ -520,9 +520,12 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
                goto fail;
        }
 
-       /* either variant of SGLs is fine, as we don't support metadata */
-       if (unlikely((flags & NVME_CMD_SGL_ALL) != NVME_CMD_SGL_METABUF &&
-                    (flags & NVME_CMD_SGL_ALL) != NVME_CMD_SGL_METASEG)) {
+       /*
+        * For fabrics, PSDT field shall describe metadata pointer (MPTR) that
+        * contains an address of a single contiguous physical buffer that is
+        * byte aligned.
+        */
+       if (unlikely((flags & NVME_CMD_SGL_ALL) != NVME_CMD_SGL_METABUF)) {
                status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
                goto fail;
        }
index 7991ec3a17db9238c4fddaadc2faaa9fb32ce0cb..861d1509b22bf412e2a9bfaee408a4fcb3ad3de4 100644 (file)
@@ -184,7 +184,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
                return BLK_STS_OK;
        }
 
-       if (blk_rq_bytes(req)) {
+       if (blk_rq_payload_bytes(req)) {
                iod->sg_table.sgl = iod->first_sgl;
                if (sg_alloc_table_chained(&iod->sg_table,
                                blk_rq_nr_phys_segments(req),
@@ -193,7 +193,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 
                iod->req.sg = iod->sg_table.sgl;
                iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl);
-               iod->req.transfer_len = blk_rq_bytes(req);
+               iod->req.transfer_len = blk_rq_payload_bytes(req);
        }
 
        blk_mq_start_request(req);
index 369d48d6c6f1a53d4bc6ab5dd0b13a33eeccd90b..365447240d95fe2bb2d484bddca71da3572daaa9 100644 (file)
@@ -401,6 +401,10 @@ void pci_release_resource(struct pci_dev *dev, int resno)
        struct resource *res = dev->resource + resno;
 
        pci_info(dev, "BAR %d: releasing %pR\n", resno, res);
+
+       if (!res->parent)
+               return;
+
        release_resource(res);
        res->end = resource_size(res) - 1;
        res->start = 0;
index 1fda9d6c7ea3f39b3768f142136b7e11f9e0c870..4b91ff74779bead16a60f96bf2566e947989e179 100644 (file)
@@ -716,7 +716,7 @@ static const char * const uart_b_groups[] = {
        "uart_tx_b_x", "uart_rx_b_x", "uart_cts_b_x", "uart_rts_b_x",
 };
 
-static const char * const uart_ao_b_gpioz_groups[] = {
+static const char * const uart_ao_b_z_groups[] = {
        "uart_ao_tx_b_z", "uart_ao_rx_b_z",
        "uart_ao_cts_b_z", "uart_ao_rts_b_z",
 };
@@ -855,7 +855,7 @@ static struct meson_pmx_func meson_axg_periphs_functions[] = {
        FUNCTION(nand),
        FUNCTION(uart_a),
        FUNCTION(uart_b),
-       FUNCTION(uart_ao_b_gpioz),
+       FUNCTION(uart_ao_b_z),
        FUNCTION(i2c0),
        FUNCTION(i2c1),
        FUNCTION(i2c2),
index d1a01311c1a2937b6863bea6b696566e376f8ac1..5e3df194723e1a1f1757fff08dd3c89069381350 100644 (file)
@@ -376,6 +376,7 @@ static int intel_hid_remove(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
 
+       device_init_wakeup(&device->dev, false);
        acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
        intel_hid_set_enable(&device->dev, false);
        intel_button_array_enable(&device->dev, false);
index b703d6f5b099b3d0d74b77d60d2e5401ff3b816e..c13780b8dabbe089c24a2b5c323f1510f589153e 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
 #include <linux/kernel.h>
@@ -97,9 +98,35 @@ out_unknown:
        dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
 }
 
-static int intel_vbtn_probe(struct platform_device *device)
+static void detect_tablet_mode(struct platform_device *device)
 {
+       const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
+       struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
+       acpi_handle handle = ACPI_HANDLE(&device->dev);
        struct acpi_buffer vgbs_output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       int m;
+
+       if (!(chassis_type && strcmp(chassis_type, "31") == 0))
+               goto out;
+
+       status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output);
+       if (ACPI_FAILURE(status))
+               goto out;
+
+       obj = vgbs_output.pointer;
+       if (!(obj && obj->type == ACPI_TYPE_INTEGER))
+               goto out;
+
+       m = !(obj->integer.value & TABLET_MODE_FLAG);
+       input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
+out:
+       kfree(vgbs_output.pointer);
+}
+
+static int intel_vbtn_probe(struct platform_device *device)
+{
        acpi_handle handle = ACPI_HANDLE(&device->dev);
        struct intel_vbtn_priv *priv;
        acpi_status status;
@@ -122,22 +149,7 @@ static int intel_vbtn_probe(struct platform_device *device)
                return err;
        }
 
-       /*
-        * VGBS being present and returning something means we have
-        * a tablet mode switch.
-        */
-       status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output);
-       if (ACPI_SUCCESS(status)) {
-               union acpi_object *obj = vgbs_output.pointer;
-
-               if (obj && obj->type == ACPI_TYPE_INTEGER) {
-                       int m = !(obj->integer.value & TABLET_MODE_FLAG);
-
-                       input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
-               }
-       }
-
-       kfree(vgbs_output.pointer);
+       detect_tablet_mode(device);
 
        status = acpi_install_notify_handler(handle,
                                             ACPI_DEVICE_NOTIFY,
@@ -154,6 +166,7 @@ static int intel_vbtn_remove(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
 
+       device_init_wakeup(&device->dev, false);
        acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
 
        /*
index c0c8945603cbbdd6284ff60b5df4d118502305d5..8796211ef24acdab6e20f976716c18577d5a8fed 100644 (file)
@@ -945,7 +945,7 @@ static int wmi_dev_probe(struct device *dev)
                wblock->char_dev.mode = 0444;
                ret = misc_register(&wblock->char_dev);
                if (ret) {
-                       dev_warn(dev, "failed to register char dev: %d", ret);
+                       dev_warn(dev, "failed to register char dev: %d\n", ret);
                        ret = -ENOMEM;
                        goto probe_misc_failure;
                }
@@ -1048,7 +1048,7 @@ static int wmi_create_device(struct device *wmi_bus_dev,
 
        if (result) {
                dev_warn(wmi_bus_dev,
-                        "%s data block query control method not found",
+                        "%s data block query control method not found\n",
                         method);
                return result;
        }
@@ -1198,7 +1198,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
 
                retval = device_add(&wblock->dev.dev);
                if (retval) {
-                       dev_err(wmi_bus_dev, "failed to register %pULL\n",
+                       dev_err(wmi_bus_dev, "failed to register %pUL\n",
                                wblock->gblock.guid);
                        if (debug_event)
                                wmi_method_enable(wblock, 0);
index cfb42f5eccb21d82adbd4b07aadc88eab310d99f..750f931974119804734945a501e0786ca003977d 100644 (file)
@@ -470,13 +470,21 @@ static int imx_gpc_probe(struct platform_device *pdev)
 
 static int imx_gpc_remove(struct platform_device *pdev)
 {
+       struct device_node *pgc_node;
        int ret;
 
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
        /*
         * If the old DT binding is used the toplevel driver needs to
         * de-register the power domains
         */
-       if (!of_get_child_by_name(pdev->dev.of_node, "pgc")) {
+       if (!pgc_node) {
                of_genpd_del_provider(pdev->dev.of_node);
 
                ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
index aff773bcebdb59f14a88a3c92b779f5c03de3ba5..37460cd6cabb806ecdf536f5a44019ff845164b9 100644 (file)
@@ -226,6 +226,7 @@ config ZIIRAVE_WATCHDOG
 config RAVE_SP_WATCHDOG
        tristate "RAVE SP Watchdog timer"
        depends on RAVE_SP_CORE
+       depends on NVMEM || !NVMEM
        select WATCHDOG_CORE
        help
          Support for the watchdog on RAVE SP device.
@@ -903,6 +904,7 @@ config F71808E_WDT
 config SP5100_TCO
        tristate "AMD/ATI SP5100 TCO Timer/Watchdog"
        depends on X86 && PCI
+       select WATCHDOG_CORE
        ---help---
          Hardware watchdog driver for the AMD/ATI SP5100 chipset. The TCO
          (Total Cost of Ownership) timer is a watchdog timer that will reboot
@@ -1008,6 +1010,7 @@ config WAFER_WDT
 config I6300ESB_WDT
        tristate "Intel 6300ESB Timer/Watchdog"
        depends on PCI
+       select WATCHDOG_CORE
        ---help---
          Hardware driver for the watchdog timer built into the Intel
          6300ESB controller hub.
@@ -1837,6 +1840,7 @@ config WATCHDOG_SUN4V
 config XEN_WDT
        tristate "Xen Watchdog support"
        depends on XEN
+       select WATCHDOG_CORE
        help
          Say Y here to support the hypervisor watchdog capability provided
          by Xen 4.0 and newer.  The watchdog timeout period is normally one
index 1ab4bd11f5f3f01f34b1a0055f836c9a0ce755ba..762378f1811cc9069dc6171edb55aaa3610b82fa 100644 (file)
@@ -755,8 +755,8 @@ out:
        mutex_unlock(&irq_mapping_update_lock);
        return irq;
 error_irq:
-       for (; i >= 0; i--)
-               __unbind_from_irq(irq + i);
+       while (nvec--)
+               __unbind_from_irq(irq + nvec);
        mutex_unlock(&irq_mapping_update_lock);
        return ret;
 }
index 156e5aea36db964dfaac58784044ca1cd0cf57c7..b1092fbefa6309d2535b17b78979b6f3fa9b2b42 100644 (file)
@@ -416,7 +416,7 @@ static int pvcalls_back_connect(struct xenbus_device *dev,
                                        sock);
        if (!map) {
                ret = -EFAULT;
-               sock_release(map->sock);
+               sock_release(sock);
        }
 
 out:
index aedbee3b28386a1cc1625334fe431875bd787277..2f11ca72a281410122ef0b4f0dc4f173ef7c6697 100644 (file)
@@ -73,20 +73,25 @@ struct sock_mapping {
                        wait_queue_head_t inflight_conn_req;
                } active;
                struct {
-               /* Socket status */
+               /*
+                * Socket status, needs to be 64-bit aligned due to the
+                * test_and_* functions which have this requirement on arm64.
+                */
 #define PVCALLS_STATUS_UNINITALIZED  0
 #define PVCALLS_STATUS_BIND          1
 #define PVCALLS_STATUS_LISTEN        2
-                       uint8_t status;
+                       uint8_t status __attribute__((aligned(8)));
                /*
                 * Internal state-machine flags.
                 * Only one accept operation can be inflight for a socket.
                 * Only one poll operation can be inflight for a given socket.
+                * flags needs to be 64-bit aligned due to the test_and_*
+                * functions which have this requirement on arm64.
                 */
 #define PVCALLS_FLAG_ACCEPT_INFLIGHT 0
 #define PVCALLS_FLAG_POLL_INFLIGHT   1
 #define PVCALLS_FLAG_POLL_RET        2
-                       uint8_t flags;
+                       uint8_t flags __attribute__((aligned(8)));
                        uint32_t inflight_req_id;
                        struct sock_mapping *accept_map;
                        wait_queue_head_t inflight_accept_req;
index 4a181fcb51751dc2cbc8fda10930a47bc883380e..fe09ef9c21f349a55d31261b5dd416b1bde2a3aa 100644 (file)
@@ -1058,6 +1058,27 @@ retry:
        return 0;
 }
 
+static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
+{
+       struct gendisk *disk = get_gendisk(bdev->bd_dev, partno);
+
+       if (!disk)
+               return NULL;
+       /*
+        * Now that we hold gendisk reference we make sure bdev we looked up is
+        * not stale. If it is, it means device got removed and created before
+        * we looked up gendisk and we fail open in such case. Associating
+        * unhashed bdev with newly created gendisk could lead to two bdevs
+        * (and thus two independent caches) being associated with one device
+        * which is bad.
+        */
+       if (inode_unhashed(bdev->bd_inode)) {
+               put_disk_and_module(disk);
+               return NULL;
+       }
+       return disk;
+}
+
 /**
  * bd_start_claiming - start claiming a block device
  * @bdev: block device of interest
@@ -1094,7 +1115,7 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
         * @bdev might not have been initialized properly yet, look up
         * and grab the outer block device the hard way.
         */
-       disk = get_gendisk(bdev->bd_dev, &partno);
+       disk = bdev_get_gendisk(bdev, &partno);
        if (!disk)
                return ERR_PTR(-ENXIO);
 
@@ -1111,8 +1132,7 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
        else
                whole = bdgrab(bdev);
 
-       module_put(disk->fops->owner);
-       put_disk(disk);
+       put_disk_and_module(disk);
        if (!whole)
                return ERR_PTR(-ENOMEM);
 
@@ -1407,10 +1427,10 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part);
 static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 {
        struct gendisk *disk;
-       struct module *owner;
        int ret;
        int partno;
        int perm = 0;
+       bool first_open = false;
 
        if (mode & FMODE_READ)
                perm |= MAY_READ;
@@ -1430,14 +1450,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
  restart:
 
        ret = -ENXIO;
-       disk = get_gendisk(bdev->bd_dev, &partno);
+       disk = bdev_get_gendisk(bdev, &partno);
        if (!disk)
                goto out;
-       owner = disk->fops->owner;
 
        disk_block_events(disk);
        mutex_lock_nested(&bdev->bd_mutex, for_part);
        if (!bdev->bd_openers) {
+               first_open = true;
                bdev->bd_disk = disk;
                bdev->bd_queue = disk->queue;
                bdev->bd_contains = bdev;
@@ -1463,8 +1483,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                        bdev->bd_queue = NULL;
                                        mutex_unlock(&bdev->bd_mutex);
                                        disk_unblock_events(disk);
-                                       put_disk(disk);
-                                       module_put(owner);
+                                       put_disk_and_module(disk);
                                        goto restart;
                                }
                        }
@@ -1524,15 +1543,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                        if (ret)
                                goto out_unlock_bdev;
                }
-               /* only one opener holds refs to the module and disk */
-               put_disk(disk);
-               module_put(owner);
        }
        bdev->bd_openers++;
        if (for_part)
                bdev->bd_part_count++;
        mutex_unlock(&bdev->bd_mutex);
        disk_unblock_events(disk);
+       /* only one opener holds refs to the module and disk */
+       if (!first_open)
+               put_disk_and_module(disk);
        return 0;
 
  out_clear:
@@ -1546,8 +1565,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
  out_unlock_bdev:
        mutex_unlock(&bdev->bd_mutex);
        disk_unblock_events(disk);
-       put_disk(disk);
-       module_put(owner);
+       put_disk_and_module(disk);
  out:
        bdput(bdev);
 
@@ -1770,8 +1788,6 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
                        disk->fops->release(disk, mode);
        }
        if (!bdev->bd_openers) {
-               struct module *owner = disk->fops->owner;
-
                disk_put_part(bdev->bd_part);
                bdev->bd_part = NULL;
                bdev->bd_disk = NULL;
@@ -1779,8 +1795,7 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
                        victim = bdev->bd_contains;
                bdev->bd_contains = NULL;
 
-               put_disk(disk);
-               module_put(owner);
+               put_disk_and_module(disk);
        }
        mutex_unlock(&bdev->bd_mutex);
        bdput(bdev);
index 6582c4507e6c9d1fdf2876c13c424f0c5830495c..0e5bd3e3344e7983e6bdf38dba1adfba17500eba 100644 (file)
@@ -3964,6 +3964,32 @@ void ceph_put_fmode(struct ceph_inode_info *ci, int fmode)
                ceph_check_caps(ci, 0, NULL);
 }
 
+/*
+ * For a soon-to-be unlinked file, drop the AUTH_RDCACHE caps. If it
+ * looks like the link count will hit 0, drop any other caps (other
+ * than PIN) we don't specifically want (due to the file still being
+ * open).
+ */
+int ceph_drop_caps_for_unlink(struct inode *inode)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
+
+       spin_lock(&ci->i_ceph_lock);
+       if (inode->i_nlink == 1) {
+               drop |= ~(__ceph_caps_wanted(ci) | CEPH_CAP_PIN);
+
+               ci->i_ceph_flags |= CEPH_I_NODELAY;
+               if (__ceph_caps_dirty(ci)) {
+                       struct ceph_mds_client *mdsc =
+                               ceph_inode_to_client(inode)->mdsc;
+                       __cap_delay_requeue_front(mdsc, ci);
+               }
+       }
+       spin_unlock(&ci->i_ceph_lock);
+       return drop;
+}
+
 /*
  * Helpers for embedding cap and dentry lease releases into mds
  * requests.
index 0c4346806e17a6f9a70e35fdafab13440c426d65..f1d9c6cc0491d7f9f33e4073db9785afac669cc8 100644 (file)
@@ -1002,26 +1002,6 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
        return err;
 }
 
-/*
- * For a soon-to-be unlinked file, drop the AUTH_RDCACHE caps.  If it
- * looks like the link count will hit 0, drop any other caps (other
- * than PIN) we don't specifically want (due to the file still being
- * open).
- */
-static int drop_caps_for_unlink(struct inode *inode)
-{
-       struct ceph_inode_info *ci = ceph_inode(inode);
-       int drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
-
-       spin_lock(&ci->i_ceph_lock);
-       if (inode->i_nlink == 1) {
-               drop |= ~(__ceph_caps_wanted(ci) | CEPH_CAP_PIN);
-               ci->i_ceph_flags |= CEPH_I_NODELAY;
-       }
-       spin_unlock(&ci->i_ceph_lock);
-       return drop;
-}
-
 /*
  * rmdir and unlink are differ only by the metadata op code
  */
@@ -1056,7 +1036,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
        set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
        req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
        req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
-       req->r_inode_drop = drop_caps_for_unlink(inode);
+       req->r_inode_drop = ceph_drop_caps_for_unlink(inode);
        err = ceph_mdsc_do_request(mdsc, dir, req);
        if (!err && !req->r_reply_info.head->is_dentry)
                d_delete(dentry);
@@ -1104,8 +1084,10 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
        req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
        /* release LINK_RDCACHE on source inode (mds will lock it) */
        req->r_old_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL;
-       if (d_really_is_positive(new_dentry))
-               req->r_inode_drop = drop_caps_for_unlink(d_inode(new_dentry));
+       if (d_really_is_positive(new_dentry)) {
+               req->r_inode_drop =
+                       ceph_drop_caps_for_unlink(d_inode(new_dentry));
+       }
        err = ceph_mdsc_do_request(mdsc, old_dir, req);
        if (!err && !req->r_reply_info.head->is_dentry) {
                /*
index a62d2a9841dc2b0487181155373c03eac60f8a02..fb2bc9c15a2378ceb5712269ab93e677c360f5d0 100644 (file)
@@ -225,6 +225,7 @@ static int parse_fsopt_token(char *c, void *private)
                        return -ENOMEM;
                break;
        case Opt_mds_namespace:
+               kfree(fsopt->mds_namespace);
                fsopt->mds_namespace = kstrndup(argstr[0].from,
                                                argstr[0].to-argstr[0].from,
                                                GFP_KERNEL);
@@ -232,6 +233,7 @@ static int parse_fsopt_token(char *c, void *private)
                        return -ENOMEM;
                break;
        case Opt_fscache_uniq:
+               kfree(fsopt->fscache_uniq);
                fsopt->fscache_uniq = kstrndup(argstr[0].from,
                                               argstr[0].to-argstr[0].from,
                                               GFP_KERNEL);
@@ -711,14 +713,17 @@ static int __init init_caches(void)
                goto bad_dentry;
 
        ceph_file_cachep = KMEM_CACHE(ceph_file_info, SLAB_MEM_SPREAD);
-
        if (!ceph_file_cachep)
                goto bad_file;
 
-       if ((error = ceph_fscache_register()))
-               goto bad_file;
+       error = ceph_fscache_register();
+       if (error)
+               goto bad_fscache;
 
        return 0;
+
+bad_fscache:
+       kmem_cache_destroy(ceph_file_cachep);
 bad_file:
        kmem_cache_destroy(ceph_dentry_cachep);
 bad_dentry:
@@ -836,7 +841,6 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
        int err;
        unsigned long started = jiffies;  /* note the start time */
        struct dentry *root;
-       int first = 0;   /* first vfsmount for this super_block */
 
        dout("mount start %p\n", fsc);
        mutex_lock(&fsc->client->mount_mutex);
@@ -861,17 +865,17 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
                        path = fsc->mount_options->server_path + 1;
                        dout("mount opening path %s\n", path);
                }
+
+               err = ceph_fs_debugfs_init(fsc);
+               if (err < 0)
+                       goto out;
+
                root = open_root_dentry(fsc, path, started);
                if (IS_ERR(root)) {
                        err = PTR_ERR(root);
                        goto out;
                }
                fsc->sb->s_root = dget(root);
-               first = 1;
-
-               err = ceph_fs_debugfs_init(fsc);
-               if (err < 0)
-                       goto fail;
        } else {
                root = dget(fsc->sb->s_root);
        }
@@ -881,11 +885,6 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
        mutex_unlock(&fsc->client->mount_mutex);
        return root;
 
-fail:
-       if (first) {
-               dput(fsc->sb->s_root);
-               fsc->sb->s_root = NULL;
-       }
 out:
        mutex_unlock(&fsc->client->mount_mutex);
        return ERR_PTR(err);
index 21b2e5b004eb72ba10057df37c6907766aed5993..1c2086e0fec27a60577c7a676b00fac67fb11102 100644 (file)
@@ -987,7 +987,7 @@ extern void ceph_check_caps(struct ceph_inode_info *ci, int flags,
                            struct ceph_mds_session *session);
 extern void ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
 extern void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc);
-
+extern int  ceph_drop_caps_for_unlink(struct inode *inode);
 extern int ceph_encode_inode_release(void **p, struct inode *inode,
                                     int mds, int drop, int unless, int force);
 extern int ceph_encode_dentry_release(void **p, struct dentry *dn,
index a0ca9e48e9937da671739e24d6d7dc2a4867d7ac..1357ef563893a1a8f0d2967eeb4b6e7b0ee6444a 100644 (file)
@@ -1274,8 +1274,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
         */
        if (dio->is_async && iov_iter_rw(iter) == WRITE) {
                retval = 0;
-               if ((iocb->ki_filp->f_flags & O_DSYNC) ||
-                   IS_SYNC(iocb->ki_filp->f_mapping->host))
+               if (iocb->ki_flags & IOCB_DSYNC)
                        retval = dio_set_defer_completion(dio);
                else if (!dio->inode->i_sb->s_dio_done_wq) {
                        /*
index fd975524f4603387e28078d13b175b5df2443021..05c66e05ae20f0bbe08c713de9feddf13c813982 100644 (file)
@@ -767,7 +767,7 @@ int
 xfs_scrub_agfl(
        struct xfs_scrub_context        *sc)
 {
-       struct xfs_scrub_agfl_info      sai = { 0 };
+       struct xfs_scrub_agfl_info      sai;
        struct xfs_agf                  *agf;
        xfs_agnumber_t                  agno;
        unsigned int                    agflcount;
@@ -795,6 +795,7 @@ xfs_scrub_agfl(
                xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
                goto out;
        }
+       memset(&sai, 0, sizeof(sai));
        sai.sz_entries = agflcount;
        sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount, KM_NOFS);
        if (!sai.entries) {
index 3a55d6fc271b1e6d50aa6ce96c9e84b7c5886e43..7a39f40645f7dddbd41740bce4404dbf36fd635b 100644 (file)
@@ -23,6 +23,7 @@
 #include "xfs_log_format.h"
 #include "xfs_trans_resv.h"
 #include "xfs_bit.h"
+#include "xfs_shared.h"
 #include "xfs_mount.h"
 #include "xfs_defer.h"
 #include "xfs_trans.h"
@@ -456,10 +457,12 @@ xfs_cui_recover(
         * transaction.  Normally, any work that needs to be deferred
         * gets attached to the same defer_ops that scheduled the
         * refcount update.  However, we're in log recovery here, so we
-        * we create our own defer_ops and use that to finish up any
-        * work that doesn't fit.
+        * we use the passed in defer_ops and to finish up any work that
+        * doesn't fit.  We need to reserve enough blocks to handle a
+        * full btree split on either end of the refcount range.
         */
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
+                       mp->m_refc_maxlevels * 2, 0, XFS_TRANS_RESERVE, &tp);
        if (error)
                return error;
        cudp = xfs_trans_get_cud(tp, cuip);
index f3b139c9aa1674a3f652ec622286e9aba616d5c3..49d3124863a81f719efd1774b0b6ac7f651b0a26 100644 (file)
@@ -23,6 +23,7 @@
 #include "xfs_log_format.h"
 #include "xfs_trans_resv.h"
 #include "xfs_bit.h"
+#include "xfs_shared.h"
 #include "xfs_mount.h"
 #include "xfs_defer.h"
 #include "xfs_trans.h"
@@ -470,7 +471,8 @@ xfs_rui_recover(
                }
        }
 
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
+                       mp->m_rmap_maxlevels, 0, XFS_TRANS_RESERVE, &tp);
        if (error)
                return error;
        rudp = xfs_trans_get_rud(tp, ruip);
index 7aba628dc5279858a7608a78839b0e32753bbee6..93588ea3d3d2ca2d664edb4e1b853f5d0dad6a73 100644 (file)
@@ -250,6 +250,7 @@ xfs_parseargs(
                                return -EINVAL;
                        break;
                case Opt_logdev:
+                       kfree(mp->m_logname);
                        mp->m_logname = match_strdup(args);
                        if (!mp->m_logname)
                                return -ENOMEM;
@@ -258,6 +259,7 @@ xfs_parseargs(
                        xfs_warn(mp, "%s option not allowed on this system", p);
                        return -EINVAL;
                case Opt_rtdev:
+                       kfree(mp->m_rtname);
                        mp->m_rtname = match_strdup(args);
                        if (!mp->m_rtname)
                                return -ENOMEM;
index d32b688eb346c9252eb66d73be49fdd477e290de..d23dcdd1bd95a20ba98e4ae65b57d6f225cad7c3 100644 (file)
@@ -56,6 +56,7 @@ struct drm_printer;
 #define DRIVER_ATOMIC                  0x10000
 #define DRIVER_KMS_LEGACY_CONTEXT      0x20000
 #define DRIVER_SYNCOBJ                  0x40000
+#define DRIVER_PREFER_XBGR_30BPP        0x80000
 
 /**
  * struct drm_driver - DRM driver structure
index d0eb659fa733eb91b57a135932f45b1eea8d9975..ce547a25e8aed5d61efd5c0ce9b5c450af4fabcc 100644 (file)
@@ -511,6 +511,7 @@ void zero_fill_bio(struct bio *bio);
 extern struct bio_vec *bvec_alloc(gfp_t, int, unsigned long *, mempool_t *);
 extern void bvec_free(mempool_t *, struct bio_vec *, unsigned int);
 extern unsigned int bvec_nr_vecs(unsigned short idx);
+extern const char *bio_devname(struct bio *bio, char *buffer);
 
 #define bio_set_dev(bio, bdev)                         \
 do {                                           \
@@ -529,9 +530,6 @@ do {                                                \
 #define bio_dev(bio) \
        disk_devt((bio)->bi_disk)
 
-#define bio_devname(bio, buf) \
-       __bdevname(bio_dev(bio), (buf))
-
 #ifdef CONFIG_BLK_CGROUP
 int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css);
 void bio_disassociate_task(struct bio *bio);
index d02a4df3f4737a2ae98cce7928c3dcf4c4167164..d3f264a5b04d9c999a94273c18272416576b17c1 100644 (file)
@@ -27,3 +27,8 @@
 #if __has_feature(address_sanitizer)
 #define __SANITIZE_ADDRESS__
 #endif
+
+/* Clang doesn't have a way to turn it off per-function, yet. */
+#ifdef __noretpoline
+#undef __noretpoline
+#endif
index 901c1ccb3374aaeba42ab3cda3ed4c3e46d75085..e2c7f4369effdbcf9cb46b1904c3cbe84debd2ca 100644 (file)
 #define __weak         __attribute__((weak))
 #define __alias(symbol)        __attribute__((alias(#symbol)))
 
+#ifdef RETPOLINE
+#define __noretpoline __attribute__((indirect_branch("keep")))
+#endif
+
 /*
  * it doesn't make sense on ARM (currently the only user of __naked)
  * to trace naked functions because then mcount is called without
index 5e3531027b5113cc7a9fde0ec0ffc0cdf3389b97..c826b0b5232aff63877bb441fb62e43128b4e976 100644 (file)
@@ -198,6 +198,7 @@ struct gendisk {
        void *private_data;
 
        int flags;
+       struct rw_semaphore lookup_sem;
        struct kobject *slave_dir;
 
        struct timer_rand_state *random;
@@ -600,8 +601,9 @@ extern void delete_partition(struct gendisk *, int);
 extern void printk_all_partitions(void);
 
 extern struct gendisk *__alloc_disk_node(int minors, int node_id);
-extern struct kobject *get_disk(struct gendisk *disk);
+extern struct kobject *get_disk_and_module(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
+extern void put_disk_and_module(struct gendisk *disk);
 extern void blk_register_region(dev_t devt, unsigned long range,
                        struct module *module,
                        struct kobject *(*probe)(dev_t, int *, void *),
index 506a9815113159651da4b98ec5d72700dbe6271f..bc27cf03c41ea5a4b19d87bb82da0f3d36e9390e 100644 (file)
@@ -6,10 +6,10 @@
 #include <linux/types.h>
 
 /* Built-in __init functions needn't be compiled with retpoline */
-#if defined(RETPOLINE) && !defined(MODULE)
-#define __noretpoline __attribute__((indirect_branch("keep")))
+#if defined(__noretpoline) && !defined(MODULE)
+#define __noinitretpoline __noretpoline
 #else
-#define __noretpoline
+#define __noinitretpoline
 #endif
 
 /* These macros are used to mark some functions or 
@@ -47,7 +47,7 @@
 
 /* These are for everybody (although not all archs will actually
    discard it in modules) */
-#define __init         __section(.init.text) __cold  __latent_entropy __noretpoline
+#define __init         __section(.init.text) __cold  __latent_entropy __noinitretpoline
 #define __initdata     __section(.init.data)
 #define __initconst    __section(.init.rodata)
 #define __exitdata     __section(.exit.data)
index b6a29c126cc49285f62995b59dc517f17cdc3af6..2168cc6b8b301dffb8a8333fc699a516c6ab51c7 100644 (file)
@@ -151,6 +151,7 @@ extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
 extern void jump_label_init(void);
+extern void jump_label_invalidate_init(void);
 extern void jump_label_lock(void);
 extern void jump_label_unlock(void);
 extern void arch_jump_label_transform(struct jump_entry *entry,
@@ -198,6 +199,8 @@ static __always_inline void jump_label_init(void)
        static_key_initialized = true;
 }
 
+static inline void jump_label_invalidate_init(void) {}
+
 static __always_inline bool static_key_false(struct static_key *key)
 {
        if (unlikely(static_key_count(key) > 0))
index ce51455e2adf631229d21b43e6afb76b2496790c..3fd291503576f1407e633851bec2b785152e6576 100644 (file)
@@ -472,6 +472,7 @@ extern bool parse_option_str(const char *str, const char *option);
 extern char *next_arg(char *args, char **param, char **val);
 
 extern int core_kernel_text(unsigned long addr);
+extern int init_kernel_text(unsigned long addr);
 extern int core_kernel_data(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
index ac0062b74aed048923c9f08b4a9d74d176ff6c96..6930c63126c78a9ef665b5b5653a60a8773b4d4c 100644 (file)
@@ -1105,7 +1105,6 @@ static inline void kvm_irq_routing_update(struct kvm *kvm)
 {
 }
 #endif
-void kvm_arch_irq_routing_update(struct kvm *kvm);
 
 static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 {
@@ -1114,6 +1113,8 @@ static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 
 #endif /* CONFIG_HAVE_KVM_EVENTFD */
 
+void kvm_arch_irq_routing_update(struct kvm *kvm);
+
 static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
 {
        /*
@@ -1272,4 +1273,7 @@ static inline long kvm_arch_vcpu_async_ioctl(struct file *filp,
 }
 #endif /* CONFIG_HAVE_KVM_VCPU_ASYNC_IOCTL */
 
+void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
+               unsigned long start, unsigned long end);
+
 #endif
index fbc98e2c8228d0b8ca17e4af9be1cb1cddaccd27..e791ebc65c9c0776325cdc5e72de5d995038d7e0 100644 (file)
@@ -5,6 +5,7 @@
 
 #ifndef _LINUX_NOSPEC_H
 #define _LINUX_NOSPEC_H
+#include <asm/barrier.h>
 
 /**
  * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
@@ -29,26 +30,6 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
 }
 #endif
 
-/*
- * Warn developers about inappropriate array_index_nospec() usage.
- *
- * Even if the CPU speculates past the WARN_ONCE branch, the
- * sign bit of @index is taken into account when generating the
- * mask.
- *
- * This warning is compiled out when the compiler can infer that
- * @index and @size are less than LONG_MAX.
- */
-#define array_index_mask_nospec_check(index, size)                             \
-({                                                                             \
-       if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,                      \
-           "array_index_nospec() limited to range of [0, LONG_MAX]\n"))        \
-               _mask = 0;                                                      \
-       else                                                                    \
-               _mask = array_index_mask_nospec(index, size);                   \
-       _mask;                                                                  \
-})
-
 /*
  * array_index_nospec - sanitize an array index after a bounds check
  *
@@ -67,12 +48,11 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
 ({                                                                     \
        typeof(index) _i = (index);                                     \
        typeof(size) _s = (size);                                       \
-       unsigned long _mask = array_index_mask_nospec_check(_i, _s);    \
+       unsigned long _mask = array_index_mask_nospec(_i, _s);          \
                                                                        \
        BUILD_BUG_ON(sizeof(_i) > sizeof(long));                        \
        BUILD_BUG_ON(sizeof(_s) > sizeof(long));                        \
                                                                        \
-       _i &= _mask;                                                    \
-       _i;                                                             \
+       (typeof(_i)) (_i & _mask);                                      \
 })
 #endif /* _LINUX_NOSPEC_H */
index c4df6cee48e6ab41520d73d4a9e12a7be76b0f07..bf00a5a41a90643437e3a750456ff534e9fa7945 100644 (file)
@@ -117,7 +117,7 @@ struct dmx_ts_feed {
  *               specified by @filter_value that will be used on the filter
  *               match logic.
  * @filter_mode:  Contains a 16 bytes (128 bits) filter mode.
- * @parent:      Pointer to struct dmx_section_feed.
+ * @parent:      Back-pointer to struct dmx_section_feed.
  * @priv:        Pointer to private data of the API client.
  *
  *
@@ -130,8 +130,9 @@ struct dmx_section_filter {
        u8 filter_value[DMX_MAX_FILTER_SIZE];
        u8 filter_mask[DMX_MAX_FILTER_SIZE];
        u8 filter_mode[DMX_MAX_FILTER_SIZE];
-       struct dmx_section_feed *parent; /* Back-pointer */
-       void *priv; /* Pointer to private data of the API client */
+       struct dmx_section_feed *parent;
+
+       void *priv;
 };
 
 /**
@@ -193,6 +194,10 @@ struct dmx_section_feed {
  * @buffer2:           Pointer to the tail of the filtered TS packets, or NULL.
  * @buffer2_length:    Length of the TS data in buffer2.
  * @source:            Indicates which TS feed is the source of the callback.
+ * @buffer_flags:      Address where buffer flags are stored. Those are
+ *                     used to report discontinuity users via DVB
+ *                     memory mapped API, as defined by
+ *                     &enum dmx_buffer_flags.
  *
  * This function callback prototype, provided by the client of the demux API,
  * is called from the demux code. The function is only called when filtering
@@ -245,7 +250,8 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1,
                         size_t buffer1_length,
                         const u8 *buffer2,
                         size_t buffer2_length,
-                        struct dmx_ts_feed *source);
+                        struct dmx_ts_feed *source,
+                        u32 *buffer_flags);
 
 /**
  * typedef dmx_section_cb - DVB demux TS filter callback function prototype
@@ -261,6 +267,10 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1,
  *                     including headers and CRC.
  * @source:            Indicates which section feed is the source of the
  *                     callback.
+ * @buffer_flags:      Address where buffer flags are stored. Those are
+ *                     used to report discontinuity users via DVB
+ *                     memory mapped API, as defined by
+ *                     &enum dmx_buffer_flags.
  *
  * This function callback prototype, provided by the client of the demux API,
  * is called from the demux code. The function is only called when
@@ -286,7 +296,8 @@ typedef int (*dmx_section_cb)(const u8 *buffer1,
                              size_t buffer1_len,
                              const u8 *buffer2,
                              size_t buffer2_len,
-                             struct dmx_section_filter *source);
+                             struct dmx_section_filter *source,
+                             u32 *buffer_flags);
 
 /*
  * DVB Front-End
index 2f5cb2c7b6a75dcf582d9f8fb6e97985c8b47888..baafa3b8aca4140ec3fe426138bada16e0a1da6f 100644 (file)
@@ -163,6 +163,7 @@ struct dmxdev_filter {
  * @demux:             pointer to &struct dmx_demux.
  * @filternum:         number of filters.
  * @capabilities:      demux capabilities as defined by &enum dmx_demux_caps.
+ * @may_do_mmap:       flag used to indicate if the device may do mmap.
  * @exit:              flag to indicate that the demux is being released.
  * @dvr_orig_fe:       pointer to &struct dmx_frontend.
  * @dvr_buffer:                embedded &struct dvb_ringbuffer for DVB output.
@@ -180,6 +181,7 @@ struct dmxdev {
        int filternum;
        int capabilities;
 
+       unsigned int may_do_mmap:1;
        unsigned int exit:1;
 #define DMXDEV_CAP_DUPLEX 1
        struct dmx_frontend *dvr_orig_fe;
index b07092038f4bde977cd50a40c16e263d2f4293ed..3b6aeca7a49e44f5dd2a602842d14362951404ae 100644 (file)
@@ -115,6 +115,8 @@ struct dvb_demux_filter {
  * @pid:       PID to be filtered.
  * @timeout:   feed timeout.
  * @filter:    pointer to &struct dvb_demux_filter.
+ * @buffer_flags: Buffer flags used to report discontinuity users via DVB
+ *               memory mapped API, as defined by &enum dmx_buffer_flags.
  * @ts_type:   type of TS, as defined by &enum ts_filter_type.
  * @pes_type:  type of PES, as defined by &enum dmx_ts_pes.
  * @cc:                MPEG-TS packet continuity counter
@@ -145,6 +147,8 @@ struct dvb_demux_feed {
        ktime_t timeout;
        struct dvb_demux_filter *filter;
 
+       u32 buffer_flags;
+
        enum ts_filter_type ts_type;
        enum dmx_ts_pes pes_type;
 
index 01d1202d1a55b8ed30d92e4ad46b20cbd17409a0..8cb88452cd6c287ced6cea133419096ef1a22955 100644 (file)
@@ -85,6 +85,12 @@ struct dvb_buffer {
  * @nonblocking:
  *             If different than zero, device is operating on non-blocking
  *             mode.
+ * @flags:     buffer flags as defined by &enum dmx_buffer_flags.
+ *             Filled only at &DMX_DQBUF. &DMX_QBUF should zero this field.
+ * @count:     monotonic counter for filled buffers. Helps to identify
+ *             data stream loses. Filled only at &DMX_DQBUF. &DMX_QBUF should
+ *             zero this field.
+ *
  * @name:      name of the device type. Currently, it can either be
  *             "dvr" or "demux_filter".
  */
@@ -100,10 +106,14 @@ struct dvb_vb2_ctx {
        int     buf_siz;
        int     buf_cnt;
        int     nonblocking;
+
+       enum dmx_buffer_flags flags;
+       u32     count;
+
        char    name[DVB_VB2_NAME_MAX + 1];
 };
 
-#ifndef DVB_MMAP
+#ifndef CONFIG_DVB_MMAP
 static inline int dvb_vb2_init(struct dvb_vb2_ctx *ctx,
                               const char *name, int non_blocking)
 {
@@ -114,7 +124,7 @@ static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
        return 0;
 };
 #define dvb_vb2_is_streaming(ctx) (0)
-#define dvb_vb2_fill_buffer(ctx, file, wait) (0)
+#define dvb_vb2_fill_buffer(ctx, file, wait, flags) (0)
 
 static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx,
                                    struct file *file,
@@ -153,9 +163,13 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx);
  * @ctx:       control struct for VB2 handler
  * @src:       place where the data is stored
  * @len:       number of bytes to be copied from @src
+ * @buffer_flags:
+ *             pointer to buffer flags as defined by &enum dmx_buffer_flags.
+ *             can be NULL.
  */
 int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
-                       const unsigned char *src, int len);
+                       const unsigned char *src, int len,
+                       enum dmx_buffer_flags *buffer_flags);
 
 /**
  * dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV
index c2d1b15da136e9aa9273a90471ac8be7a1b6b413..a91f25151a5b96ce43d61e2f58841aefa4190baa 100644 (file)
@@ -15,6 +15,7 @@
 
 #define ARC_REG_MCIP_BCR       0x0d0
 #define ARC_REG_MCIP_IDU_BCR   0x0D5
+#define ARC_REG_GFRC_BUILD     0x0D6
 #define ARC_REG_MCIP_CMD       0x600
 #define ARC_REG_MCIP_WDATA     0x601
 #define ARC_REG_MCIP_READBACK  0x602
@@ -36,10 +37,14 @@ struct mcip_cmd {
 #define CMD_SEMA_RELEASE               0x12
 
 #define CMD_DEBUG_SET_MASK             0x34
+#define CMD_DEBUG_READ_MASK            0x35
 #define CMD_DEBUG_SET_SELECT           0x36
+#define CMD_DEBUG_READ_SELECT          0x37
 
 #define CMD_GFRC_READ_LO               0x42
 #define CMD_GFRC_READ_HI               0x43
+#define CMD_GFRC_SET_CORE              0x47
+#define CMD_GFRC_READ_CORE             0x48
 
 #define CMD_IDU_ENABLE                 0x71
 #define CMD_IDU_DISABLE                        0x72
index 91a31ffed828ddfbad55967022d3a1df32db5340..9a781f0611df0280be7d952258f486f805f27528 100644 (file)
@@ -63,6 +63,7 @@ struct drm_virtgpu_execbuffer {
 };
 
 #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
+#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */
 
 struct drm_virtgpu_getparam {
        __u64 param;
index 20d1490d63773288d1d91130e96478ee7708bf26..3c50e07ee833116a726c19402f26cf63e91491e9 100644 (file)
@@ -131,7 +131,7 @@ enum {
 #define BLKTRACE_BDEV_SIZE     32
 
 /*
- * User setup structure passed with BLKTRACESTART
+ * User setup structure passed with BLKTRACESETUP
  */
 struct blk_user_trace_setup {
        char name[BLKTRACE_BDEV_SIZE];  /* output */
index 5f3c5a918f00d5ed3cb2c82b8803edeae456cad9..b4112f0b6dd36c33299930f4ffc16fc5230e465f 100644 (file)
@@ -211,6 +211,32 @@ struct dmx_stc {
        __u64 stc;
 };
 
+/**
+ * enum dmx_buffer_flags - DMX memory-mapped buffer flags
+ *
+ * @DMX_BUFFER_FLAG_HAD_CRC32_DISCARD:
+ *     Indicates that the Kernel discarded one or more frames due to wrong
+ *     CRC32 checksum.
+ * @DMX_BUFFER_FLAG_TEI:
+ *     Indicates that the Kernel has detected a Transport Error indicator
+ *     (TEI) on a filtered pid.
+ * @DMX_BUFFER_PKT_COUNTER_MISMATCH:
+ *     Indicates that the Kernel has detected a packet counter mismatch
+ *     on a filtered pid.
+ * @DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED:
+ *     Indicates that the Kernel has detected one or more frame discontinuity.
+ * @DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR:
+ *     Received at least one packet with a frame discontinuity indicator.
+ */
+
+enum dmx_buffer_flags {
+       DMX_BUFFER_FLAG_HAD_CRC32_DISCARD               = 1 << 0,
+       DMX_BUFFER_FLAG_TEI                             = 1 << 1,
+       DMX_BUFFER_PKT_COUNTER_MISMATCH                 = 1 << 2,
+       DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED          = 1 << 3,
+       DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR         = 1 << 4,
+};
+
 /**
  * struct dmx_buffer - dmx buffer info
  *
@@ -220,15 +246,24 @@ struct dmx_stc {
  *             offset from the start of the device memory for this plane,
  *             (or a "cookie" that should be passed to mmap() as offset)
  * @length:    size in bytes of the buffer
+ * @flags:     bit array of buffer flags as defined by &enum dmx_buffer_flags.
+ *             Filled only at &DMX_DQBUF.
+ * @count:     monotonic counter for filled buffers. Helps to identify
+ *             data stream loses. Filled only at &DMX_DQBUF.
  *
  * Contains data exchanged by application and driver using one of the streaming
  * I/O methods.
+ *
+ * Please notice that, for &DMX_QBUF, only @index should be filled.
+ * On &DMX_DQBUF calls, all fields will be filled by the Kernel.
  */
 struct dmx_buffer {
        __u32                   index;
        __u32                   bytesused;
        __u32                   offset;
        __u32                   length;
+       __u32                   flags;
+       __u32                   count;
 };
 
 /**
index 0fb5ef939732517293f222f2c85d88f2b4c1e973..7b26d4b0b0529649816ec1523d225eec7fa8ee26 100644 (file)
@@ -761,6 +761,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_TRACE_PAUSE           __KVM_DEPRECATED_MAIN_0x07
 #define KVM_TRACE_DISABLE         __KVM_DEPRECATED_MAIN_0x08
 #define KVM_GET_EMULATED_CPUID   _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
+#define KVM_GET_MSR_FEATURE_INDEX_LIST    _IOWR(KVMIO, 0x0a, struct kvm_msr_list)
 
 /*
  * Extension capability list.
@@ -934,6 +935,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_AIS_MIGRATION 150
 #define KVM_CAP_PPC_GET_CPU_CHAR 151
 #define KVM_CAP_S390_BPB 152
+#define KVM_CAP_GET_MSR_FEATURES 153
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index 3d77fe91239a802367634d3cc29fd3903c1cee19..9008f31c7eb65c90a487d99d3f371a00ba526f3f 100644 (file)
@@ -42,7 +42,7 @@ typedef enum {
        SEV_RET_INVALID_PLATFORM_STATE,
        SEV_RET_INVALID_GUEST_STATE,
        SEV_RET_INAVLID_CONFIG,
-       SEV_RET_INVALID_len,
+       SEV_RET_INVALID_LEN,
        SEV_RET_ALREADY_OWNED,
        SEV_RET_INVALID_CERTIFICATE,
        SEV_RET_POLICY_FAILURE,
index a8100b9548398e8b102052f2c1418b21ea423825..969eaf140ef0a5d356e2c9a085b5d2a86c215eba 100644 (file)
@@ -89,6 +89,7 @@
 #include <linux/io.h>
 #include <linux/cache.h>
 #include <linux/rodata_test.h>
+#include <linux/jump_label.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -1000,6 +1001,7 @@ static int __ref kernel_init(void *unused)
        /* need to finish all async __init code before freeing the memory */
        async_synchronize_full();
        ftrace_free_init_mem();
+       jump_label_invalidate_init();
        free_initmem();
        mark_readonly();
        system_state = SYSTEM_RUNNING;
index a17fdb63dc3e470955dcfd5e5861920b9db2749f..6a5b61ebc66c956e6eeee6537786f4161d98f2ef 100644 (file)
@@ -64,7 +64,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
        return e;
 }
 
-static inline int init_kernel_text(unsigned long addr)
+int init_kernel_text(unsigned long addr)
 {
        if (addr >= (unsigned long)_sinittext &&
            addr < (unsigned long)_einittext)
index b4517095db6af2f5130e6c871a7a9e32884c2a66..52a0a7af8640b6b51dade855b6b18468589dff2c 100644 (file)
@@ -366,12 +366,15 @@ static void __jump_label_update(struct static_key *key,
 {
        for (; (entry < stop) && (jump_entry_key(entry) == key); entry++) {
                /*
-                * entry->code set to 0 invalidates module init text sections
-                * kernel_text_address() verifies we are not in core kernel
-                * init code, see jump_label_invalidate_module_init().
+                * An entry->code of 0 indicates an entry which has been
+                * disabled because it was in an init text area.
                 */
-               if (entry->code && kernel_text_address(entry->code))
-                       arch_jump_label_transform(entry, jump_label_type(entry));
+               if (entry->code) {
+                       if (kernel_text_address(entry->code))
+                               arch_jump_label_transform(entry, jump_label_type(entry));
+                       else
+                               WARN_ONCE(1, "can't patch jump_label at %pS", (void *)entry->code);
+               }
        }
 }
 
@@ -417,6 +420,19 @@ void __init jump_label_init(void)
        cpus_read_unlock();
 }
 
+/* Disable any jump label entries in __init code */
+void __init jump_label_invalidate_init(void)
+{
+       struct jump_entry *iter_start = __start___jump_table;
+       struct jump_entry *iter_stop = __stop___jump_table;
+       struct jump_entry *iter;
+
+       for (iter = iter_start; iter < iter_stop; iter++) {
+               if (init_kernel_text(iter->code))
+                       iter->code = 0;
+       }
+}
+
 #ifdef CONFIG_MODULES
 
 static enum jump_label_type jump_label_init_type(struct jump_entry *entry)
@@ -633,6 +649,7 @@ static void jump_label_del_module(struct module *mod)
        }
 }
 
+/* Disable any jump label entries in module init code */
 static void jump_label_invalidate_module_init(struct module *mod)
 {
        struct jump_entry *iter_start = mod->jump_entries;
index fc1123583fa6edadb19214bb1922f7ce4ccdf1e1..f274fbef821d1bee0c457da42417f4b8153444cf 100644 (file)
@@ -2397,7 +2397,7 @@ skip:
 
                if (console_lock_spinning_disable_and_check()) {
                        printk_safe_exit_irqrestore(flags);
-                       return;
+                       goto out;
                }
 
                printk_safe_exit_irqrestore(flags);
@@ -2430,6 +2430,7 @@ skip:
        if (retry && console_trylock())
                goto again;
 
+out:
        if (wake_klogd)
                wake_up_klogd();
 }
index 1b34d210452c5aba703aea04e648dd6ed56fd576..7f5cdc1e6b298f2c2121ebc33195fbc7c7d71145 100644 (file)
@@ -1491,12 +1491,12 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
        if (unlikely(virt == NULL))
                return;
 
-       entry = dma_entry_alloc();
-       if (!entry)
+       /* handle vmalloc and linear addresses */
+       if (!is_vmalloc_addr(virt) && !virt_addr_valid(virt))
                return;
 
-       /* handle vmalloc and linear addresses */
-       if (!is_vmalloc_addr(virt) && !virt_to_page(virt))
+       entry = dma_entry_alloc();
+       if (!entry)
                return;
 
        entry->type      = dma_debug_coherent;
@@ -1528,7 +1528,7 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
        };
 
        /* handle vmalloc and linear addresses */
-       if (!is_vmalloc_addr(virt) && !virt_to_page(virt))
+       if (!is_vmalloc_addr(virt) && !virt_addr_valid(virt))
                return;
 
        if (is_vmalloc_addr(virt))
index 99ec5bc89d252fd303a0a277d9b1471a6583e282..823b813f08f862b4c80463ad69f91ba9acf62703 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -36,8 +36,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid,
 {
        struct radix_tree_iter iter;
        void __rcu **slot;
-       int base = idr->idr_base;
-       int id = *nextid;
+       unsigned int base = idr->idr_base;
+       unsigned int id = *nextid;
 
        if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr)))
                return -EINVAL;
@@ -204,10 +204,11 @@ int idr_for_each(const struct idr *idr,
 
        radix_tree_for_each_slot(slot, &idr->idr_rt, &iter, 0) {
                int ret;
+               unsigned long id = iter.index + base;
 
-               if (WARN_ON_ONCE(iter.index > INT_MAX))
+               if (WARN_ON_ONCE(id > INT_MAX))
                        break;
-               ret = fn(iter.index + base, rcu_dereference_raw(*slot), data);
+               ret = fn(id, rcu_dereference_raw(*slot), data);
                if (ret)
                        return ret;
        }
@@ -230,8 +231,8 @@ void *idr_get_next(struct idr *idr, int *nextid)
 {
        struct radix_tree_iter iter;
        void __rcu **slot;
-       int base = idr->idr_base;
-       int id = *nextid;
+       unsigned long base = idr->idr_base;
+       unsigned long id = *nextid;
 
        id = (id < base) ? 0 : id - base;
        slot = radix_tree_iter_find(&idr->idr_rt, &iter, id);
index 1e492ef2a33d945699a327831640db04c1f158fa..4d4c82229e9e21cea5ab7011aaf03e7a28e2b394 100644 (file)
@@ -418,6 +418,7 @@ ceph_parse_options(char *options, const char *dev_name,
                                opt->flags |= CEPH_OPT_FSID;
                        break;
                case Opt_name:
+                       kfree(opt->name);
                        opt->name = kstrndup(argstr[0].from,
                                              argstr[0].to-argstr[0].from,
                                              GFP_KERNEL);
@@ -427,6 +428,9 @@ ceph_parse_options(char *options, const char *dev_name,
                        }
                        break;
                case Opt_secret:
+                       ceph_crypto_key_destroy(opt->key);
+                       kfree(opt->key);
+
                        opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
                        if (!opt->key) {
                                err = -ENOMEM;
@@ -437,6 +441,9 @@ ceph_parse_options(char *options, const char *dev_name,
                                goto out;
                        break;
                case Opt_key:
+                       ceph_crypto_key_destroy(opt->key);
+                       kfree(opt->key);
+
                        opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
                        if (!opt->key) {
                                err = -ENOMEM;
index 0e349b80686e76a421759b931ec04d194e446768..ba942e3ead890de9f4632d25a5fc1fd000676296 100644 (file)
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+ifndef CROSS_COMPILE
 hostprogs-$(CONFIG_SAMPLE_SECCOMP) := bpf-fancy dropper bpf-direct
 
 HOSTCFLAGS_bpf-fancy.o += -I$(objtree)/usr/include
@@ -16,7 +17,6 @@ HOSTCFLAGS_bpf-direct.o += -idirafter $(objtree)/include
 bpf-direct-objs := bpf-direct.o
 
 # Try to match the kernel target.
-ifndef CROSS_COMPILE
 ifndef CONFIG_64BIT
 
 # s390 has -m31 flag to build 31 bit binaries
@@ -35,12 +35,4 @@ HOSTLOADLIBES_bpf-fancy += $(MFLAG)
 HOSTLOADLIBES_dropper += $(MFLAG)
 endif
 always := $(hostprogs-m)
-else
-# MIPS system calls are defined based on the -mabi that is passed
-# to the toolchain which may or may not be a valid option
-# for the host toolchain. So disable tests if target architecture
-# is MIPS but the host isn't.
-ifndef CONFIG_MIPS
-always := $(hostprogs-m)
-endif
 endif
index 47cddf32aeba025f2741dbc7f48d596f4f6653fa..4f2b25d43ec9b46923e52ae5d6f2bf789a6465b4 100644 (file)
@@ -256,6 +256,8 @@ __objtool_obj := $(objtree)/tools/objtool/objtool
 
 objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check)
 
+objtool_args += $(if $(part-of-module), --module,)
+
 ifndef CONFIG_FRAME_POINTER
 objtool_args += --no-fp
 endif
@@ -264,6 +266,12 @@ objtool_args += --no-unreachable
 else
 objtool_args += $(call cc-ifversion, -lt, 0405, --no-unreachable)
 endif
+ifdef CONFIG_RETPOLINE
+ifneq ($(RETPOLINE_CFLAGS),)
+  objtool_args += --retpoline
+endif
+endif
+
 
 ifdef CONFIG_MODVERSIONS
 objtool_o = $(@D)/.tmp_$(@F)
index 0b3026d937b101918581edab80aa3b2803ecec5a..8a77620a38548ef8ad36d5b9bf154a14a785f568 100644 (file)
@@ -889,7 +889,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
 
        index_offset = snd_ctl_get_ioff(kctl, &control->id);
        vd = &kctl->vd[index_offset];
-       if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get == NULL)
+       if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL)
                return -EPERM;
 
        snd_ctl_build_ioff(&control->id, kctl, index_offset);
index c71dcacea807bf0e0d11aa147401acd12280686c..96143df19b2150884fdea3d6eb26ea49fd65a874 100644 (file)
@@ -181,7 +181,7 @@ static const struct kernel_param_ops param_ops_xint = {
 };
 #define param_check_xint param_check_int
 
-static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
+static int power_save = -1;
 module_param(power_save, xint, 0644);
 MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
                 "(in second, 0 = disable).");
@@ -2186,6 +2186,24 @@ out_free:
        return err;
 }
 
+#ifdef CONFIG_PM
+/* On some boards setting power_save to a non 0 value leads to clicking /
+ * popping sounds when ever we enter/leave powersaving mode. Ideally we would
+ * figure out how to avoid these sounds, but that is not always feasible.
+ * So we keep a list of devices where we disable powersaving as its known
+ * to causes problems on these devices.
+ */
+static struct snd_pci_quirk power_save_blacklist[] = {
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+       SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0),
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+       SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
+       SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
+       {}
+};
+#endif /* CONFIG_PM */
+
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
 static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
        [AZX_DRIVER_NVIDIA] = 8,
@@ -2198,6 +2216,7 @@ static int azx_probe_continue(struct azx *chip)
        struct hdac_bus *bus = azx_bus(chip);
        struct pci_dev *pci = chip->pci;
        int dev = chip->dev_index;
+       int val;
        int err;
 
        hda->probe_continued = 1;
@@ -2278,7 +2297,22 @@ static int azx_probe_continue(struct azx *chip)
 
        chip->running = 1;
        azx_add_card_list(chip);
-       snd_hda_set_power_save(&chip->bus, power_save * 1000);
+
+       val = power_save;
+#ifdef CONFIG_PM
+       if (val == -1) {
+               const struct snd_pci_quirk *q;
+
+               val = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
+               q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist);
+               if (q && val) {
+                       dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n",
+                                q->subvendor, q->subdevice);
+                       val = 0;
+               }
+       }
+#endif /* CONFIG_PM */
+       snd_hda_set_power_save(&chip->bus, val * 1000);
        if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo)
                pm_runtime_put_autosuspend(&pci->dev);
 
index ce28f7ce64e63774655a421bf1102b7c354786dc..b9c93fa0a51c6e2ec57a51fae96b4d4f8eaf52b8 100644 (file)
@@ -4997,13 +4997,14 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
+               snd_hda_apply_pincfgs(codec, pincfgs);
+       } else if (action == HDA_FIXUP_ACT_INIT) {
                /* Enable DOCK device */
                snd_hda_codec_write(codec, 0x17, 0,
                            AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
                /* Enable DOCK device */
                snd_hda_codec_write(codec, 0x19, 0,
                            AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
-               snd_hda_apply_pincfgs(codec, pincfgs);
        }
 }
 
index 50252046b01df7cdb376e1c8ae8c59559befdd1f..754e632a27bd2e8c15931e821fa158bf50bfdb78 100644 (file)
@@ -3325,4 +3325,51 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
        }
 },
 
+{
+       /*
+        * Bower's & Wilkins PX headphones only support the 48 kHz sample rate
+        * even though it advertises more. The capture interface doesn't work
+        * even on windows.
+        */
+       USB_DEVICE(0x19b5, 0x0021),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
+                       },
+                       /* Capture */
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_IGNORE_INTERFACE,
+                       },
+                       /* Playback */
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_FILL_MAX |
+                                               UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x03,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) {
+                                               48000
+                                       }
+                               }
+                       },
+               }
+       }
+},
+
 #undef USB_DEVICE_VENDOR_SPEC
index a0951505c7f5b2804c3203fe7eeb0dea7d4935b1..4ed9d0c41843888d6e9c4aa7f79b980c3e0ac74b 100644 (file)
@@ -50,6 +50,7 @@
 /*standard module options for ALSA. This module supports only one card*/
 static int hdmi_card_index = SNDRV_DEFAULT_IDX1;
 static char *hdmi_card_id = SNDRV_DEFAULT_STR1;
+static bool single_port;
 
 module_param_named(index, hdmi_card_index, int, 0444);
 MODULE_PARM_DESC(index,
@@ -57,6 +58,9 @@ MODULE_PARM_DESC(index,
 module_param_named(id, hdmi_card_id, charp, 0444);
 MODULE_PARM_DESC(id,
                "ID string for INTEL Intel HDMI Audio controller.");
+module_param(single_port, bool, 0444);
+MODULE_PARM_DESC(single_port,
+               "Single-port mode (for compatibility)");
 
 /*
  * ELD SA bits in the CEA Speaker Allocation data block
@@ -1579,7 +1583,11 @@ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id)
 static void notify_audio_lpe(struct platform_device *pdev, int port)
 {
        struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
-       struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
+       struct snd_intelhad *ctx;
+
+       ctx = &card_ctx->pcm_ctx[single_port ? 0 : port];
+       if (single_port)
+               ctx->port = port;
 
        schedule_work(&ctx->hdmi_audio_wq);
 }
@@ -1743,6 +1751,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
 {
        struct snd_card *card;
        struct snd_intelhad_card *card_ctx;
+       struct snd_intelhad *ctx;
        struct snd_pcm *pcm;
        struct intel_hdmi_lpe_audio_pdata *pdata;
        int irq;
@@ -1787,6 +1796,21 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, card_ctx);
 
+       card_ctx->num_pipes = pdata->num_pipes;
+       card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
+
+       for_each_port(card_ctx, port) {
+               ctx = &card_ctx->pcm_ctx[port];
+               ctx->card_ctx = card_ctx;
+               ctx->dev = card_ctx->dev;
+               ctx->port = single_port ? -1 : port;
+               ctx->pipe = -1;
+
+               spin_lock_init(&ctx->had_spinlock);
+               mutex_init(&ctx->mutex);
+               INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
+       }
+
        dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n",
                __func__, (unsigned int)res_mmio->start,
                (unsigned int)res_mmio->end);
@@ -1816,19 +1840,12 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        init_channel_allocations();
 
        card_ctx->num_pipes = pdata->num_pipes;
-       card_ctx->num_ports = pdata->num_ports;
+       card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
 
        for_each_port(card_ctx, port) {
-               struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
                int i;
 
-               ctx->card_ctx = card_ctx;
-               ctx->dev = card_ctx->dev;
-               ctx->port = port;
-               ctx->pipe = -1;
-
-               INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
-
+               ctx = &card_ctx->pcm_ctx[port];
                ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
                                  MAX_CAP_STREAMS, &pcm);
                if (ret)
index a5684d0968b4fd087905e659c0ce80bd170434c2..5898c22ba310bdf27f626a2dfb7bc45e5cf2a505 100755 (executable)
@@ -33,7 +33,7 @@ import resource
 import struct
 import re
 import subprocess
-from collections import defaultdict
+from collections import defaultdict, namedtuple
 
 VMX_EXIT_REASONS = {
     'EXCEPTION_NMI':        0,
@@ -228,6 +228,7 @@ IOCTL_NUMBERS = {
 }
 
 ENCODING = locale.getpreferredencoding(False)
+TRACE_FILTER = re.compile(r'^[^\(]*$')
 
 
 class Arch(object):
@@ -260,6 +261,11 @@ class Arch(object):
                     return ArchX86(SVM_EXIT_REASONS)
                 return
 
+    def tracepoint_is_child(self, field):
+        if (TRACE_FILTER.match(field)):
+            return None
+        return field.split('(', 1)[0]
+
 
 class ArchX86(Arch):
     def __init__(self, exit_reasons):
@@ -267,6 +273,10 @@ class ArchX86(Arch):
         self.ioctl_numbers = IOCTL_NUMBERS
         self.exit_reasons = exit_reasons
 
+    def debugfs_is_child(self, field):
+        """ Returns name of parent if 'field' is a child, None otherwise """
+        return None
+
 
 class ArchPPC(Arch):
     def __init__(self):
@@ -282,6 +292,10 @@ class ArchPPC(Arch):
         self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16
         self.exit_reasons = {}
 
+    def debugfs_is_child(self, field):
+        """ Returns name of parent if 'field' is a child, None otherwise """
+        return None
+
 
 class ArchA64(Arch):
     def __init__(self):
@@ -289,6 +303,10 @@ class ArchA64(Arch):
         self.ioctl_numbers = IOCTL_NUMBERS
         self.exit_reasons = AARCH64_EXIT_REASONS
 
+    def debugfs_is_child(self, field):
+        """ Returns name of parent if 'field' is a child, None otherwise """
+        return None
+
 
 class ArchS390(Arch):
     def __init__(self):
@@ -296,6 +314,12 @@ class ArchS390(Arch):
         self.ioctl_numbers = IOCTL_NUMBERS
         self.exit_reasons = None
 
+    def debugfs_is_child(self, field):
+        """ Returns name of parent if 'field' is a child, None otherwise """
+        if field.startswith('instruction_'):
+            return 'exit_instruction'
+
+
 ARCH = Arch.get_arch()
 
 
@@ -331,9 +355,6 @@ class perf_event_attr(ctypes.Structure):
 PERF_TYPE_TRACEPOINT = 2
 PERF_FORMAT_GROUP = 1 << 3
 
-PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
-PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
-
 
 class Group(object):
     """Represents a perf event group."""
@@ -376,8 +397,8 @@ class Event(object):
         self.syscall = self.libc.syscall
         self.name = name
         self.fd = None
-        self.setup_event(group, trace_cpu, trace_pid, trace_point,
-                         trace_filter, trace_set)
+        self._setup_event(group, trace_cpu, trace_pid, trace_point,
+                          trace_filter, trace_set)
 
     def __del__(self):
         """Closes the event's file descriptor.
@@ -390,7 +411,7 @@ class Event(object):
         if self.fd:
             os.close(self.fd)
 
-    def perf_event_open(self, attr, pid, cpu, group_fd, flags):
+    def _perf_event_open(self, attr, pid, cpu, group_fd, flags):
         """Wrapper for the sys_perf_evt_open() syscall.
 
         Used to set up performance events, returns a file descriptor or -1
@@ -409,7 +430,7 @@ class Event(object):
                             ctypes.c_int(pid), ctypes.c_int(cpu),
                             ctypes.c_int(group_fd), ctypes.c_long(flags))
 
-    def setup_event_attribute(self, trace_set, trace_point):
+    def _setup_event_attribute(self, trace_set, trace_point):
         """Returns an initialized ctype perf_event_attr struct."""
 
         id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set,
@@ -419,8 +440,8 @@ class Event(object):
         event_attr.config = int(open(id_path).read())
         return event_attr
 
-    def setup_event(self, group, trace_cpu, trace_pid, trace_point,
-                    trace_filter, trace_set):
+    def _setup_event(self, group, trace_cpu, trace_pid, trace_point,
+                     trace_filter, trace_set):
         """Sets up the perf event in Linux.
 
         Issues the syscall to register the event in the kernel and
@@ -428,7 +449,7 @@ class Event(object):
 
         """
 
-        event_attr = self.setup_event_attribute(trace_set, trace_point)
+        event_attr = self._setup_event_attribute(trace_set, trace_point)
 
         # First event will be group leader.
         group_leader = -1
@@ -437,8 +458,8 @@ class Event(object):
         if group.events:
             group_leader = group.events[0].fd
 
-        fd = self.perf_event_open(event_attr, trace_pid,
-                                  trace_cpu, group_leader, 0)
+        fd = self._perf_event_open(event_attr, trace_pid,
+                                   trace_cpu, group_leader, 0)
         if fd == -1:
             err = ctypes.get_errno()
             raise OSError(err, os.strerror(err),
@@ -475,6 +496,10 @@ class Event(object):
 
 class Provider(object):
     """Encapsulates functionalities used by all providers."""
+    def __init__(self, pid):
+        self.child_events = False
+        self.pid = pid
+
     @staticmethod
     def is_field_wanted(fields_filter, field):
         """Indicate whether field is valid according to fields_filter."""
@@ -500,12 +525,12 @@ class TracepointProvider(Provider):
     """
     def __init__(self, pid, fields_filter):
         self.group_leaders = []
-        self.filters = self.get_filters()
+        self.filters = self._get_filters()
         self.update_fields(fields_filter)
-        self.pid = pid
+        super(TracepointProvider, self).__init__(pid)
 
     @staticmethod
-    def get_filters():
+    def _get_filters():
         """Returns a dict of trace events, their filter ids and
         the values that can be filtered.
 
@@ -521,8 +546,8 @@ class TracepointProvider(Provider):
             filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
         return filters
 
-    def get_available_fields(self):
-        """Returns a list of available event's of format 'event name(filter
+    def _get_available_fields(self):
+        """Returns a list of available events of format 'event name(filter
         name)'.
 
         All available events have directories under
@@ -549,11 +574,12 @@ class TracepointProvider(Provider):
 
     def update_fields(self, fields_filter):
         """Refresh fields, applying fields_filter"""
-        self.fields = [field for field in self.get_available_fields()
-                       if self.is_field_wanted(fields_filter, field)]
+        self.fields = [field for field in self._get_available_fields()
+                       if self.is_field_wanted(fields_filter, field) or
+                       ARCH.tracepoint_is_child(field)]
 
     @staticmethod
-    def get_online_cpus():
+    def _get_online_cpus():
         """Returns a list of cpu id integers."""
         def parse_int_list(list_string):
             """Returns an int list from a string of comma separated integers and
@@ -575,17 +601,17 @@ class TracepointProvider(Provider):
             cpu_string = cpu_list.readline()
             return parse_int_list(cpu_string)
 
-    def setup_traces(self):
+    def _setup_traces(self):
         """Creates all event and group objects needed to be able to retrieve
         data."""
-        fields = self.get_available_fields()
+        fields = self._get_available_fields()
         if self._pid > 0:
             # Fetch list of all threads of the monitored pid, as qemu
             # starts a thread for each vcpu.
             path = os.path.join('/proc', str(self._pid), 'task')
             groupids = self.walkdir(path)[1]
         else:
-            groupids = self.get_online_cpus()
+            groupids = self._get_online_cpus()
 
         # The constant is needed as a buffer for python libs, std
         # streams and other files that the script opens.
@@ -663,7 +689,7 @@ class TracepointProvider(Provider):
         # The garbage collector will get rid of all Event/Group
         # objects and open files after removing the references.
         self.group_leaders = []
-        self.setup_traces()
+        self._setup_traces()
         self.fields = self._fields
 
     def read(self, by_guest=0):
@@ -671,8 +697,12 @@ class TracepointProvider(Provider):
         ret = defaultdict(int)
         for group in self.group_leaders:
             for name, val in group.read().items():
-                if name in self._fields:
-                    ret[name] += val
+                if name not in self._fields:
+                    continue
+                parent = ARCH.tracepoint_is_child(name)
+                if parent:
+                    name += ' ' + parent
+                ret[name] += val
         return ret
 
     def reset(self):
@@ -690,11 +720,11 @@ class DebugfsProvider(Provider):
         self._baseline = {}
         self.do_read = True
         self.paths = []
-        self.pid = pid
+        super(DebugfsProvider, self).__init__(pid)
         if include_past:
-            self.restore()
+            self._restore()
 
-    def get_available_fields(self):
+    def _get_available_fields(self):
         """"Returns a list of available fields.
 
         The fields are all available KVM debugfs files
@@ -704,8 +734,9 @@ class DebugfsProvider(Provider):
 
     def update_fields(self, fields_filter):
         """Refresh fields, applying fields_filter"""
-        self._fields = [field for field in self.get_available_fields()
-                        if self.is_field_wanted(fields_filter, field)]
+        self._fields = [field for field in self._get_available_fields()
+                        if self.is_field_wanted(fields_filter, field) or
+                        ARCH.debugfs_is_child(field)]
 
     @property
     def fields(self):
@@ -758,7 +789,7 @@ class DebugfsProvider(Provider):
                     paths.append(dir)
         for path in paths:
             for field in self._fields:
-                value = self.read_field(field, path)
+                value = self._read_field(field, path)
                 key = path + field
                 if reset == 1:
                     self._baseline[key] = value
@@ -766,20 +797,21 @@ class DebugfsProvider(Provider):
                     self._baseline[key] = 0
                 if self._baseline.get(key, -1) == -1:
                     self._baseline[key] = value
-                increment = (results.get(field, 0) + value -
-                             self._baseline.get(key, 0))
-                if by_guest:
-                    pid = key.split('-')[0]
-                    if pid in results:
-                        results[pid] += increment
-                    else:
-                        results[pid] = increment
+                parent = ARCH.debugfs_is_child(field)
+                if parent:
+                    field = field + ' ' + parent
+                else:
+                    if by_guest:
+                        field = key.split('-')[0]    # set 'field' to 'pid'
+                increment = value - self._baseline.get(key, 0)
+                if field in results:
+                    results[field] += increment
                 else:
                     results[field] = increment
 
         return results
 
-    def read_field(self, field, path):
+    def _read_field(self, field, path):
         """Returns the value of a single field from a specific VM."""
         try:
             return int(open(os.path.join(PATH_DEBUGFS_KVM,
@@ -794,12 +826,15 @@ class DebugfsProvider(Provider):
         self._baseline = {}
         self.read(1)
 
-    def restore(self):
+    def _restore(self):
         """Reset field counters"""
         self._baseline = {}
         self.read(2)
 
 
+EventStat = namedtuple('EventStat', ['value', 'delta'])
+
+
 class Stats(object):
     """Manages the data providers and the data they provide.
 
@@ -808,13 +843,13 @@ class Stats(object):
 
     """
     def __init__(self, options):
-        self.providers = self.get_providers(options)
+        self.providers = self._get_providers(options)
         self._pid_filter = options.pid
         self._fields_filter = options.fields
         self.values = {}
+        self._child_events = False
 
-    @staticmethod
-    def get_providers(options):
+    def _get_providers(self, options):
         """Returns a list of data providers depending on the passed options."""
         providers = []
 
@@ -826,7 +861,7 @@ class Stats(object):
 
         return providers
 
-    def update_provider_filters(self):
+    def _update_provider_filters(self):
         """Propagates fields filters to providers."""
         # As we reset the counters when updating the fields we can
         # also clear the cache of old values.
@@ -847,7 +882,7 @@ class Stats(object):
     def fields_filter(self, fields_filter):
         if fields_filter != self._fields_filter:
             self._fields_filter = fields_filter
-            self.update_provider_filters()
+            self._update_provider_filters()
 
     @property
     def pid_filter(self):
@@ -861,16 +896,33 @@ class Stats(object):
             for provider in self.providers:
                 provider.pid = self._pid_filter
 
+    @property
+    def child_events(self):
+        return self._child_events
+
+    @child_events.setter
+    def child_events(self, val):
+        self._child_events = val
+        for provider in self.providers:
+            provider.child_events = val
+
     def get(self, by_guest=0):
         """Returns a dict with field -> (value, delta to last value) of all
-        provider data."""
+        provider data.
+        Key formats:
+          * plain: 'key' is event name
+          * child-parent: 'key' is in format '<child> <parent>'
+          * pid: 'key' is the pid of the guest, and the record contains the
+               aggregated event data
+        These formats are generated by the providers, and handled in class TUI.
+        """
         for provider in self.providers:
             new = provider.read(by_guest=by_guest)
-            for key in new if by_guest else provider.fields:
-                oldval = self.values.get(key, (0, 0))[0]
+            for key in new:
+                oldval = self.values.get(key, EventStat(0, 0)).value
                 newval = new.get(key, 0)
                 newdelta = newval - oldval
-                self.values[key] = (newval, newdelta)
+                self.values[key] = EventStat(newval, newdelta)
         return self.values
 
     def toggle_display_guests(self, to_pid):
@@ -899,10 +951,10 @@ class Stats(object):
         self.get(to_pid)
         return 0
 
+
 DELAY_DEFAULT = 3.0
 MAX_GUEST_NAME_LEN = 48
 MAX_REGEX_LEN = 44
-DEFAULT_REGEX = r'^[^\(]*$'
 SORT_DEFAULT = 0
 
 
@@ -969,7 +1021,7 @@ class Tui(object):
 
         return res
 
-    def print_all_gnames(self, row):
+    def _print_all_gnames(self, row):
         """Print a list of all running guests along with their pids."""
         self.screen.addstr(row, 2, '%8s  %-60s' %
                            ('Pid', 'Guest Name (fuzzy list, might be '
@@ -1032,19 +1084,13 @@ class Tui(object):
 
         return name
 
-    def update_drilldown(self):
-        """Sets or removes a filter that only allows fields without braces."""
-        if not self.stats.fields_filter:
-            self.stats.fields_filter = DEFAULT_REGEX
-
-        elif self.stats.fields_filter == DEFAULT_REGEX:
-            self.stats.fields_filter = None
-
-    def update_pid(self, pid):
+    def _update_pid(self, pid):
         """Propagates pid selection to stats object."""
+        self.screen.addstr(4, 1, 'Updating pid filter...')
+        self.screen.refresh()
         self.stats.pid_filter = pid
 
-    def refresh_header(self, pid=None):
+    def _refresh_header(self, pid=None):
         """Refreshes the header."""
         if pid is None:
             pid = self.stats.pid_filter
@@ -1059,8 +1105,7 @@ class Tui(object):
                                .format(pid, gname), curses.A_BOLD)
         else:
             self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD)
-        if self.stats.fields_filter and self.stats.fields_filter \
-           != DEFAULT_REGEX:
+        if self.stats.fields_filter:
             regex = self.stats.fields_filter
             if len(regex) > MAX_REGEX_LEN:
                 regex = regex[:MAX_REGEX_LEN] + '...'
@@ -1075,56 +1120,99 @@ class Tui(object):
         self.screen.addstr(4, 1, 'Collecting data...')
         self.screen.refresh()
 
-    def refresh_body(self, sleeptime):
+    def _refresh_body(self, sleeptime):
+        def is_child_field(field):
+            return field.find('(') != -1
+
+        def insert_child(sorted_items, child, values, parent):
+            num = len(sorted_items)
+            for i in range(0, num):
+                # only add child if parent is present
+                if parent.startswith(sorted_items[i][0]):
+                    sorted_items.insert(i + 1, ('  ' + child, values))
+
+        def get_sorted_events(self, stats):
+            """ separate parent and child events """
+            if self._sorting == SORT_DEFAULT:
+                def sortkey((_k, v)):
+                    # sort by (delta value, overall value)
+                    return (v.delta, v.value)
+            else:
+                def sortkey((_k, v)):
+                    # sort by overall value
+                    return v.value
+
+            childs = []
+            sorted_items = []
+            # we can't rule out child events to appear prior to parents even
+            # when sorted - separate out all children first, and add in later
+            for key, values in sorted(stats.items(), key=sortkey,
+                                      reverse=True):
+                if values == (0, 0):
+                    continue
+                if key.find(' ') != -1:
+                    if not self.stats.child_events:
+                        continue
+                    childs.insert(0, (key, values))
+                else:
+                    sorted_items.append((key, values))
+            if self.stats.child_events:
+                for key, values in childs:
+                    (child, parent) = key.split(' ')
+                    insert_child(sorted_items, child, values, parent)
+
+            return sorted_items
+
         row = 3
         self.screen.move(row, 0)
         self.screen.clrtobot()
         stats = self.stats.get(self._display_guests)
-
-        def sortCurAvg(x):
-            # sort by current events if available
-            if stats[x][1]:
-                return (-stats[x][1], -stats[x][0])
+        total = 0.
+        ctotal = 0.
+        for key, values in stats.items():
+            if self._display_guests:
+                if self.get_gname_from_pid(key):
+                    total += values.value
+                continue
+            if not key.find(' ') != -1:
+                total += values.value
             else:
-                return (0, -stats[x][0])
+                ctotal += values.value
+        if total == 0.:
+            # we don't have any fields, or all non-child events are filtered
+            total = ctotal
 
-        def sortTotal(x):
-            # sort by totals
-            return (0, -stats[x][0])
-        total = 0.
-        for key in stats.keys():
-            if key.find('(') is -1:
-                total += stats[key][0]
-        if self._sorting == SORT_DEFAULT:
-            sortkey = sortCurAvg
-        else:
-            sortkey = sortTotal
+        # print events
         tavg = 0
-        for key in sorted(stats.keys(), key=sortkey):
-            if row >= self.screen.getmaxyx()[0] - 1:
-                break
-            values = stats[key]
-            if not values[0] and not values[1]:
+        tcur = 0
+        for key, values in get_sorted_events(self, stats):
+            if row >= self.screen.getmaxyx()[0] - 1 or values == (0, 0):
                 break
-            if values[0] is not None:
-                cur = int(round(values[1] / sleeptime)) if values[1] else ''
-                if self._display_guests:
-                    key = self.get_gname_from_pid(key)
-                self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' %
-                                   (key, values[0], values[0] * 100 / total,
-                                    cur))
-                if cur is not '' and key.find('(') is -1:
-                    tavg += cur
+            if self._display_guests:
+                key = self.get_gname_from_pid(key)
+                if not key:
+                    continue
+            cur = int(round(values.delta / sleeptime)) if values.delta else ''
+            if key[0] != ' ':
+                if values.delta:
+                    tcur += values.delta
+                ptotal = values.value
+                ltotal = total
+            else:
+                ltotal = ptotal
+            self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' % (key,
+                               values.value,
+                               values.value * 100 / float(ltotal), cur))
             row += 1
         if row == 3:
             self.screen.addstr(4, 1, 'No matching events reported yet')
-        else:
+        if row > 4:
+            tavg = int(round(tcur / sleeptime)) if tcur > 0 else ''
             self.screen.addstr(row, 1, '%-40s %10d        %8s' %
-                               ('Total', total, tavg if tavg else ''),
-                               curses.A_BOLD)
+                               ('Total', total, tavg), curses.A_BOLD)
         self.screen.refresh()
 
-    def show_msg(self, text):
+    def _show_msg(self, text):
         """Display message centered text and exit on key press"""
         hint = 'Press any key to continue'
         curses.cbreak()
@@ -1139,16 +1227,16 @@ class Tui(object):
                            curses.A_STANDOUT)
         self.screen.getkey()
 
-    def show_help_interactive(self):
+    def _show_help_interactive(self):
         """Display help with list of interactive commands"""
         msg = ('   b     toggle events by guests (debugfs only, honors'
                ' filters)',
                '   c     clear filter',
                '   f     filter by regular expression',
-               '   g     filter by guest name',
+               '   g     filter by guest name/PID',
                '   h     display interactive commands reference',
                '   o     toggle sorting order (Total vs CurAvg/s)',
-               '   p     filter by PID',
+               '   p     filter by guest name/PID',
                '   q     quit',
                '   r     reset stats',
                '   s     set update interval',
@@ -1165,14 +1253,15 @@ class Tui(object):
             self.screen.addstr(row, 0, line)
             row += 1
         self.screen.getkey()
-        self.refresh_header()
+        self._refresh_header()
 
-    def show_filter_selection(self):
+    def _show_filter_selection(self):
         """Draws filter selection mask.
 
         Asks for a valid regex and sets the fields filter accordingly.
 
         """
+        msg = ''
         while True:
             self.screen.erase()
             self.screen.addstr(0, 0,
@@ -1181,61 +1270,25 @@ class Tui(object):
             self.screen.addstr(2, 0,
                                "Current regex: {0}"
                                .format(self.stats.fields_filter))
+            self.screen.addstr(5, 0, msg)
             self.screen.addstr(3, 0, "New regex: ")
             curses.echo()
             regex = self.screen.getstr().decode(ENCODING)
             curses.noecho()
             if len(regex) == 0:
-                self.stats.fields_filter = DEFAULT_REGEX
-                self.refresh_header()
+                self.stats.fields_filter = ''
+                self._refresh_header()
                 return
             try:
                 re.compile(regex)
                 self.stats.fields_filter = regex
-                self.refresh_header()
+                self._refresh_header()
                 return
             except re.error:
+                msg = '"' + regex + '": Not a valid regular expression'
                 continue
 
-    def show_vm_selection_by_pid(self):
-        """Draws PID selection mask.
-
-        Asks for a pid until a valid pid or 0 has been entered.
-
-        """
-        msg = ''
-        while True:
-            self.screen.erase()
-            self.screen.addstr(0, 0,
-                               'Show statistics for specific pid.',
-                               curses.A_BOLD)
-            self.screen.addstr(1, 0,
-                               'This might limit the shown data to the trace '
-                               'statistics.')
-            self.screen.addstr(5, 0, msg)
-            self.print_all_gnames(7)
-
-            curses.echo()
-            self.screen.addstr(3, 0, "Pid [0 or pid]: ")
-            pid = self.screen.getstr().decode(ENCODING)
-            curses.noecho()
-
-            try:
-                if len(pid) > 0:
-                    pid = int(pid)
-                    if pid != 0 and not os.path.isdir(os.path.join('/proc/',
-                                                                   str(pid))):
-                        msg = '"' + str(pid) + '": Not a running process'
-                        continue
-                else:
-                    pid = 0
-                self.refresh_header(pid)
-                self.update_pid(pid)
-                break
-            except ValueError:
-                msg = '"' + str(pid) + '": Not a valid pid'
-
-    def show_set_update_interval(self):
+    def _show_set_update_interval(self):
         """Draws update interval selection mask."""
         msg = ''
         while True:
@@ -1265,60 +1318,67 @@ class Tui(object):
 
             except ValueError:
                 msg = '"' + str(val) + '": Invalid value'
-        self.refresh_header()
+        self._refresh_header()
 
-    def show_vm_selection_by_guest_name(self):
+    def _show_vm_selection_by_guest(self):
         """Draws guest selection mask.
 
-        Asks for a guest name until a valid guest name or '' is entered.
+        Asks for a guest name or pid until a valid guest name or '' is entered.
 
         """
         msg = ''
         while True:
             self.screen.erase()
             self.screen.addstr(0, 0,
-                               'Show statistics for specific guest.',
+                               'Show statistics for specific guest or pid.',
                                curses.A_BOLD)
             self.screen.addstr(1, 0,
                                'This might limit the shown data to the trace '
                                'statistics.')
             self.screen.addstr(5, 0, msg)
-            self.print_all_gnames(7)
+            self._print_all_gnames(7)
             curses.echo()
-            self.screen.addstr(3, 0, "Guest [ENTER or guest]: ")
-            gname = self.screen.getstr().decode(ENCODING)
+            curses.curs_set(1)
+            self.screen.addstr(3, 0, "Guest or pid [ENTER exits]: ")
+            guest = self.screen.getstr().decode(ENCODING)
             curses.noecho()
 
-            if not gname:
-                self.refresh_header(0)
-                self.update_pid(0)
+            pid = 0
+            if not guest or guest == '0':
                 break
-            else:
-                pids = []
-                try:
-                    pids = self.get_pid_from_gname(gname)
-                except:
-                    msg = '"' + gname + '": Internal error while searching, ' \
-                          'use pid filter instead'
-                    continue
-                if len(pids) == 0:
-                    msg = '"' + gname + '": Not an active guest'
+            if guest.isdigit():
+                if not os.path.isdir(os.path.join('/proc/', guest)):
+                    msg = '"' + guest + '": Not a running process'
                     continue
-                if len(pids) > 1:
-                    msg = '"' + gname + '": Multiple matches found, use pid ' \
-                          'filter instead'
-                    continue
-                self.refresh_header(pids[0])
-                self.update_pid(pids[0])
+                pid = int(guest)
                 break
+            pids = []
+            try:
+                pids = self.get_pid_from_gname(guest)
+            except:
+                msg = '"' + guest + '": Internal error while searching, ' \
+                      'use pid filter instead'
+                continue
+            if len(pids) == 0:
+                msg = '"' + guest + '": Not an active guest'
+                continue
+            if len(pids) > 1:
+                msg = '"' + guest + '": Multiple matches found, use pid ' \
+                      'filter instead'
+                continue
+            pid = pids[0]
+            break
+        curses.curs_set(0)
+        self._refresh_header(pid)
+        self._update_pid(pid)
 
     def show_stats(self):
         """Refreshes the screen and processes user input."""
         sleeptime = self._delay_initial
-        self.refresh_header()
+        self._refresh_header()
         start = 0.0  # result based on init value never appears on screen
         while True:
-            self.refresh_body(time.time() - start)
+            self._refresh_body(time.time() - start)
             curses.halfdelay(int(sleeptime * 10))
             start = time.time()
             sleeptime = self._delay_regular
@@ -1327,47 +1387,39 @@ class Tui(object):
                 if char == 'b':
                     self._display_guests = not self._display_guests
                     if self.stats.toggle_display_guests(self._display_guests):
-                        self.show_msg(['Command not available with tracepoints'
-                                       ' enabled', 'Restart with debugfs only '
-                                       '(see option \'-d\') and try again!'])
+                        self._show_msg(['Command not available with '
+                                        'tracepoints enabled', 'Restart with '
+                                        'debugfs only (see option \'-d\') and '
+                                        'try again!'])
                         self._display_guests = not self._display_guests
-                    self.refresh_header()
+                    self._refresh_header()
                 if char == 'c':
-                    self.stats.fields_filter = DEFAULT_REGEX
-                    self.refresh_header(0)
-                    self.update_pid(0)
+                    self.stats.fields_filter = ''
+                    self._refresh_header(0)
+                    self._update_pid(0)
                 if char == 'f':
                     curses.curs_set(1)
-                    self.show_filter_selection()
+                    self._show_filter_selection()
                     curses.curs_set(0)
                     sleeptime = self._delay_initial
-                if char == 'g':
-                    curses.curs_set(1)
-                    self.show_vm_selection_by_guest_name()
-                    curses.curs_set(0)
+                if char == 'g' or char == 'p':
+                    self._show_vm_selection_by_guest()
                     sleeptime = self._delay_initial
                 if char == 'h':
-                    self.show_help_interactive()
+                    self._show_help_interactive()
                 if char == 'o':
                     self._sorting = not self._sorting
-                if char == 'p':
-                    curses.curs_set(1)
-                    self.show_vm_selection_by_pid()
-                    curses.curs_set(0)
-                    sleeptime = self._delay_initial
                 if char == 'q':
                     break
                 if char == 'r':
                     self.stats.reset()
                 if char == 's':
                     curses.curs_set(1)
-                    self.show_set_update_interval()
+                    self._show_set_update_interval()
                     curses.curs_set(0)
                     sleeptime = self._delay_initial
                 if char == 'x':
-                    self.update_drilldown()
-                    # prevents display of current values on next refresh
-                    self.stats.get(self._display_guests)
+                    self.stats.child_events = not self.stats.child_events
             except KeyboardInterrupt:
                 break
             except curses.error:
@@ -1380,9 +1432,9 @@ def batch(stats):
         s = stats.get()
         time.sleep(1)
         s = stats.get()
-        for key in sorted(s.keys()):
-            values = s[key]
-            print('%-42s%10d%10d' % (key, values[0], values[1]))
+        for key, values in sorted(s.items()):
+            print('%-42s%10d%10d' % (key.split(' ')[0], values.value,
+                  values.delta))
     except KeyboardInterrupt:
         pass
 
@@ -1392,14 +1444,14 @@ def log(stats):
     keys = sorted(stats.get().keys())
 
     def banner():
-        for k in keys:
-            print(k, end=' ')
+        for key in keys:
+            print(key.split(' ')[0], end=' ')
         print()
 
     def statline():
         s = stats.get()
-        for k in keys:
-            print(' %9d' % s[k][1], end=' ')
+        for key in keys:
+            print(' %9d' % s[key].delta, end=' ')
         print()
     line = 0
     banner_repeat = 20
@@ -1504,7 +1556,7 @@ Press any other key to refresh statistics immediately.
                          )
     optparser.add_option('-f', '--fields',
                          action='store',
-                         default=DEFAULT_REGEX,
+                         default='',
                          dest='fields',
                          help='''fields to display (regex)
                                  "-f help" for a list of available events''',
@@ -1539,17 +1591,6 @@ Press any other key to refresh statistics immediately.
 
 def check_access(options):
     """Exits if the current user can't access all needed directories."""
-    if not os.path.exists('/sys/kernel/debug'):
-        sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.')
-        sys.exit(1)
-
-    if not os.path.exists(PATH_DEBUGFS_KVM):
-        sys.stderr.write("Please make sure, that debugfs is mounted and "
-                         "readable by the current user:\n"
-                         "('mount -t debugfs debugfs /sys/kernel/debug')\n"
-                         "Also ensure, that the kvm modules are loaded.\n")
-        sys.exit(1)
-
     if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints or
                                                      not options.debugfs):
         sys.stderr.write("Please enable CONFIG_TRACING in your kernel "
@@ -1567,7 +1608,33 @@ def check_access(options):
     return options
 
 
+def assign_globals():
+    global PATH_DEBUGFS_KVM
+    global PATH_DEBUGFS_TRACING
+
+    debugfs = ''
+    for line in file('/proc/mounts'):
+        if line.split(' ')[0] == 'debugfs':
+            debugfs = line.split(' ')[1]
+            break
+    if debugfs == '':
+        sys.stderr.write("Please make sure that CONFIG_DEBUG_FS is enabled in "
+                         "your kernel, mounted and\nreadable by the current "
+                         "user:\n"
+                         "('mount -t debugfs debugfs /sys/kernel/debug')\n")
+        sys.exit(1)
+
+    PATH_DEBUGFS_KVM = os.path.join(debugfs, 'kvm')
+    PATH_DEBUGFS_TRACING = os.path.join(debugfs, 'tracing')
+
+    if not os.path.exists(PATH_DEBUGFS_KVM):
+        sys.stderr.write("Please make sure that CONFIG_KVM is enabled in "
+                         "your kernel and that the modules are loaded.\n")
+        sys.exit(1)
+
+
 def main():
+    assign_globals()
     options = get_options()
     options = check_access(options)
 
index b5b3810c9e945d7f3a39568840fbc5b73f84983b..0811d860fe75000de852c569ccaaa3ae1f0aa944 100644 (file)
@@ -35,13 +35,13 @@ INTERACTIVE COMMANDS
 
 *f*::  filter by regular expression
 
-*g*::  filter by guest name
+*g*::  filter by guest name/PID
 
 *h*::  display interactive commands reference
 
 *o*::   toggle sorting order (Total vs CurAvg/s)
 
-*p*::  filter by PID
+*p*::  filter by guest name/PID
 
 *q*::  quit
 
index 57254f5b2779fb02276f00eb82401a05eaaabeb0..694abc628e9b3060b2252c1e8c86af4d6176e518 100644 (file)
@@ -29,7 +29,7 @@
 #include "builtin.h"
 #include "check.h"
 
-bool no_fp, no_unreachable;
+bool no_fp, no_unreachable, retpoline, module;
 
 static const char * const check_usage[] = {
        "objtool check [<options>] file.o",
@@ -39,6 +39,8 @@ static const char * const check_usage[] = {
 const struct option check_options[] = {
        OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"),
        OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
+       OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"),
+       OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"),
        OPT_END(),
 };
 
@@ -53,5 +55,5 @@ int cmd_check(int argc, const char **argv)
 
        objname = argv[0];
 
-       return check(objname, no_fp, no_unreachable, false);
+       return check(objname, false);
 }
index 91e8e19ff5e06193adc55c455b4d97ad947da7ee..77ea2b97117d2fd586e52294593c4d0c23a55ecd 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include <string.h>
-#include <subcmd/parse-options.h>
 #include "builtin.h"
 #include "check.h"
 
@@ -36,9 +35,6 @@ static const char *orc_usage[] = {
        NULL,
 };
 
-extern const struct option check_options[];
-extern bool no_fp, no_unreachable;
-
 int cmd_orc(int argc, const char **argv)
 {
        const char *objname;
@@ -54,7 +50,7 @@ int cmd_orc(int argc, const char **argv)
 
                objname = argv[0];
 
-               return check(objname, no_fp, no_unreachable, true);
+               return check(objname, true);
        }
 
        if (!strcmp(argv[0], "dump")) {
index dd526067fed5ebcacbb45b7ce8a686437bd83d1a..28ff40e19a1413823b9b06ae4d1f1b42d922e850 100644 (file)
 #ifndef _BUILTIN_H
 #define _BUILTIN_H
 
+#include <subcmd/parse-options.h>
+
+extern const struct option check_options[];
+extern bool no_fp, no_unreachable, retpoline, module;
+
 extern int cmd_check(int argc, const char **argv);
 extern int cmd_orc(int argc, const char **argv);
 
index a8cb69a2657658ec41c5877f1b4a47526c8079b0..472e64e95891e671b0c13c0d851e6defdc8e5b2c 100644 (file)
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "builtin.h"
 #include "check.h"
 #include "elf.h"
 #include "special.h"
@@ -33,7 +34,6 @@ struct alternative {
 };
 
 const char *objname;
-static bool no_fp;
 struct cfi_state initial_func_cfi;
 
 struct instruction *find_insn(struct objtool_file *file,
@@ -497,6 +497,7 @@ static int add_jump_destinations(struct objtool_file *file)
                         * disguise, so convert them accordingly.
                         */
                        insn->type = INSN_JUMP_DYNAMIC;
+                       insn->retpoline_safe = true;
                        continue;
                } else {
                        /* sibling call */
@@ -548,7 +549,8 @@ static int add_call_destinations(struct objtool_file *file)
                        if (!insn->call_dest && !insn->ignore) {
                                WARN_FUNC("unsupported intra-function call",
                                          insn->sec, insn->offset);
-                               WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
+                               if (retpoline)
+                                       WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
                                return -1;
                        }
 
@@ -1108,6 +1110,54 @@ static int read_unwind_hints(struct objtool_file *file)
        return 0;
 }
 
+static int read_retpoline_hints(struct objtool_file *file)
+{
+       struct section *sec, *relasec;
+       struct instruction *insn;
+       struct rela *rela;
+       int i;
+
+       sec = find_section_by_name(file->elf, ".discard.retpoline_safe");
+       if (!sec)
+               return 0;
+
+       relasec = sec->rela;
+       if (!relasec) {
+               WARN("missing .rela.discard.retpoline_safe section");
+               return -1;
+       }
+
+       if (sec->len % sizeof(unsigned long)) {
+               WARN("retpoline_safe size mismatch: %d %ld", sec->len, sizeof(unsigned long));
+               return -1;
+       }
+
+       for (i = 0; i < sec->len / sizeof(unsigned long); i++) {
+               rela = find_rela_by_dest(sec, i * sizeof(unsigned long));
+               if (!rela) {
+                       WARN("can't find rela for retpoline_safe[%d]", i);
+                       return -1;
+               }
+
+               insn = find_insn(file, rela->sym->sec, rela->addend);
+               if (!insn) {
+                       WARN("can't find insn for retpoline_safe[%d]", i);
+                       return -1;
+               }
+
+               if (insn->type != INSN_JUMP_DYNAMIC &&
+                   insn->type != INSN_CALL_DYNAMIC) {
+                       WARN_FUNC("retpoline_safe hint not a indirect jump/call",
+                                 insn->sec, insn->offset);
+                       return -1;
+               }
+
+               insn->retpoline_safe = true;
+       }
+
+       return 0;
+}
+
 static int decode_sections(struct objtool_file *file)
 {
        int ret;
@@ -1146,6 +1196,10 @@ static int decode_sections(struct objtool_file *file)
        if (ret)
                return ret;
 
+       ret = read_retpoline_hints(file);
+       if (ret)
+               return ret;
+
        return 0;
 }
 
@@ -1891,6 +1945,38 @@ static int validate_unwind_hints(struct objtool_file *file)
        return warnings;
 }
 
+static int validate_retpoline(struct objtool_file *file)
+{
+       struct instruction *insn;
+       int warnings = 0;
+
+       for_each_insn(file, insn) {
+               if (insn->type != INSN_JUMP_DYNAMIC &&
+                   insn->type != INSN_CALL_DYNAMIC)
+                       continue;
+
+               if (insn->retpoline_safe)
+                       continue;
+
+               /*
+                * .init.text code is ran before userspace and thus doesn't
+                * strictly need retpolines, except for modules which are
+                * loaded late, they very much do need retpoline in their
+                * .init.text
+                */
+               if (!strcmp(insn->sec->name, ".init.text") && !module)
+                       continue;
+
+               WARN_FUNC("indirect %s found in RETPOLINE build",
+                         insn->sec, insn->offset,
+                         insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
+
+               warnings++;
+       }
+
+       return warnings;
+}
+
 static bool is_kasan_insn(struct instruction *insn)
 {
        return (insn->type == INSN_CALL &&
@@ -2022,13 +2108,12 @@ static void cleanup(struct objtool_file *file)
        elf_close(file->elf);
 }
 
-int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc)
+int check(const char *_objname, bool orc)
 {
        struct objtool_file file;
        int ret, warnings = 0;
 
        objname = _objname;
-       no_fp = _no_fp;
 
        file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY);
        if (!file.elf)
@@ -2052,6 +2137,13 @@ int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc)
        if (list_empty(&file.insn_list))
                goto out;
 
+       if (retpoline) {
+               ret = validate_retpoline(&file);
+               if (ret < 0)
+                       return ret;
+               warnings += ret;
+       }
+
        ret = validate_functions(&file);
        if (ret < 0)
                goto out;
index 23a1d065cae190c11432bd2c768f38c7f91e470b..c6b68fcb926ff76c6e44675ff636c16f3552a184 100644 (file)
@@ -45,6 +45,7 @@ struct instruction {
        unsigned char type;
        unsigned long immediate;
        bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
+       bool retpoline_safe;
        struct symbol *call_dest;
        struct instruction *jump_dest;
        struct instruction *first_jump_src;
@@ -63,7 +64,7 @@ struct objtool_file {
        bool ignore_unreachables, c_file, hints;
 };
 
-int check(const char *objname, bool no_fp, bool no_unreachable, bool orc);
+int check(const char *objname, bool orc);
 
 struct instruction *find_insn(struct objtool_file *file,
                              struct section *sec, unsigned long offset);
index 44ef9eba5a7a2181004676cfa28f330cfb576b6a..6c645eb77d4218fd102968fb2a24b19350e3edd9 100644 (file)
@@ -178,6 +178,55 @@ void idr_get_next_test(int base)
        idr_destroy(&idr);
 }
 
+int idr_u32_cb(int id, void *ptr, void *data)
+{
+       BUG_ON(id < 0);
+       BUG_ON(ptr != DUMMY_PTR);
+       return 0;
+}
+
+void idr_u32_test1(struct idr *idr, u32 handle)
+{
+       static bool warned = false;
+       u32 id = handle;
+       int sid = 0;
+       void *ptr;
+
+       BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL));
+       BUG_ON(id != handle);
+       BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL) != -ENOSPC);
+       BUG_ON(id != handle);
+       if (!warned && id > INT_MAX)
+               printk("vvv Ignore these warnings\n");
+       ptr = idr_get_next(idr, &sid);
+       if (id > INT_MAX) {
+               BUG_ON(ptr != NULL);
+               BUG_ON(sid != 0);
+       } else {
+               BUG_ON(ptr != DUMMY_PTR);
+               BUG_ON(sid != id);
+       }
+       idr_for_each(idr, idr_u32_cb, NULL);
+       if (!warned && id > INT_MAX) {
+               printk("^^^ Warnings over\n");
+               warned = true;
+       }
+       BUG_ON(idr_remove(idr, id) != DUMMY_PTR);
+       BUG_ON(!idr_is_empty(idr));
+}
+
+void idr_u32_test(int base)
+{
+       DEFINE_IDR(idr);
+       idr_init_base(&idr, base);
+       idr_u32_test1(&idr, 10);
+       idr_u32_test1(&idr, 0x7fffffff);
+       idr_u32_test1(&idr, 0x80000000);
+       idr_u32_test1(&idr, 0x80000001);
+       idr_u32_test1(&idr, 0xffe00000);
+       idr_u32_test1(&idr, 0xffffffff);
+}
+
 void idr_checks(void)
 {
        unsigned long i;
@@ -248,6 +297,9 @@ void idr_checks(void)
        idr_get_next_test(0);
        idr_get_next_test(1);
        idr_get_next_test(4);
+       idr_u32_test(4);
+       idr_u32_test(1);
+       idr_u32_test(0);
 }
 
 /*
index 6903ccf35595f560350a26d03e3eb4369fbb128b..44a0d1ad4408429d67378bf185773f77b3461ab8 100644 (file)
@@ -29,7 +29,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
 {
        struct radix_tree_node *node;
 
-       if (flags & __GFP_NOWARN)
+       if (!(flags & __GFP_DIRECT_RECLAIM))
                return NULL;
 
        pthread_mutex_lock(&cachep->lock);
@@ -73,10 +73,17 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 
 void *kmalloc(size_t size, gfp_t gfp)
 {
-       void *ret = malloc(size);
+       void *ret;
+
+       if (!(gfp & __GFP_DIRECT_RECLAIM))
+               return NULL;
+
+       ret = malloc(size);
        uatomic_inc(&nr_allocated);
        if (kmalloc_verbose)
                printf("Allocating %p from malloc\n", ret);
+       if (gfp & __GFP_ZERO)
+               memset(ret, 0, size);
        return ret;
 }
 
diff --git a/tools/testing/radix-tree/linux/compiler_types.h b/tools/testing/radix-tree/linux/compiler_types.h
new file mode 100644 (file)
index 0000000..e69de29
index e9fff59dfd8a86cb6022d0dc6e5321a3d9a4f636..e3201ccf54c3c46dc7ffaf9bc6185edd406a6b95 100644 (file)
@@ -11,6 +11,7 @@
 #define __GFP_IO               0x40u
 #define __GFP_FS               0x80u
 #define __GFP_NOWARN           0x200u
+#define __GFP_ZERO             0x8000u
 #define __GFP_ATOMIC           0x80000u
 #define __GFP_ACCOUNT          0x100000u
 #define __GFP_DIRECT_RECLAIM   0x400000u
index 979baeec7e706aee05ef6bdfbf8dd91494284dd2..a037def0dec637ef9a38b034de5ac1fed4d32d8e 100644 (file)
@@ -3,6 +3,7 @@
 #define SLAB_H
 
 #include <linux/types.h>
+#include <linux/gfp.h>
 
 #define SLAB_HWCACHE_ALIGN 1
 #define SLAB_PANIC 2
 void *kmalloc(size_t size, gfp_t);
 void kfree(void *);
 
+static inline void *kzalloc(size_t size, gfp_t gfp)
+{
+        return kmalloc(size, gfp | __GFP_ZERO);
+}
+
 void *kmem_cache_alloc(struct kmem_cache *cachep, int flags);
 void kmem_cache_free(struct kmem_cache *cachep, void *objp);
 
index 1a74922689930ce1829afaa5f91b701f97861b07..f6304d2be90c16e7b818415d867704abda3ecf09 100644 (file)
@@ -11,11 +11,11 @@ all:
                BUILD_TARGET=$(OUTPUT)/$$DIR;   \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
-               #SUBDIR test prog name should be in the form: SUBDIR_test.sh
+               #SUBDIR test prog name should be in the form: SUBDIR_test.sh \
                TEST=$$DIR"_test.sh"; \
-               if [ -e $$DIR/$$TEST ]; then
-                       rsync -a $$DIR/$$TEST $$BUILD_TARGET/;
-               fi
+               if [ -e $$DIR/$$TEST ]; then \
+                       rsync -a $$DIR/$$TEST $$BUILD_TARGET/; \
+               fi \
        done
 
 override define RUN_TESTS
index cea4adcd42b8877f7e5a05d57a837bcc61c1d97d..a63e8453984d2793eb38b706236f31dc49527e9b 100644 (file)
@@ -12,9 +12,9 @@ all:
                BUILD_TARGET=$(OUTPUT)/$$DIR;   \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
-               if [ -e $$DIR/$(TEST_PROGS) ]; then
-                       rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/;
-               fi
+               if [ -e $$DIR/$(TEST_PROGS) ]; then \
+                       rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/; \
+               fi \
        done
 
 override define RUN_TESTS
diff --git a/tools/testing/selftests/memfd/config b/tools/testing/selftests/memfd/config
new file mode 100644 (file)
index 0000000..835c7f4
--- /dev/null
@@ -0,0 +1 @@
+CONFIG_FUSE_FS=m
index 86636d207adf72c12403355cae88d3bfe819fd80..183b46883875e8622bb91f1372f5458ea9aedbaf 100644 (file)
@@ -4,7 +4,7 @@ all:
 include ../lib.mk
 
 TEST_PROGS := mem-on-off-test.sh
-override RUN_TESTS := ./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]"
+override RUN_TESTS := @./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]"
 override EMIT_TESTS := echo "$(RUN_TESTS)"
 
 run_full_test:
index 6a8e5a9bfc1065a3e860cd5b31e7aea2d508bea8..d148f9f89fb64cf325a546a1855c1e1cc5fc8a21 100644 (file)
@@ -2,3 +2,4 @@ CONFIG_MISC_FILESYSTEMS=y
 CONFIG_PSTORE=y
 CONFIG_PSTORE_PMSG=y
 CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_RAM=m
index b3c8ba3cb66855ff93d6581f7428982be41fca60..d0121a8a3523a948af699e52b6adbf1cde37b030 100644 (file)
@@ -30,7 +30,7 @@ $(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS)
        $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS)
 
 $(OBJS): $(OUTPUT)/%.o: %.c
-       $(CC) -c $^ -o $@
+       $(CC) -c $^ -o $@ $(CFLAGS)
 
 $(TESTS): $(OUTPUT)/%.o: %.c
        $(CC) -c $^ -o $@
index 3d5a62ff7d31ed437fc5457a501ec9b606839f92..f5d7a7851e2177b315111f4e8ae3f0b0a716487d 100644 (file)
@@ -1,4 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
+include ../lib.mk
+
 ifndef CROSS_COMPILE
 CFLAGS := -std=gnu99
 CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
@@ -6,16 +8,14 @@ ifeq ($(CONFIG_X86_32),y)
 LDLIBS += -lgcc_s
 endif
 
-TEST_PROGS := vdso_test vdso_standalone_test_x86
+TEST_PROGS := $(OUTPUT)/vdso_test $(OUTPUT)/vdso_standalone_test_x86
 
 all: $(TEST_PROGS)
-vdso_test: parse_vdso.c vdso_test.c
-vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
+$(OUTPUT)/vdso_test: parse_vdso.c vdso_test.c
+$(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
        $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \
                vdso_standalone_test_x86.c parse_vdso.c \
-               -o vdso_standalone_test_x86
+               -o $@
 
-include ../lib.mk
-clean:
-       rm -fr $(TEST_PROGS)
+EXTRA_CLEAN := $(TEST_PROGS)
 endif
index 63c94d776e8970de2703b7416a76bffdeb101361..342c7bc9dc8c5d29441e27da5131d5312ea4bca8 100644 (file)
@@ -11,3 +11,4 @@ mlock-intersect-test
 mlock-random-test
 virtual_address_range
 gup_benchmark
+va_128TBswitch
index 70268c0bec799c0ce85c2f27267e0ab514c5f852..70f4c30918eb2682b638c326977b50e3568c7638 100644 (file)
@@ -36,6 +36,8 @@ static struct timecounter *timecounter;
 static unsigned int host_vtimer_irq;
 static u32 host_vtimer_irq_flags;
 
+static DEFINE_STATIC_KEY_FALSE(has_gic_active_state);
+
 static const struct kvm_irq_level default_ptimer_irq = {
        .irq    = 30,
        .level  = 1,
@@ -56,6 +58,12 @@ u64 kvm_phys_timer_read(void)
        return timecounter->cc->read(timecounter->cc);
 }
 
+static inline bool userspace_irqchip(struct kvm *kvm)
+{
+       return static_branch_unlikely(&userspace_irqchip_in_use) &&
+               unlikely(!irqchip_in_kernel(kvm));
+}
+
 static void soft_timer_start(struct hrtimer *hrt, u64 ns)
 {
        hrtimer_start(hrt, ktime_add_ns(ktime_get(), ns),
@@ -69,25 +77,6 @@ static void soft_timer_cancel(struct hrtimer *hrt, struct work_struct *work)
                cancel_work_sync(work);
 }
 
-static void kvm_vtimer_update_mask_user(struct kvm_vcpu *vcpu)
-{
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-
-       /*
-        * When using a userspace irqchip with the architected timers, we must
-        * prevent continuously exiting from the guest, and therefore mask the
-        * physical interrupt by disabling it on the host interrupt controller
-        * when the virtual level is high, such that the guest can make
-        * forward progress.  Once we detect the output level being
-        * de-asserted, we unmask the interrupt again so that we exit from the
-        * guest when the timer fires.
-        */
-       if (vtimer->irq.level)
-               disable_percpu_irq(host_vtimer_irq);
-       else
-               enable_percpu_irq(host_vtimer_irq, 0);
-}
-
 static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
 {
        struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
@@ -106,9 +95,9 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
        if (kvm_timer_should_fire(vtimer))
                kvm_timer_update_irq(vcpu, true, vtimer);
 
-       if (static_branch_unlikely(&userspace_irqchip_in_use) &&
-           unlikely(!irqchip_in_kernel(vcpu->kvm)))
-               kvm_vtimer_update_mask_user(vcpu);
+       if (userspace_irqchip(vcpu->kvm) &&
+           !static_branch_unlikely(&has_gic_active_state))
+               disable_percpu_irq(host_vtimer_irq);
 
        return IRQ_HANDLED;
 }
@@ -290,8 +279,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
        trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_ctx->irq.irq,
                                   timer_ctx->irq.level);
 
-       if (!static_branch_unlikely(&userspace_irqchip_in_use) ||
-           likely(irqchip_in_kernel(vcpu->kvm))) {
+       if (!userspace_irqchip(vcpu->kvm)) {
                ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
                                          timer_ctx->irq.irq,
                                          timer_ctx->irq.level,
@@ -350,12 +338,6 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
        phys_timer_emulate(vcpu);
 }
 
-static void __timer_snapshot_state(struct arch_timer_context *timer)
-{
-       timer->cnt_ctl = read_sysreg_el0(cntv_ctl);
-       timer->cnt_cval = read_sysreg_el0(cntv_cval);
-}
-
 static void vtimer_save_state(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
@@ -367,8 +349,10 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
        if (!vtimer->loaded)
                goto out;
 
-       if (timer->enabled)
-               __timer_snapshot_state(vtimer);
+       if (timer->enabled) {
+               vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
+               vtimer->cnt_cval = read_sysreg_el0(cntv_cval);
+       }
 
        /* Disable the virtual timer */
        write_sysreg_el0(0, cntv_ctl);
@@ -460,23 +444,43 @@ static void set_cntvoff(u64 cntvoff)
        kvm_call_hyp(__kvm_timer_set_cntvoff, low, high);
 }
 
-static void kvm_timer_vcpu_load_vgic(struct kvm_vcpu *vcpu)
+static inline void set_vtimer_irq_phys_active(struct kvm_vcpu *vcpu, bool active)
+{
+       int r;
+       r = irq_set_irqchip_state(host_vtimer_irq, IRQCHIP_STATE_ACTIVE, active);
+       WARN_ON(r);
+}
+
+static void kvm_timer_vcpu_load_gic(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
        bool phys_active;
-       int ret;
 
-       phys_active = kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
-
-       ret = irq_set_irqchip_state(host_vtimer_irq,
-                                   IRQCHIP_STATE_ACTIVE,
-                                   phys_active);
-       WARN_ON(ret);
+       if (irqchip_in_kernel(vcpu->kvm))
+               phys_active = kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
+       else
+               phys_active = vtimer->irq.level;
+       set_vtimer_irq_phys_active(vcpu, phys_active);
 }
 
-static void kvm_timer_vcpu_load_user(struct kvm_vcpu *vcpu)
+static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
 {
-       kvm_vtimer_update_mask_user(vcpu);
+       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+
+       /*
+        * When using a userspace irqchip with the architected timers and a
+        * host interrupt controller that doesn't support an active state, we
+        * must still prevent continuously exiting from the guest, and
+        * therefore mask the physical interrupt by disabling it on the host
+        * interrupt controller when the virtual level is high, such that the
+        * guest can make forward progress.  Once we detect the output level
+        * being de-asserted, we unmask the interrupt again so that we exit
+        * from the guest when the timer fires.
+        */
+       if (vtimer->irq.level)
+               disable_percpu_irq(host_vtimer_irq);
+       else
+               enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
 }
 
 void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
@@ -487,10 +491,10 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
        if (unlikely(!timer->enabled))
                return;
 
-       if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
-               kvm_timer_vcpu_load_user(vcpu);
+       if (static_branch_likely(&has_gic_active_state))
+               kvm_timer_vcpu_load_gic(vcpu);
        else
-               kvm_timer_vcpu_load_vgic(vcpu);
+               kvm_timer_vcpu_load_nogic(vcpu);
 
        set_cntvoff(vtimer->cntvoff);
 
@@ -555,18 +559,24 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
 
-       if (unlikely(!irqchip_in_kernel(vcpu->kvm))) {
-               __timer_snapshot_state(vtimer);
-               if (!kvm_timer_should_fire(vtimer)) {
-                       kvm_timer_update_irq(vcpu, false, vtimer);
-                       kvm_vtimer_update_mask_user(vcpu);
-               }
+       if (!kvm_timer_should_fire(vtimer)) {
+               kvm_timer_update_irq(vcpu, false, vtimer);
+               if (static_branch_likely(&has_gic_active_state))
+                       set_vtimer_irq_phys_active(vcpu, false);
+               else
+                       enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
        }
 }
 
 void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
 {
-       unmask_vtimer_irq_user(vcpu);
+       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+       if (unlikely(!timer->enabled))
+               return;
+
+       if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
+               unmask_vtimer_irq_user(vcpu);
 }
 
 int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
@@ -753,6 +763,8 @@ int kvm_timer_hyp_init(bool has_gic)
                        kvm_err("kvm_arch_timer: error setting vcpu affinity\n");
                        goto out_free_irq;
                }
+
+               static_branch_enable(&has_gic_active_state);
        }
 
        kvm_info("virtual timer IRQ%d\n", host_vtimer_irq);
index 4501e658e8d6fc97f39b54bceff8f8b1f36cb95a..65dea3ffef68ede4ca8d8e5bb7d9c2d3edd3352a 100644 (file)
@@ -969,8 +969,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
                /* Check for overlaps */
                r = -EEXIST;
                kvm_for_each_memslot(slot, __kvm_memslots(kvm, as_id)) {
-                       if ((slot->id >= KVM_USER_MEM_SLOTS) ||
-                           (slot->id == id))
+                       if (slot->id == id)
                                continue;
                        if (!((base_gfn + npages <= slot->base_gfn) ||
                              (base_gfn >= slot->base_gfn + slot->npages)))