OSDN Git Service

Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Feb 2020 00:34:41 +0000 (16:34 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Feb 2020 00:34:41 +0000 (16:34 -0800)
Pull networking fixes from David Miller:

 1) Fix leak in nl80211 AP start where we leak the ACL memory, from
    Johannes Berg.

 2) Fix double mutex unlock in mac80211, from Andrei Otcheretianski.

 3) Fix RCU stall in ipset, from Jozsef Kadlecsik.

 4) Fix devlink locking in devlink_dpipe_table_register, from Madhuparna
    Bhowmik.

 5) Fix race causing TX hang in ll_temac, from Esben Haabendal.

 6) Stale eth hdr pointer in br_dev_xmit(), from Nikolay Aleksandrov.

 7) Fix TX hash calculation bounds checking wrt. tc rules, from Amritha
    Nambiar.

 8) Size netlink responses properly in schedule action code to take into
    consideration TCA_ACT_FLAGS. From Jiri Pirko.

 9) Fix firmware paths for mscc PHY driver, from Antoine Tenart.

10) Don't register stmmac notifier multiple times, from Aaro Koskinen.

11) Various rmnet bug fixes, from Taehee Yoo.

12) Fix vsock deadlock in vsock transport release, from Stefano
    Garzarella.

* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (61 commits)
  net: dsa: mv88e6xxx: Fix masking of egress port
  mlxsw: pci: Wait longer before accessing the device after reset
  sfc: fix timestamp reconstruction at 16-bit rollover points
  vsock: fix potential deadlock in transport->release()
  unix: It's CONFIG_PROC_FS not CONFIG_PROCFS
  net: rmnet: fix packet forwarding in rmnet bridge mode
  net: rmnet: fix bridge mode bugs
  net: rmnet: use upper/lower device infrastructure
  net: rmnet: do not allow to change mux id if mux id is duplicated
  net: rmnet: remove rcu_read_lock in rmnet_force_unassociate_device()
  net: rmnet: fix suspicious RCU usage
  net: rmnet: fix NULL pointer dereference in rmnet_changelink()
  net: rmnet: fix NULL pointer dereference in rmnet_newlink()
  net: phy: marvell: don't interpret PHY status unless resolved
  mlx5: register lag notifier for init network namespace only
  unix: define and set show_fdinfo only if procfs is enabled
  hinic: fix a bug of rss configuration
  hinic: fix a bug of setting hw_ioctxt
  hinic: fix a irq affinity bug
  net/smc: check for valid ib_client_data
  ...

194 files changed:
.gitignore
CREDITS
Documentation/admin-guide/bootconfig.rst
Documentation/arm64/memory.rst
Documentation/arm64/tagged-address-abi.rst
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.yaml
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/net/mdio.yaml
Documentation/filesystems/zonefs.txt
Documentation/hwmon/xdpe12284.rst
Documentation/kbuild/makefiles.rst
Documentation/sphinx/parallel-wrapper.sh
Documentation/virt/kvm/api.rst
Documentation/x86/index.rst
MAINTAINERS
Makefile
arch/arm64/include/asm/lse.h
arch/arm64/include/asm/memory.h
arch/csky/Kconfig
arch/csky/Kconfig.platforms [new file with mode: 0644]
arch/csky/abiv1/inc/abi/cacheflush.h
arch/csky/abiv1/inc/abi/entry.h
arch/csky/abiv2/cacheflush.c
arch/csky/abiv2/inc/abi/cacheflush.h
arch/csky/abiv2/inc/abi/entry.h
arch/csky/configs/defconfig
arch/csky/include/asm/Kbuild
arch/csky/include/asm/cache.h
arch/csky/include/asm/cacheflush.h
arch/csky/include/asm/fixmap.h
arch/csky/include/asm/memory.h [new file with mode: 0644]
arch/csky/include/asm/mmu.h
arch/csky/include/asm/mmu_context.h
arch/csky/include/asm/pci.h [new file with mode: 0644]
arch/csky/include/asm/pgtable.h
arch/csky/include/asm/stackprotector.h [new file with mode: 0644]
arch/csky/include/asm/tcm.h [new file with mode: 0644]
arch/csky/include/uapi/asm/unistd.h
arch/csky/kernel/atomic.S
arch/csky/kernel/process.c
arch/csky/kernel/setup.c
arch/csky/kernel/smp.c
arch/csky/kernel/time.c
arch/csky/kernel/vmlinux.lds.S
arch/csky/mm/Makefile
arch/csky/mm/cachev1.c
arch/csky/mm/cachev2.c
arch/csky/mm/highmem.c
arch/csky/mm/init.c
arch/csky/mm/syscache.c
arch/csky/mm/tcm.c [new file with mode: 0644]
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/ingenic/jz4780.dtsi
arch/mips/boot/dts/ingenic/x1000.dtsi
arch/mips/include/asm/sync.h
arch/mips/kernel/vpe.c
arch/mips/vdso/Makefile
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_32.h
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/mm/book3s32/hash_low.S
arch/powerpc/mm/book3s32/mmu.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/kasan/kasan_init_32.c
arch/powerpc/xmon/xmon.c
arch/riscv/boot/.gitignore
arch/riscv/include/asm/csr.h
arch/riscv/kernel/head.S
arch/riscv/kernel/traps.c
arch/riscv/mm/kasan_init.c
arch/s390/Makefile
arch/s390/boot/Makefile
arch/s390/boot/kaslr.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/include/asm/page.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/qdio.h
arch/x86/boot/compressed/kaslr_64.c
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/vmx.h
arch/x86/include/asm/vmxfeatures.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kvm/emulate.c
arch/x86/kvm/irq_comm.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmutrace.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/capabilities.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/nested.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/xen/enlighten_pv.c
drivers/block/floppy.c
drivers/hid/hid-alps.c
drivers/hid/hid-apple.c
drivers/hid/hid-bigbenff.c
drivers/hid/hid-core.c
drivers/hid/hid-ite.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/w83627ehf.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/pci.c
drivers/platform/chrome/wilco_ec/properties.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chp.c
drivers/s390/cio/qdio_setup.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/net/qeth_core_main.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_qdio.h
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_transport.c
drivers/tee/amdtee/Kconfig
drivers/xen/preempt.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/qgroup.h
fs/btrfs/transaction.c
fs/ext4/balloc.c
fs/ext4/ext4.h
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/io_uring.c
fs/jbd2/transaction.c
include/linux/bootconfig.h
include/linux/hid.h
include/linux/irqdomain.h
include/linux/kvm_host.h
include/scsi/iscsi_proto.h
init/Kconfig
init/main.c
kernel/audit.c
kernel/auditfilter.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/proc.c
kernel/signal.c
kernel/sysctl.c
kernel/trace/Kconfig
kernel/trace/synth_event_gen_test.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
lib/bootconfig.c
lib/crypto/chacha20poly1305.c
mm/mmap.c
mm/mremap.c
mm/shmem.c
scripts/Makefile.lib
tools/bootconfig/include/linux/printk.h
tools/bootconfig/main.c
tools/bootconfig/samples/bad-mixed-kv1.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-mixed-kv2.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-samekey.bconf [new file with mode: 0644]
tools/bootconfig/test-bootconfig.sh
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_kernel.py
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/livepatch/Makefile
tools/testing/selftests/net/mptcp/Makefile
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rtc/Makefile

index 72ef86a..2763fce 100644 (file)
@@ -100,6 +100,10 @@ modules.order
 /include/ksym/
 /arch/*/include/generated/
 
+# Generated lkdtm tests
+/tools/testing/selftests/lkdtm/*.sh
+!/tools/testing/selftests/lkdtm/run.sh
+
 # stgit generated dirs
 patches-*
 
diff --git a/CREDITS b/CREDITS
index a97d328..032b599 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -567,6 +567,11 @@ D: Original author of Amiga FFS filesystem
 S: Orlando, Florida
 S: USA
 
+N: Paul Burton
+E: paulburton@kernel.org
+W: https://pburton.com
+D: MIPS maintainer 2018-2020
+
 N: Lennert Buytenhek
 E: kernel@wantstofly.org
 D: Original (2.4) rewrite of the ethernet bridging code
index b342a67..cf2edcd 100644 (file)
@@ -62,6 +62,30 @@ Or more shorter, written as following::
 In both styles, same key words are automatically merged when parsing it
 at boot time. So you can append similar trees or key-values.
 
+Same-key Values
+---------------
+
+It is prohibited that two or more values or arrays share a same-key.
+For example,::
+
+ foo = bar, baz
+ foo = qux  # !ERROR! we can not re-define same key
+
+If you want to append the value to existing key as an array member,
+you can use ``+=`` operator. For example::
+
+ foo = bar, baz
+ foo += qux
+
+In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``.
+
+However, a sub-key and a value can not co-exist under a parent key.
+For example, following config is NOT allowed.::
+
+ foo = value1
+ foo.bar = value2 # !ERROR! subkey "bar" and value "value1" can NOT co-exist
+
+
 Comments
 --------
 
@@ -102,9 +126,13 @@ Boot Kernel With a Boot Config
 ==============================
 
 Since the boot configuration file is loaded with initrd, it will be added
-to the end of the initrd (initramfs) image file. The Linux kernel decodes
-the last part of the initrd image in memory to get the boot configuration
-data.
+to the end of the initrd (initramfs) image file with size, checksum and
+12-byte magic word as below.
+
+[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
+
+The Linux kernel decodes the last part of the initrd image in memory to
+get the boot configuration data.
 Because of this "piggyback" method, there is no need to change or
 update the boot loader and the kernel image itself.
 
index 02e0217..cf03b32 100644 (file)
@@ -129,7 +129,7 @@ this logic.
 
 As a single binary will need to support both 48-bit and 52-bit VA
 spaces, the VMEMMAP must be sized large enough for 52-bit VAs and
-also must be sized large enought to accommodate a fixed PAGE_OFFSET.
+also must be sized large enough to accommodate a fixed PAGE_OFFSET.
 
 Most code in the kernel should not need to consider the VA_BITS, for
 code that does need to know the VA size the variables are
index d4a85d5..4a9d9c7 100644 (file)
@@ -44,8 +44,15 @@ The AArch64 Tagged Address ABI has two stages of relaxation depending
 how the user addresses are used by the kernel:
 
 1. User addresses not accessed by the kernel but used for address space
-   management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
-   of valid tagged pointers in this context is always allowed.
+   management (e.g. ``mprotect()``, ``madvise()``). The use of valid
+   tagged pointers in this context is allowed with the exception of
+   ``brk()``, ``mmap()`` and the ``new_address`` argument to
+   ``mremap()`` as these have the potential to alias with existing
+   user addresses.
+
+   NOTE: This behaviour changed in v5.6 and so some earlier kernels may
+   incorrectly accept valid tagged pointers for the ``brk()``,
+   ``mmap()`` and ``mremap()`` system calls.
 
 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
    relaxation is disabled by default and the application thread needs to
index 7cd56a1..607758a 100644 (file)
@@ -551,6 +551,7 @@ options to your ``.config``:
 Once the kernel is built and installed, a simple
 
 .. code-block:: bash
+
        modprobe example-test
 
 ...will run the tests.
index 9af873b..8453ee3 100644 (file)
@@ -33,24 +33,40 @@ properties:
     maxItems: 1
 
   clocks:
-    minItems: 2
-    maxItems: 3
-    items:
-      - description: The CSI interface clock
-      - description: The CSI ISP clock
-      - description: The CSI DRAM clock
+    oneOf:
+      - items:
+        - description: The CSI interface clock
+        - description: The CSI DRAM clock
+
+      - items:
+        - description: The CSI interface clock
+        - description: The CSI ISP clock
+        - description: The CSI DRAM clock
 
   clock-names:
-    minItems: 2
-    maxItems: 3
-    items:
-      - const: bus
-      - const: isp
-      - const: ram
+    oneOf:
+      - items:
+        - const: bus
+        - const: ram
+
+      - items:
+        - const: bus
+        - const: isp
+        - const: ram
 
   resets:
     maxItems: 1
 
+  # FIXME: This should be made required eventually once every SoC will
+  # have the MBUS declared.
+  interconnects:
+    maxItems: 1
+
+  # FIXME: This should be made required eventually once every SoC will
+  # have the MBUS declared.
+  interconnect-names:
+    const: dma-mem
+
   # See ./video-interfaces.txt for details
   port:
     type: object
index dd18434..3e0a8a9 100644 (file)
@@ -347,6 +347,7 @@ examples:
         interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 
         #iommu-cells = <1>;
+        #reset-cells = <1>;
     };
 
     external-memory-controller@7001b000 {
@@ -363,20 +364,23 @@ examples:
             timing-0 {
                 clock-frequency = <12750000>;
 
-                nvidia,emc-zcal-cnt-long = <0x00000042>;
-                nvidia,emc-auto-cal-interval = <0x001fffff>;
-                nvidia,emc-ctt-term-ctrl = <0x00000802>;
-                nvidia,emc-cfg = <0x73240000>;
-                nvidia,emc-cfg-2 = <0x000008c5>;
-                nvidia,emc-sel-dpd-ctrl = <0x00040128>;
-                nvidia,emc-bgbias-ctl0 = <0x00000008>;
                 nvidia,emc-auto-cal-config = <0xa1430000>;
                 nvidia,emc-auto-cal-config2 = <0x00000000>;
                 nvidia,emc-auto-cal-config3 = <0x00000000>;
-                nvidia,emc-mode-reset = <0x80001221>;
+                nvidia,emc-auto-cal-interval = <0x001fffff>;
+                nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                nvidia,emc-cfg = <0x73240000>;
+                nvidia,emc-cfg-2 = <0x000008c5>;
+                nvidia,emc-ctt-term-ctrl = <0x00000802>;
                 nvidia,emc-mode-1 = <0x80100003>;
                 nvidia,emc-mode-2 = <0x80200008>;
                 nvidia,emc-mode-4 = <0x00000000>;
+                nvidia,emc-mode-reset = <0x80001221>;
+                nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                nvidia,emc-zcal-cnt-long = <0x00000042>;
+                nvidia,emc-zcal-interval = <0x00000000>;
 
                 nvidia,emc-configuration = <
                     0x00000000 /* EMC_RC */
index 19f5508..4a9145e 100644 (file)
@@ -124,7 +124,7 @@ not every application needs SDIO irq, e.g. MMC cards.
                pinctrl-1 = <&mmc1_idle>;
                pinctrl-2 = <&mmc1_sleep>;
                ...
-               interrupts-extended = <&intc 64 &gpio2 28 GPIO_ACTIVE_LOW>;
+               interrupts-extended = <&intc 64 &gpio2 28 IRQ_TYPE_LEVEL_LOW>;
        };
 
        mmc1_idle : pinmux_cirq_pin {
index 5d08d2f..50c3397 100644 (file)
@@ -56,7 +56,6 @@ patternProperties:
 examples:
   - |
     davinci_mdio: mdio@5c030000 {
-        compatible = "ti,davinci_mdio";
         reg = <0x5c030000 0x1000>;
         #address-cells = <1>;
         #size-cells = <0>;
index 935bf22..d54fa98 100644 (file)
@@ -134,7 +134,7 @@ Sequential zone files can only be written sequentially, starting from the file
 end, that is, write operations can only be append writes. Zonefs makes no
 attempt at accepting random writes and will fail any write request that has a
 start offset not corresponding to the end of the file, or to the end of the last
-write issued and still in-flight (for asynchrnous I/O operations).
+write issued and still in-flight (for asynchronous I/O operations).
 
 Since dirty page writeback by the page cache does not guarantee a sequential
 write pattern, zonefs prevents buffered writes and writeable shared mappings
@@ -142,7 +142,7 @@ on sequential files. Only direct I/O writes are accepted for these files.
 zonefs relies on the sequential delivery of write I/O requests to the device
 implemented by the block layer elevator. An elevator implementing the sequential
 write feature for zoned block device (ELEVATOR_F_ZBD_SEQ_WRITE elevator feature)
-must be used. This type of elevator (e.g. mq-deadline) is the set by default
+must be used. This type of elevator (e.g. mq-deadline) is set by default
 for zoned block devices on device initialization.
 
 There are no restrictions on the type of I/O used for read operations in
@@ -196,7 +196,7 @@ additional conditions that result in I/O errors.
   may still happen in the case of a partial failure of a very large direct I/O
   operation split into multiple BIOs/requests or asynchronous I/O operations.
   If one of the write request within the set of sequential write requests
-  issued to the device fails, all write requests after queued after it will
+  issued to the device fails, all write requests queued after it will
   become unaligned and fail.
 
 * Delayed write errors: similarly to regular block devices, if the device side
@@ -207,7 +207,7 @@ additional conditions that result in I/O errors.
   causing all data to be dropped after the sector that caused the error.
 
 All I/O errors detected by zonefs are notified to the user with an error code
-return for the system call that trigered or detected the error. The recovery
+return for the system call that triggered or detected the error. The recovery
 actions taken by zonefs in response to I/O errors depend on the I/O type (read
 vs write) and on the reason for the error (bad sector, unaligned writes or zone
 condition change).
@@ -222,7 +222,7 @@ condition change).
 * A zone condition change to read-only or offline also always triggers zonefs
   I/O error recovery.
 
-Zonefs minimal I/O error recovery may change a file size and file access
+Zonefs minimal I/O error recovery may change a file size and file access
 permissions.
 
 * File size changes:
@@ -237,7 +237,7 @@ permissions.
   A file size may also be reduced to reflect a delayed write error detected on
   fsync(): in this case, the amount of data effectively written in the zone may
   be less than originally indicated by the file inode size. After such I/O
-  error, zonefs always fixes a file inode size to reflect the amount of data
+  error, zonefs always fixes the file inode size to reflect the amount of data
   persistently stored in the file zone.
 
 * Access permission changes:
@@ -281,11 +281,11 @@ Further notes:
   permissions to read-only applies to all files. The file system is remounted
   read-only.
 * Access permission and file size changes due to the device transitioning zones
-  to the offline condition are permanent. Remounting or reformating the device
+  to the offline condition are permanent. Remounting or reformatting the device
   with mkfs.zonefs (mkzonefs) will not change back offline zone files to a good
   state.
 * File access permission changes to read-only due to the device transitioning
-  zones to the read-only condition are permanent. Remounting or reformating
+  zones to the read-only condition are permanent. Remounting or reformatting
   the device will not re-enable file write access.
 * File access permission changes implied by the remount-ro, zone-ro and
   zone-offline mount options are temporary for zones in a good condition.
@@ -301,13 +301,13 @@ Mount options
 
 zonefs define the "errors=<behavior>" mount option to allow the user to specify
 zonefs behavior in response to I/O errors, inode size inconsistencies or zone
-condition chages. The defined behaviors are as follow:
+condition changes. The defined behaviors are as follow:
 * remount-ro (default)
 * zone-ro
 * zone-offline
 * repair
 
-The I/O error actions defined for each behavior is detailed in the previous
+The I/O error actions defined for each behavior are detailed in the previous
 section.
 
 Zonefs User Space Tools
index 6b7ae98..67d1f87 100644 (file)
@@ -24,6 +24,7 @@ This driver implements support for Infineon Multi-phase XDPE122 family
 dual loop voltage regulators.
 The family includes XDPE12284 and XDPE12254 devices.
 The devices from this family complaint with:
+
 - Intel VR13 and VR13HC rev 1.3, IMVP8 rev 1.2 and IMPVP9 rev 1.3 DC-DC
   converter specification.
 - Intel SVID rev 1.9. protocol.
index 0e0eb2c..6bc126a 100644 (file)
@@ -765,7 +765,7 @@ is not sufficient this sometimes needs to be explicit.
        Example::
 
                #arch/x86/boot/Makefile
-               subdir- := compressed/
+               subdir- := compressed
 
 The above assignment instructs kbuild to descend down in the
 directory compressed/ when "make clean" is executed.
@@ -1379,9 +1379,6 @@ See subsequent chapter for the syntax of the Kbuild file.
        in arch/$(ARCH)/include/(uapi/)/asm, Kbuild will automatically generate
        a wrapper of the asm-generic one.
 
-       The convention is to list one subdir per line and
-       preferably in alphabetic order.
-
 8 Kbuild Variables
 ==================
 
index 7daf513..e54c44c 100644 (file)
@@ -30,4 +30,4 @@ if [ -n "$parallel" ] ; then
        parallel="-j$parallel"
 fi
 
-exec "$sphinx" "$parallel" "$@"
+exec "$sphinx" $parallel "$@"
index 97a72a5..ebd383f 100644 (file)
@@ -4611,35 +4611,38 @@ unpins the VPA pages and releases all the device pages that are used to
 track the secure pages by hypervisor.
 
 4.122 KVM_S390_NORMAL_RESET
+---------------------------
 
-Capability: KVM_CAP_S390_VCPU_RESETS
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: KVM_CAP_S390_VCPU_RESETS
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the cpu reset definition in the POP (Principles Of Operation).
 
 4.123 KVM_S390_INITIAL_RESET
+----------------------------
 
-Capability: none
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: none
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the initial cpu reset definition in the POP. However, the cpu is not
 put into ESA mode. This reset is a superset of the normal reset.
 
 4.124 KVM_S390_CLEAR_RESET
+--------------------------
 
-Capability: KVM_CAP_S390_VCPU_RESETS
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: KVM_CAP_S390_VCPU_RESETS
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the clear cpu reset definition in the POP. However, the cpu is not put
index a8de2fb..265d9e9 100644 (file)
@@ -19,7 +19,6 @@ x86-specific Documentation
    tlb
    mtrr
    pat
-   intel_mpx
    intel-iommu
    intel_txt
    amd-memory-encryption
index 2af5fa7..8f27f40 100644 (file)
@@ -3649,6 +3649,7 @@ F:        sound/pci/oxygen/
 
 C-SKY ARCHITECTURE
 M:     Guo Ren <guoren@kernel.org>
+L:     linux-csky@vger.kernel.org
 T:     git https://github.com/c-sky/csky-linux.git
 S:     Supported
 F:     arch/csky/
@@ -11114,14 +11115,12 @@ S:    Maintained
 F:     drivers/usb/image/microtek.*
 
 MIPS
-M:     Ralf Baechle <ralf@linux-mips.org>
-M:     Paul Burton <paulburton@kernel.org>
+M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
 L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
-T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
-S:     Supported
+S:     Maintained
 F:     Documentation/devicetree/bindings/mips/
 F:     Documentation/mips/
 F:     arch/mips/
index aab38cb..1a1a0d2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -68,6 +68,7 @@ unexport GREP_OPTIONS
 #
 # If KBUILD_VERBOSE equals 0 then the above command will be hidden.
 # If KBUILD_VERBOSE equals 1 then the above command is displayed.
+# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
 #
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
@@ -1238,7 +1239,7 @@ ifneq ($(dtstree),)
 %.dtb: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
 
-PHONY += dtbs dtbs_install dt_binding_check
+PHONY += dtbs dtbs_install dtbs_check
 dtbs dtbs_check: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree)
 
@@ -1258,6 +1259,7 @@ PHONY += scripts_dtc
 scripts_dtc: scripts_basic
        $(Q)$(MAKE) $(build)=scripts/dtc
 
+PHONY += dt_binding_check
 dt_binding_check: scripts_dtc
        $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings
 
index d429f77..5d10051 100644 (file)
@@ -6,7 +6,7 @@
 
 #ifdef CONFIG_ARM64_LSE_ATOMICS
 
-#define __LSE_PREAMBLE ".arch armv8-a+lse\n"
+#define __LSE_PREAMBLE ".arch_extension lse\n"
 
 #include <linux/compiler_types.h>
 #include <linux/export.h>
index a4f9ca5..4d94676 100644 (file)
@@ -213,7 +213,7 @@ static inline unsigned long kaslr_offset(void)
        ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
 
 #define untagged_addr(addr)    ({                                      \
-       u64 __addr = (__force u64)addr;                                 \
+       u64 __addr = (__force u64)(addr);                                       \
        __addr &= __untagged_addr(__addr);                              \
        (__force __typeof__(addr))__addr;                               \
 })
index da09c88..047427f 100644 (file)
@@ -9,7 +9,6 @@ config CSKY
        select ARCH_USE_QUEUED_RWLOCKS if NR_CPUS>2
        select COMMON_CLK
        select CLKSRC_MMIO
-       select CLKSRC_OF
        select CSKY_MPINTC if CPU_CK860
        select CSKY_MP_TIMER if CPU_CK860
        select CSKY_APB_INTC
@@ -37,6 +36,7 @@ config CSKY
        select GX6605S_TIMER if CPU_CK610
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_AUDITSYSCALL
+       select HAVE_COPY_THREAD_TLS
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
@@ -47,8 +47,8 @@ config CSKY
        select HAVE_PERF_EVENTS
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
-       select HAVE_DMA_API_DEBUG
        select HAVE_DMA_CONTIGUOUS
+       select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
        select MAY_HAVE_SPARSE_IRQ
        select MODULES_USE_ELF_RELA if MODULES
@@ -59,6 +59,11 @@ config CSKY
        select TIMER_OF
        select USB_ARCH_HAS_EHCI
        select USB_ARCH_HAS_OHCI
+       select GENERIC_PCI_IOMAP
+       select HAVE_PCI
+       select PCI_DOMAINS_GENERIC if PCI
+       select PCI_SYSCALL if PCI
+       select PCI_MSI if PCI
 
 config CPU_HAS_CACHEV2
        bool
@@ -75,7 +80,7 @@ config CPU_HAS_TLBI
 config CPU_HAS_LDSTEX
        bool
        help
-         For SMP, CPU needs "ldex&stex" instrcutions to atomic operations.
+         For SMP, CPU needs "ldex&stex" instructions for atomic operations.
 
 config CPU_NEED_TLBSYNC
        bool
@@ -188,6 +193,40 @@ config CPU_PM_STOP
        bool "stop"
 endchoice
 
+menuconfig HAVE_TCM
+       bool "Tightly-Coupled/Sram Memory"
+       select GENERIC_ALLOCATOR
+       help
+         The implementation are not only used by TCM (Tightly-Coupled Meory)
+         but also used by sram on SOC bus. It follow existed linux tcm
+         software interface, so that old tcm application codes could be
+         re-used directly.
+
+if HAVE_TCM
+config ITCM_RAM_BASE
+       hex "ITCM ram base"
+       default 0xffffffff
+
+config ITCM_NR_PAGES
+       int "Page count of ITCM size: NR*4KB"
+       range 1 256
+       default 32
+
+config HAVE_DTCM
+       bool "DTCM Support"
+
+config DTCM_RAM_BASE
+       hex "DTCM ram base"
+       depends on HAVE_DTCM
+       default 0xffffffff
+
+config DTCM_NR_PAGES
+       int "Page count of DTCM size: NR*4KB"
+       depends on HAVE_DTCM
+       range 1 256
+       default 32
+endif
+
 config CPU_HAS_VDSP
        bool "CPU has VDSP coprocessor"
        depends on CPU_HAS_FPU && CPU_HAS_FPUV2
@@ -196,6 +235,10 @@ config CPU_HAS_FPU
        bool "CPU has FPU coprocessor"
        depends on CPU_CK807 || CPU_CK810 || CPU_CK860
 
+config CPU_HAS_ICACHE_INS
+       bool "CPU has Icache invalidate instructions"
+       depends on CPU_HAS_CACHEV2
+
 config CPU_HAS_TEE
        bool "CPU has Trusted Execution Environment"
        depends on CPU_CK810
@@ -235,4 +278,6 @@ config HOTPLUG_CPU
          Say N if you want to disable CPU hotplug.
 endmenu
 
+source "arch/csky/Kconfig.platforms"
+
 source "kernel/Kconfig.hz"
diff --git a/arch/csky/Kconfig.platforms b/arch/csky/Kconfig.platforms
new file mode 100644 (file)
index 0000000..639e17f
--- /dev/null
@@ -0,0 +1,9 @@
+menu "Platform drivers selection"
+
+config ARCH_CSKY_DW_APB_ICTL
+       bool "Select dw-apb interrupt controller"
+       select DW_APB_ICTL
+       default y
+       help
+         This enables support for snps dw-apb-ictl
+endmenu
index 79ef9e8..d3e0420 100644 (file)
@@ -48,9 +48,8 @@ extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, u
 
 #define flush_icache_page(vma, page)           do {} while (0);
 #define flush_icache_range(start, end)         cache_wbinv_range(start, end)
-
-#define flush_icache_user_range(vma,page,addr,len) \
-       flush_dcache_page(page)
+#define flush_icache_mm_range(mm, start, end)  cache_wbinv_range(start, end)
+#define flush_icache_deferred(mm)              do {} while (0);
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 do { \
index 7ab78bd..f35a9f3 100644 (file)
 #define LSAVE_A4       40
 #define LSAVE_A5       44
 
+#define usp ss1
+
 .macro USPTOKSP
-       mtcr    sp, ss1
+       mtcr    sp, usp
        mfcr    sp, ss0
 .endm
 
 .macro KSPTOUSP
        mtcr    sp, ss0
-       mfcr    sp, ss1
+       mfcr    sp, usp
 .endm
 
 .macro SAVE_ALL epc_inc
        add     lr, r13
        stw     lr, (sp, 8)
 
+       mov     lr, sp
+       addi    lr, 32
+       addi    lr, 32
+       addi    lr, 16
+       bt      2f
        mfcr    lr, ss1
+2:
        stw     lr, (sp, 16)
 
        stw     a0, (sp, 20)
        ldw     a0, (sp, 12)
        mtcr    a0, epsr
        btsti   a0, 31
+       bt      1f
        ldw     a0, (sp, 16)
        mtcr    a0, ss1
-
+1:
        ldw     a0, (sp, 24)
        ldw     a1, (sp, 28)
        ldw     a2, (sp, 32)
        addi    sp, 32
        addi    sp, 8
 
-       bt      1f
+       bt      2f
        KSPTOUSP
-1:
+2:
        rte
 .endm
 
index 5bb887b..790f1eb 100644 (file)
@@ -6,46 +6,80 @@
 #include <linux/mm.h>
 #include <asm/cache.h>
 
-void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
+                     pte_t *pte)
 {
-       unsigned long start;
+       unsigned long addr;
+       struct page *page;
 
-       start = (unsigned long) kmap_atomic(page);
+       page = pfn_to_page(pte_pfn(*pte));
+       if (page == ZERO_PAGE(0))
+               return;
 
-       cache_wbinv_range(start, start + PAGE_SIZE);
+       if (test_and_set_bit(PG_dcache_clean, &page->flags))
+               return;
 
-       kunmap_atomic((void *)start);
-}
+       addr = (unsigned long) kmap_atomic(page);
 
-void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
-                            unsigned long vaddr, int len)
-{
-       unsigned long kaddr;
+       dcache_wb_range(addr, addr + PAGE_SIZE);
 
-       kaddr = (unsigned long) kmap_atomic(page) + (vaddr & ~PAGE_MASK);
+       if (vma->vm_flags & VM_EXEC)
+               icache_inv_range(addr, addr + PAGE_SIZE);
+
+       kunmap_atomic((void *) addr);
+}
 
-       cache_wbinv_range(kaddr, kaddr + len);
+void flush_icache_deferred(struct mm_struct *mm)
+{
+       unsigned int cpu = smp_processor_id();
+       cpumask_t *mask = &mm->context.icache_stale_mask;
 
-       kunmap_atomic((void *)kaddr);
+       if (cpumask_test_cpu(cpu, mask)) {
+               cpumask_clear_cpu(cpu, mask);
+               /*
+                * Ensure the remote hart's writes are visible to this hart.
+                * This pairs with a barrier in flush_icache_mm.
+                */
+               smp_mb();
+               local_icache_inv_all(NULL);
+       }
 }
 
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
-                     pte_t *pte)
+void flush_icache_mm_range(struct mm_struct *mm,
+               unsigned long start, unsigned long end)
 {
-       unsigned long addr, pfn;
-       struct page *page;
+       unsigned int cpu;
+       cpumask_t others, *mask;
 
-       pfn = pte_pfn(*pte);
-       if (unlikely(!pfn_valid(pfn)))
-               return;
+       preempt_disable();
 
-       page = pfn_to_page(pfn);
-       if (page == ZERO_PAGE(0))
+#ifdef CONFIG_CPU_HAS_ICACHE_INS
+       if (mm == current->mm) {
+               icache_inv_range(start, end);
+               preempt_enable();
                return;
+       }
+#endif
 
-       addr = (unsigned long) kmap_atomic(page);
+       /* Mark every hart's icache as needing a flush for this MM. */
+       mask = &mm->context.icache_stale_mask;
+       cpumask_setall(mask);
 
-       cache_wbinv_range(addr, addr + PAGE_SIZE);
+       /* Flush this hart's I$ now, and mark it as flushed. */
+       cpu = smp_processor_id();
+       cpumask_clear_cpu(cpu, mask);
+       local_icache_inv_all(NULL);
 
-       kunmap_atomic((void *) addr);
+       /*
+        * Flush the I$ of other harts concurrently executing, and mark them as
+        * flushed.
+        */
+       cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
+
+       if (mm != current->active_mm || !cpumask_empty(&others)) {
+               on_each_cpu_mask(&others, local_icache_inv_all, NULL, 1);
+               cpumask_clear(mask);
+       }
+
+       preempt_enable();
 }
index b8db5e0..a565e00 100644 (file)
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
 #define flush_cache_dup_mm(mm)                 do { } while (0)
+#define flush_cache_range(vma, start, end)     do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 
-#define flush_cache_range(vma, start, end) \
-       do { \
-               if (vma->vm_flags & VM_EXEC) \
-                       icache_inv_all(); \
-       } while (0)
+#define PG_dcache_clean                PG_arch_1
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+static inline void flush_dcache_page(struct page *page)
+{
+       if (test_bit(PG_dcache_clean, &page->flags))
+               clear_bit(PG_dcache_clean, &page->flags);
+}
 
-#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)                        do { } while (0)
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#define flush_icache_page(vma, page)           do { } while (0)
 
 #define flush_icache_range(start, end)         cache_wbinv_range(start, end)
 
-void flush_icache_page(struct vm_area_struct *vma, struct page *page);
-void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
-                            unsigned long vaddr, int len);
+void flush_icache_mm_range(struct mm_struct *mm,
+                       unsigned long start, unsigned long end);
+void flush_icache_deferred(struct mm_struct *mm);
 
 #define flush_cache_vmap(start, end)           do { } while (0)
 #define flush_cache_vunmap(start, end)         do { } while (0)
@@ -38,7 +41,13 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 do { \
        memcpy(dst, src, len); \
-       cache_wbinv_range((unsigned long)dst, (unsigned long)dst + len); \
+       if (vma->vm_flags & VM_EXEC) { \
+               dcache_wb_range((unsigned long)dst, \
+                               (unsigned long)dst + len); \
+               flush_icache_mm_range(current->mm, \
+                               (unsigned long)dst, \
+                               (unsigned long)dst + len); \
+               } \
 } while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
        memcpy(dst, src, len)
index 9897a16..94a7a58 100644 (file)
 
        mfcr    lr, epsr
        stw     lr, (sp, 12)
+       btsti   lr, 31
+       bf      1f
+       addi    lr, sp, 152
+       br      2f
+1:
        mfcr    lr, usp
+2:
        stw     lr, (sp, 16)
 
        stw     a0, (sp, 20)
        mtcr    a0, epc
        ldw     a0, (sp, 12)
        mtcr    a0, epsr
+       btsti   a0, 31
        ldw     a0, (sp, 16)
        mtcr    a0, usp
+       mtcr    a0, ss0
 
 #ifdef CONFIG_CPU_HAS_HILO
        ldw     a0, (sp, 140)
@@ -86,6 +94,9 @@
        addi    sp, 40
        ldm     r16-r30, (sp)
        addi    sp, 72
+       bf      1f
+       mfcr    sp, ss0
+1:
        rte
 .endm
 
index 7ef4289..af722e4 100644 (file)
@@ -10,9 +10,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_DEFAULT_DEADLINE=y
-CONFIG_CPU_CK807=y
-CONFIG_CPU_HAS_FPU=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -27,10 +24,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_TTY_PRINTK=y
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_CSKY_MPTIMER=y
-CONFIG_GX6605S_TIMER=y
 CONFIG_PM_DEVFREQ=y
 CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
 CONFIG_DEVFREQ_GOV_PERFORMANCE=y
@@ -56,6 +50,4 @@ CONFIG_CRAMFS=y
 CONFIG_ROMFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
index bc15a26..4130e3e 100644 (file)
@@ -28,7 +28,6 @@ generic-y += local64.h
 generic-y += mm-arch-hooks.h
 generic-y += mmiowb.h
 generic-y += module.h
-generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += qrwlock.h
index 1d5fc2f..4b5c09b 100644 (file)
@@ -16,6 +16,7 @@ void dcache_wb_line(unsigned long start);
 
 void icache_inv_range(unsigned long start, unsigned long end);
 void icache_inv_all(void);
+void local_icache_inv_all(void *priv);
 
 void dcache_wb_range(unsigned long start, unsigned long end);
 void dcache_wbinv_all(void);
index a96da67..f0b8f25 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef __ASM_CSKY_CACHEFLUSH_H
 #define __ASM_CSKY_CACHEFLUSH_H
 
+#include <linux/mm.h>
 #include <abi/cacheflush.h>
 
 #endif /* __ASM_CSKY_CACHEFLUSH_H */
index 380ff0a..81f9477 100644 (file)
@@ -5,12 +5,16 @@
 #define __ASM_CSKY_FIXMAP_H
 
 #include <asm/page.h>
+#include <asm/memory.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
 #endif
 
 enum fixed_addresses {
+#ifdef CONFIG_HAVE_TCM
+       FIX_TCM = TCM_NR_PAGES,
+#endif
 #ifdef CONFIG_HIGHMEM
        FIX_KMAP_BEGIN,
        FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
@@ -18,10 +22,13 @@ enum fixed_addresses {
        __end_of_fixed_addresses
 };
 
-#define FIXADDR_TOP    0xffffc000
 #define FIXADDR_SIZE   (__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START  (FIXADDR_TOP - FIXADDR_SIZE)
 
 #include <asm-generic/fixmap.h>
 
+extern void fixrange_init(unsigned long start, unsigned long end,
+       pgd_t *pgd_base);
+extern void __init fixaddr_init(void);
+
 #endif /* __ASM_CSKY_FIXMAP_H */
diff --git a/arch/csky/include/asm/memory.h b/arch/csky/include/asm/memory.h
new file mode 100644 (file)
index 0000000..a65c675
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_CSKY_MEMORY_H
+#define __ASM_CSKY_MEMORY_H
+
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+
+#define FIXADDR_TOP    _AC(0xffffc000, UL)
+#define PKMAP_BASE     _AC(0xff800000, UL)
+#define VMALLOC_START  _AC(0xc0008000, UL)
+#define VMALLOC_END    (PKMAP_BASE - (PAGE_SIZE * 2))
+
+#ifdef CONFIG_HAVE_TCM
+#ifdef CONFIG_HAVE_DTCM
+#define TCM_NR_PAGES   (CONFIG_ITCM_NR_PAGES + CONFIG_DTCM_NR_PAGES)
+#else
+#define TCM_NR_PAGES   (CONFIG_ITCM_NR_PAGES)
+#endif
+#define FIXADDR_TCM    _AC(FIXADDR_TOP - (TCM_NR_PAGES * PAGE_SIZE), UL)
+#endif
+
+#endif
index b382a14..26fbb1d 100644 (file)
@@ -7,6 +7,7 @@
 typedef struct {
        atomic64_t      asid;
        void *vdso;
+       cpumask_t       icache_stale_mask;
 } mm_context_t;
 
 #endif /* __ASM_CSKY_MMU_H */
index 0285b0a..abdf1f1 100644 (file)
@@ -43,5 +43,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
        write_mmu_entryhi(next->context.asid.counter);
+
+       flush_icache_deferred(next);
 }
 #endif /* __ASM_CSKY_MMU_CONTEXT_H */
diff --git a/arch/csky/include/asm/pci.h b/arch/csky/include/asm/pci.h
new file mode 100644 (file)
index 0000000..ebc765b
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_CSKY_PCI_H
+#define __ASM_CSKY_PCI_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+
+#define PCIBIOS_MIN_IO         0
+#define PCIBIOS_MIN_MEM                0
+
+/* C-SKY shim does not initialize PCI bus */
+#define pcibios_assign_all_busses() 1
+
+extern int isa_dma_bridge_buggy;
+
+#ifdef CONFIG_PCI
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       /* no legacy IRQ on csky */
+       return -ENODEV;
+}
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+       /* always show the domain in /proc */
+       return 1;
+}
+#endif  /* CONFIG_PCI */
+
+#endif  /* __ASM_CSKY_PCI_H */
index 4b2a41e..9b7764c 100644 (file)
@@ -5,6 +5,7 @@
 #define __ASM_CSKY_PGTABLE_H
 
 #include <asm/fixmap.h>
+#include <asm/memory.h>
 #include <asm/addrspace.h>
 #include <abi/pgtable-bits.h>
 #include <asm-generic/pgtable-nopmd.h>
 #define USER_PTRS_PER_PGD      (0x80000000UL/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS     0UL
 
-#define PKMAP_BASE             (0xff800000)
-
-#define VMALLOC_START          (0xc0008000)
-#define VMALLOC_END            (PKMAP_BASE - 2*PAGE_SIZE)
-
 /*
  * C-SKY is two-level paging structure:
  */
diff --git a/arch/csky/include/asm/stackprotector.h b/arch/csky/include/asm/stackprotector.h
new file mode 100644 (file)
index 0000000..d7cd4e5
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_STACKPROTECTOR_H
+#define _ASM_STACKPROTECTOR_H 1
+
+#include <linux/random.h>
+#include <linux/version.h>
+
+extern unsigned long __stack_chk_guard;
+
+/*
+ * Initialize the stackprotector canary value.
+ *
+ * NOTE: this must only be called from functions that never return,
+ * and it must always be inlined.
+ */
+static __always_inline void boot_init_stack_canary(void)
+{
+       unsigned long canary;
+
+       /* Try to get a semi random initial value. */
+       get_random_bytes(&canary, sizeof(canary));
+       canary ^= LINUX_VERSION_CODE;
+       canary &= CANARY_MASK;
+
+       current->stack_canary = canary;
+       __stack_chk_guard = current->stack_canary;
+}
+
+#endif /* __ASM_SH_STACKPROTECTOR_H */
diff --git a/arch/csky/include/asm/tcm.h b/arch/csky/include/asm/tcm.h
new file mode 100644 (file)
index 0000000..2b135ce
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_CSKY_TCM_H
+#define __ASM_CSKY_TCM_H
+
+#ifndef CONFIG_HAVE_TCM
+#error "You should not be including tcm.h unless you have a TCM!"
+#endif
+
+#include <linux/compiler.h>
+
+/* Tag variables with this */
+#define __tcmdata __section(.tcm.data)
+/* Tag constants with this */
+#define __tcmconst __section(.tcm.rodata)
+/* Tag functions inside TCM called from outside TCM with this */
+#define __tcmfunc __section(.tcm.text) noinline
+/* Tag function inside TCM called from inside TCM  with this */
+#define __tcmlocalfunc __section(.tcm.text)
+
+void *tcm_alloc(size_t len);
+void tcm_free(void *addr, size_t len);
+
+#endif
index 211c983..ba40189 100644 (file)
@@ -1,7 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
 #include <asm-generic/unistd.h>
index 5b84f11..3821ef9 100644 (file)
@@ -17,10 +17,12 @@ ENTRY(csky_cmpxchg)
        mfcr    a3, epc
        addi    a3, TRAP0_SIZE
 
-       subi    sp, 8
+       subi    sp, 16
        stw     a3, (sp, 0)
        mfcr    a3, epsr
        stw     a3, (sp, 4)
+       mfcr    a3, usp
+       stw     a3, (sp, 8)
 
        psrset  ee
 #ifdef CONFIG_CPU_HAS_LDSTEX
@@ -47,7 +49,9 @@ ENTRY(csky_cmpxchg)
        mtcr    a3, epc
        ldw     a3, (sp, 4)
        mtcr    a3, epsr
-       addi    sp, 8
+       ldw     a3, (sp, 8)
+       mtcr    a3, usp
+       addi    sp, 16
        KSPTOUSP
        rte
 END(csky_cmpxchg)
index f320d92..f7b231c 100644 (file)
 
 struct cpuinfo_csky cpu_data[NR_CPUS];
 
+#ifdef CONFIG_STACKPROTECTOR
+#include <linux/stackprotector.h>
+unsigned long __stack_chk_guard __read_mostly;
+EXPORT_SYMBOL(__stack_chk_guard);
+#endif
+
 asmlinkage void ret_from_fork(void);
 asmlinkage void ret_from_kernel_thread(void);
 
@@ -34,10 +40,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sw->r15;
 }
 
-int copy_thread(unsigned long clone_flags,
+int copy_thread_tls(unsigned long clone_flags,
                unsigned long usp,
                unsigned long kthread_arg,
-               struct task_struct *p)
+               struct task_struct *p,
+               unsigned long tls)
 {
        struct switch_stack *childstack;
        struct pt_regs *childregs = task_pt_regs(p);
@@ -64,7 +71,7 @@ int copy_thread(unsigned long clone_flags,
                        childregs->usp = usp;
                if (clone_flags & CLONE_SETTLS)
                        task_thread_info(p)->tp_value = childregs->tls
-                                                     = childregs->regs[0];
+                                                     = tls;
 
                childregs->a0 = 0;
                childstack->r15 = (unsigned long) ret_from_fork;
index 52eaf31..3821e55 100644 (file)
@@ -47,9 +47,6 @@ static void __init csky_memblock_init(void)
        signed long size;
 
        memblock_reserve(__pa(_stext), _end - _stext);
-#ifdef CONFIG_BLK_DEV_INITRD
-       memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
-#endif
 
        early_init_fdt_reserve_self();
        early_init_fdt_scan_reserved_mem();
@@ -133,6 +130,8 @@ void __init setup_arch(char **cmdline_p)
 
        sparse_init();
 
+       fixaddr_init();
+
 #ifdef CONFIG_HIGHMEM
        kmap_init();
 #endif
index b753d38..0bb0954 100644 (file)
@@ -120,7 +120,7 @@ void __init setup_smp_ipi(void)
        int rc;
 
        if (ipi_irq == 0)
-               panic("%s IRQ mapping failed\n", __func__);
+               return;
 
        rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt",
                                &ipi_dummy_dev);
index b5fc944..52379d8 100644 (file)
@@ -1,8 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
-#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
+#include <linux/of_clk.h>
 
 void __init time_init(void)
 {
index 2ff37be..f05b413 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <asm/vmlinux.lds.h>
 #include <asm/page.h>
+#include <asm/memory.h>
 
 OUTPUT_ARCH(csky)
 ENTRY(_start)
@@ -53,6 +54,54 @@ SECTIONS
        RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
        _edata = .;
 
+#ifdef CONFIG_HAVE_TCM
+       .tcm_start : {
+               . = ALIGN(PAGE_SIZE);
+               __tcm_start = .;
+       }
+
+       .text_data_tcm FIXADDR_TCM : AT(__tcm_start)
+       {
+               . = ALIGN(4);
+               __stcm_text_data = .;
+               *(.tcm.text)
+               *(.tcm.rodata)
+#ifndef CONFIG_HAVE_DTCM
+               *(.tcm.data)
+#endif
+               . = ALIGN(4);
+               __etcm_text_data = .;
+       }
+
+       . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_data_tcm);
+
+#ifdef CONFIG_HAVE_DTCM
+       #define ITCM_SIZE       CONFIG_ITCM_NR_PAGES * PAGE_SIZE
+
+       .dtcm_start : {
+               __dtcm_start = .;
+       }
+
+       .data_tcm FIXADDR_TCM + ITCM_SIZE : AT(__dtcm_start)
+       {
+               . = ALIGN(4);
+               __stcm_data = .;
+               *(.tcm.data)
+               . = ALIGN(4);
+               __etcm_data = .;
+       }
+
+       . = ADDR(.dtcm_start) + SIZEOF(.data_tcm);
+
+       .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_tcm)) {
+#else
+       .tcm_end : AT(ADDR(.tcm_start) + SIZEOF(.text_data_tcm)) {
+#endif
+               . = ALIGN(PAGE_SIZE);
+               __tcm_end = .;
+       }
+#endif
+
        EXCEPTION_TABLE(L1_CACHE_BYTES)
        BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES)
        VBR_BASE
index c94ef64..6e7696e 100644 (file)
@@ -1,8 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 ifeq ($(CONFIG_CPU_HAS_CACHEV2),y)
 obj-y +=                       cachev2.o
+CFLAGS_REMOVE_cachev2.o = $(CC_FLAGS_FTRACE)
 else
 obj-y +=                       cachev1.o
+CFLAGS_REMOVE_cachev1.o = $(CC_FLAGS_FTRACE)
 endif
 
 obj-y +=                       dma-mapping.o
@@ -14,3 +16,4 @@ obj-y +=                      syscache.o
 obj-y +=                       tlb.o
 obj-y +=                       asid.o
 obj-y +=                       context.o
+obj-$(CONFIG_HAVE_TCM) +=      tcm.o
index 494ec91..5a5a980 100644 (file)
@@ -94,6 +94,11 @@ void icache_inv_all(void)
        cache_op_all(INS_CACHE|CACHE_INV, 0);
 }
 
+void local_icache_inv_all(void *priv)
+{
+       cache_op_all(INS_CACHE|CACHE_INV, 0);
+}
+
 void dcache_wb_range(unsigned long start, unsigned long end)
 {
        cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
index b61be65..bc419f8 100644 (file)
@@ -3,15 +3,25 @@
 
 #include <linux/spinlock.h>
 #include <linux/smp.h>
+#include <linux/mm.h>
 #include <asm/cache.h>
 #include <asm/barrier.h>
 
-inline void dcache_wb_line(unsigned long start)
+#define INS_CACHE              (1 << 0)
+#define CACHE_INV              (1 << 4)
+
+void local_icache_inv_all(void *priv)
 {
-       asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
+       mtcr("cr17", INS_CACHE|CACHE_INV);
        sync_is();
 }
 
+void icache_inv_all(void)
+{
+       on_each_cpu(local_icache_inv_all, NULL, 1);
+}
+
+#ifdef CONFIG_CPU_HAS_ICACHE_INS
 void icache_inv_range(unsigned long start, unsigned long end)
 {
        unsigned long i = start & ~(L1_CACHE_BYTES - 1);
@@ -20,43 +30,32 @@ void icache_inv_range(unsigned long start, unsigned long end)
                asm volatile("icache.iva %0\n"::"r"(i):"memory");
        sync_is();
 }
-
-void icache_inv_all(void)
+#else
+void icache_inv_range(unsigned long start, unsigned long end)
 {
-       asm volatile("icache.ialls\n":::"memory");
-       sync_is();
+       icache_inv_all();
 }
+#endif
 
-void dcache_wb_range(unsigned long start, unsigned long end)
+inline void dcache_wb_line(unsigned long start)
 {
-       unsigned long i = start & ~(L1_CACHE_BYTES - 1);
-
-       for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
+       asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
        sync_is();
 }
 
-void dcache_inv_range(unsigned long start, unsigned long end)
+void dcache_wb_range(unsigned long start, unsigned long end)
 {
        unsigned long i = start & ~(L1_CACHE_BYTES - 1);
 
        for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("dcache.civa %0\n"::"r"(i):"memory");
+               asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
        sync_is();
 }
 
 void cache_wbinv_range(unsigned long start, unsigned long end)
 {
-       unsigned long i = start & ~(L1_CACHE_BYTES - 1);
-
-       for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
-       sync_is();
-
-       i = start & ~(L1_CACHE_BYTES - 1);
-       for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("icache.iva %0\n"::"r"(i):"memory");
-       sync_is();
+       dcache_wb_range(start, end);
+       icache_inv_range(start, end);
 }
 EXPORT_SYMBOL(cache_wbinv_range);
 
index 3317b77..8131291 100644 (file)
@@ -117,85 +117,29 @@ struct page *kmap_atomic_to_page(void *ptr)
        return pte_page(*pte);
 }
 
-static void __init fixrange_init(unsigned long start, unsigned long end,
-                               pgd_t *pgd_base)
+static void __init kmap_pages_init(void)
 {
-#ifdef CONFIG_HIGHMEM
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       int i, j, k;
        unsigned long vaddr;
-
-       vaddr = start;
-       i = __pgd_offset(vaddr);
-       j = __pud_offset(vaddr);
-       k = __pmd_offset(vaddr);
-       pgd = pgd_base + i;
-
-       for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-               pud = (pud_t *)pgd;
-               for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
-                       pmd = (pmd_t *)pud;
-                       for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
-                               if (pmd_none(*pmd)) {
-                                       pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
-                                       if (!pte)
-                                               panic("%s: Failed to allocate %lu bytes align=%lx\n",
-                                                     __func__, PAGE_SIZE,
-                                                     PAGE_SIZE);
-
-                                       set_pmd(pmd, __pmd(__pa(pte)));
-                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
-                               }
-                               vaddr += PMD_SIZE;
-                       }
-                       k = 0;
-               }
-               j = 0;
-       }
-#endif
-}
-
-void __init fixaddr_kmap_pages_init(void)
-{
-       unsigned long vaddr;
-       pgd_t *pgd_base;
-#ifdef CONFIG_HIGHMEM
        pgd_t *pgd;
        pmd_t *pmd;
        pud_t *pud;
        pte_t *pte;
-#endif
-       pgd_base = swapper_pg_dir;
-
-       /*
-        * Fixed mappings:
-        */
-       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       fixrange_init(vaddr, 0, pgd_base);
-
-#ifdef CONFIG_HIGHMEM
-       /*
-        * Permanent kmaps:
-        */
+
        vaddr = PKMAP_BASE;
-       fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+       fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
 
        pgd = swapper_pg_dir + __pgd_offset(vaddr);
        pud = (pud_t *)pgd;
        pmd = pmd_offset(pud, vaddr);
        pte = pte_offset_kernel(pmd, vaddr);
        pkmap_page_table = pte;
-#endif
 }
 
 void __init kmap_init(void)
 {
        unsigned long vaddr;
 
-       fixaddr_kmap_pages_init();
+       kmap_pages_init();
 
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN);
 
index d4c2292..cb64d86 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/swap.h>
 #include <linux/proc_fs.h>
 #include <linux/pfn.h>
+#include <linux/initrd.h>
 
 #include <asm/setup.h>
 #include <asm/cachectl.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
+EXPORT_SYMBOL(invalid_pte_table);
 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
                                                __page_aligned_bss;
 EXPORT_SYMBOL(empty_zero_page);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static void __init setup_initrd(void)
+{
+       unsigned long size;
+
+       if (initrd_start >= initrd_end) {
+               pr_err("initrd not found or empty");
+               goto disable;
+       }
+
+       if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
+               pr_err("initrd extends beyond end of memory");
+               goto disable;
+       }
+
+       size = initrd_end - initrd_start;
+
+       if (memblock_is_region_reserved(__pa(initrd_start), size)) {
+               pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region",
+                      __pa(initrd_start), size);
+               goto disable;
+       }
+
+       memblock_reserve(__pa(initrd_start), size);
+
+       pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
+               (void *)(initrd_start), size);
+
+       initrd_below_start_ok = 1;
+
+       return;
+
+disable:
+       initrd_start = initrd_end = 0;
+
+       pr_err(" - disabling initrd\n");
+}
+#endif
+
 void __init mem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
@@ -46,6 +87,10 @@ void __init mem_init(void)
 #endif
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       setup_initrd();
+#endif
+
        memblock_free_all();
 
 #ifdef CONFIG_HIGHMEM
@@ -101,3 +146,50 @@ void __init pre_mmu_init(void)
        /* Setup page mask to 4k */
        write_mmu_pagemask(0);
 }
+
+void __init fixrange_init(unsigned long start, unsigned long end,
+                       pgd_t *pgd_base)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       int i, j, k;
+       unsigned long vaddr;
+
+       vaddr = start;
+       i = __pgd_offset(vaddr);
+       j = __pud_offset(vaddr);
+       k = __pmd_offset(vaddr);
+       pgd = pgd_base + i;
+
+       for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+               pud = (pud_t *)pgd;
+               for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+                       pmd = (pmd_t *)pud;
+                       for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+                               if (pmd_none(*pmd)) {
+                                       pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+                                       if (!pte)
+                                               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                                                     __func__, PAGE_SIZE,
+                                                     PAGE_SIZE);
+
+                                       set_pmd(pmd, __pmd(__pa(pte)));
+                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
+                               }
+                               vaddr += PMD_SIZE;
+                       }
+                       k = 0;
+               }
+               j = 0;
+       }
+}
+
+void __init fixaddr_init(void)
+{
+       unsigned long vaddr;
+
+       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+       fixrange_init(vaddr, vaddr + PMD_SIZE, swapper_pg_dir);
+}
index c4645e4..ffade2f 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/syscalls.h>
 #include <asm/page.h>
-#include <asm/cache.h>
+#include <asm/cacheflush.h>
 #include <asm/cachectl.h>
 
 SYSCALL_DEFINE3(cacheflush,
@@ -13,17 +13,14 @@ SYSCALL_DEFINE3(cacheflush,
 {
        switch (cache) {
        case ICACHE:
-               icache_inv_range((unsigned long)addr,
-                                (unsigned long)addr + bytes);
-               break;
+       case BCACHE:
+               flush_icache_mm_range(current->mm,
+                               (unsigned long)addr,
+                               (unsigned long)addr + bytes);
        case DCACHE:
                dcache_wb_range((unsigned long)addr,
                                (unsigned long)addr + bytes);
                break;
-       case BCACHE:
-               cache_wbinv_range((unsigned long)addr,
-                                 (unsigned long)addr + bytes);
-               break;
        default:
                return -EINVAL;
        }
diff --git a/arch/csky/mm/tcm.c b/arch/csky/mm/tcm.c
new file mode 100644 (file)
index 0000000..ddeb363
--- /dev/null
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/highmem.h>
+#include <linux/genalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+#if (CONFIG_ITCM_RAM_BASE == 0xffffffff)
+#error "You should define ITCM_RAM_BASE"
+#endif
+
+#ifdef CONFIG_HAVE_DTCM
+#if (CONFIG_DTCM_RAM_BASE == 0xffffffff)
+#error "You should define DTCM_RAM_BASE"
+#endif
+
+#if (CONFIG_DTCM_RAM_BASE == CONFIG_ITCM_RAM_BASE)
+#error "You should define correct DTCM_RAM_BASE"
+#endif
+#endif
+
+extern char __tcm_start, __tcm_end, __dtcm_start;
+
+static struct gen_pool *tcm_pool;
+
+static void __init tcm_mapping_init(void)
+{
+       pte_t *tcm_pte;
+       unsigned long vaddr, paddr;
+       int i;
+
+       paddr = CONFIG_ITCM_RAM_BASE;
+
+       if (pfn_valid(PFN_DOWN(CONFIG_ITCM_RAM_BASE)))
+               goto panic;
+
+#ifndef CONFIG_HAVE_DTCM
+       for (i = 0; i < TCM_NR_PAGES; i++) {
+#else
+       for (i = 0; i < CONFIG_ITCM_NR_PAGES; i++) {
+#endif
+               vaddr = __fix_to_virt(FIX_TCM - i);
+
+               tcm_pte =
+                       pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr);
+
+               set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
+
+               flush_tlb_one(vaddr);
+
+               paddr = paddr + PAGE_SIZE;
+       }
+
+#ifdef CONFIG_HAVE_DTCM
+       if (pfn_valid(PFN_DOWN(CONFIG_DTCM_RAM_BASE)))
+               goto panic;
+
+       paddr = CONFIG_DTCM_RAM_BASE;
+
+       for (i = 0; i < CONFIG_DTCM_NR_PAGES; i++) {
+               vaddr = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES - i);
+
+               tcm_pte =
+                       pte_offset_kernel((pmd_t *) pgd_offset_k(vaddr), vaddr);
+
+               set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
+
+               flush_tlb_one(vaddr);
+
+               paddr = paddr + PAGE_SIZE;
+       }
+#endif
+
+#ifndef CONFIG_HAVE_DTCM
+       memcpy((void *)__fix_to_virt(FIX_TCM),
+                               &__tcm_start, &__tcm_end - &__tcm_start);
+
+       pr_info("%s: mapping tcm va:0x%08lx to pa:0x%08x\n",
+                       __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
+
+       pr_info("%s: __tcm_start va:0x%08lx size:%d\n",
+                       __func__, (unsigned long)&__tcm_start, &__tcm_end - &__tcm_start);
+#else
+       memcpy((void *)__fix_to_virt(FIX_TCM),
+                               &__tcm_start, &__dtcm_start - &__tcm_start);
+
+       pr_info("%s: mapping itcm va:0x%08lx to pa:0x%08x\n",
+                       __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
+
+       pr_info("%s: __itcm_start va:0x%08lx size:%d\n",
+                       __func__, (unsigned long)&__tcm_start, &__dtcm_start - &__tcm_start);
+
+       memcpy((void *)__fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
+                               &__dtcm_start, &__tcm_end - &__dtcm_start);
+
+       pr_info("%s: mapping dtcm va:0x%08lx to pa:0x%08x\n",
+                       __func__, __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
+                                               CONFIG_DTCM_RAM_BASE);
+
+       pr_info("%s: __dtcm_start va:0x%08lx size:%d\n",
+                       __func__, (unsigned long)&__dtcm_start, &__tcm_end - &__dtcm_start);
+
+#endif
+       return;
+panic:
+       panic("TCM init error");
+}
+
+void *tcm_alloc(size_t len)
+{
+       unsigned long vaddr;
+
+       if (!tcm_pool)
+               return NULL;
+
+       vaddr = gen_pool_alloc(tcm_pool, len);
+       if (!vaddr)
+               return NULL;
+
+       return (void *) vaddr;
+}
+EXPORT_SYMBOL(tcm_alloc);
+
+void tcm_free(void *addr, size_t len)
+{
+       gen_pool_free(tcm_pool, (unsigned long) addr, len);
+}
+EXPORT_SYMBOL(tcm_free);
+
+static int __init tcm_setup_pool(void)
+{
+#ifndef CONFIG_HAVE_DTCM
+       u32 pool_size = (u32) (TCM_NR_PAGES * PAGE_SIZE)
+                               - (u32) (&__tcm_end - &__tcm_start);
+
+       u32 tcm_pool_start = __fix_to_virt(FIX_TCM)
+                               + (u32) (&__tcm_end - &__tcm_start);
+#else
+       u32 pool_size = (u32) (CONFIG_DTCM_NR_PAGES * PAGE_SIZE)
+                               - (u32) (&__tcm_end - &__dtcm_start);
+
+       u32 tcm_pool_start = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES)
+                               + (u32) (&__tcm_end - &__dtcm_start);
+#endif
+       int ret;
+
+       tcm_pool = gen_pool_create(2, -1);
+
+       ret = gen_pool_add(tcm_pool, tcm_pool_start, pool_size, -1);
+       if (ret) {
+               pr_err("%s: gen_pool add failed!\n", __func__);
+               return ret;
+       }
+
+       pr_info("%s: Added %d bytes @ 0x%08x to memory pool\n",
+               __func__, pool_size, tcm_pool_start);
+
+       return 0;
+}
+
+static int __init tcm_init(void)
+{
+       tcm_mapping_init();
+
+       tcm_setup_pool();
+
+       return 0;
+}
+arch_initcall(tcm_init);
index 5accda2..a3301ba 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4740-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 
 / {
        #address-cells = <1>;
                #clock-cells = <1>;
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4740-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4740_CLK_RTC>;
-               clock-names = "rtc";
-       };
-
        tcu: timer@10002000 {
                compatible = "ingenic,jz4740-tcu", "simple-mfd";
                reg = <0x10002000 0x1000>;
 
                interrupt-parent = <&intc>;
                interrupts = <23 22 21>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4740-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
index f928329..bb89653 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4780-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/dma/jz4780-dma.h>
 
 / {
 
                interrupt-parent = <&intc>;
                interrupts = <27 26 25>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4780-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
                status = "disabled";
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4780-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4780_CLK_RTCLK>;
-               clock-names = "rtc";
-       };
-
        nemc: nemc@13410000 {
                compatible = "ingenic,jz4780-nemc";
                reg = <0x13410000 0x10000>;
index 4994c69..147f7d5 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/clock/x1000-cgu.h>
 #include <dt-bindings/dma/x1000-dma.h>
 
@@ -72,7 +73,7 @@
                        compatible = "ingenic,x1000-watchdog", "ingenic,jz4780-watchdog";
                        reg = <0x0 0x10>;
 
-                       clocks = <&cgu X1000_CLK_RTCLK>;
+                       clocks = <&tcu TCU_CLK_WDT>;
                        clock-names = "wdt";
                };
        };
        i2c0: i2c-controller@10050000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10050000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c1: i2c-controller@10051000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10051000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c2: i2c-controller@10052000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10052000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
index 7c6a109..aabd097 100644 (file)
  * effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use
  * optimized memory barrier primitives."). Here we specify that the affected
  * sync instructions should be emitted twice.
+ * Note that this expression is evaluated by the assembler (not the compiler),
+ * and that the assembler evaluates '==' as 0 or -1, not 0 or 1.
  */
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-# define __SYNC_rpt(type)      (1 + (type == __SYNC_wmb))
+# define __SYNC_rpt(type)      (1 - (type == __SYNC_wmb))
 #else
 # define __SYNC_rpt(type)      1
 #endif
index 6176b9a..d0d832a 100644 (file)
@@ -134,7 +134,7 @@ void release_vpe(struct vpe *v)
 {
        list_del(&v->list);
        if (v->load_addr)
-               release_progmem(v);
+               release_progmem(v->load_addr);
        kfree(v);
 }
 
index aa89a41..d7fe840 100644 (file)
@@ -33,6 +33,7 @@ endif
 cflags-vdso := $(ccflags-vdso) \
        $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
        -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+       -mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \
        -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
        $(call cc-option, -fno-asynchronous-unwind-tables) \
        $(call cc-option, -fno-stack-protector)
@@ -51,6 +52,8 @@ endif
 
 CFLAGS_REMOVE_vgettimeofday.o = -pg
 
+DISABLE_VDSO := n
+
 #
 # For the pre-R6 code in arch/mips/vdso/vdso.h for locating
 # the base address of VDSO, the linker will emit a R_MIPS_PC32
@@ -64,11 +67,24 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
 ifndef CONFIG_CPU_MIPSR6
   ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
     $(warning MIPS VDSO requires binutils >= 2.25)
-    obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
-    ccflags-vdso += -DDISABLE_MIPS_VDSO
+    DISABLE_VDSO := y
   endif
 endif
 
+#
+# GCC (at least up to version 9.2) appears to emit function calls that make use
+# of the GOT when targeting microMIPS, which we can't use in the VDSO due to
+# the lack of relocations. As such, we disable the VDSO for microMIPS builds.
+#
+ifdef CONFIG_CPU_MICROMIPS
+  DISABLE_VDSO := y
+endif
+
+ifeq ($(DISABLE_VDSO),y)
+  obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
+  ccflags-vdso += -DDISABLE_MIPS_VDSO
+endif
+
 # VDSO linker flags.
 VDSO_LDFLAGS := \
        -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
@@ -81,12 +97,18 @@ GCOV_PROFILE := n
 UBSAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
+# Check that we don't have PIC 'jalr t9' calls left
+quiet_cmd_vdso_mips_check = VDSOCHK $@
+      cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
+                      then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
+                            rm -f $@; /bin/false); fi
+
 #
 # Shared build commands.
 #
 
 quiet_cmd_vdsold_and_vdso_check = LD      $@
-      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
+      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check); $(cmd_vdso_mips_check)
 
 quiet_cmd_vdsold = VDSO    $@
       cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
index 8633208..080a0bf 100644 (file)
@@ -295,8 +295,13 @@ static inline bool pfn_valid(unsigned long pfn)
 /*
  * Some number of bits at the level of the page table that points to
  * a hugepte are used to encode the size.  This masks those bits.
+ * On 8xx, HW assistance requires 4k alignment for the hugepte.
  */
+#ifdef CONFIG_PPC_8xx
+#define HUGEPD_SHIFT_MASK     0xfff
+#else
 #define HUGEPD_SHIFT_MASK     0x3f
+#endif
 
 #ifndef __ASSEMBLY__
 
index 8387698..eedcbfb 100644 (file)
@@ -168,6 +168,10 @@ struct thread_struct {
        unsigned long   srr1;
        unsigned long   dar;
        unsigned long   dsisr;
+#ifdef CONFIG_PPC_BOOK3S_32
+       unsigned long   r0, r3, r4, r5, r6, r8, r9, r11;
+       unsigned long   lr, ctr;
+#endif
 #endif
        /* Debug Registers */
        struct debug_reg debug;
index c25e562..fcf24a3 100644 (file)
@@ -132,6 +132,18 @@ int main(void)
        OFFSET(SRR1, thread_struct, srr1);
        OFFSET(DAR, thread_struct, dar);
        OFFSET(DSISR, thread_struct, dsisr);
+#ifdef CONFIG_PPC_BOOK3S_32
+       OFFSET(THR0, thread_struct, r0);
+       OFFSET(THR3, thread_struct, r3);
+       OFFSET(THR4, thread_struct, r4);
+       OFFSET(THR5, thread_struct, r5);
+       OFFSET(THR6, thread_struct, r6);
+       OFFSET(THR8, thread_struct, r8);
+       OFFSET(THR9, thread_struct, r9);
+       OFFSET(THR11, thread_struct, r11);
+       OFFSET(THLR, thread_struct, lr);
+       OFFSET(THCTR, thread_struct, ctr);
+#endif
 #endif
 #ifdef CONFIG_SPE
        OFFSET(THREAD_EVR0, thread_struct, evr[0]);
index a1eaffe..7b048ce 100644 (file)
@@ -1184,6 +1184,17 @@ void eeh_handle_special_event(void)
                        eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
                        eeh_handle_normal_event(pe);
                } else {
+                       eeh_for_each_pe(pe, tmp_pe)
+                               eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
+                                       edev->mode &= ~EEH_DEV_NO_HANDLER;
+
+                       /* Notify all devices to be down */
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
+                       eeh_set_channel_state(pe, pci_channel_io_perm_failure);
+                       eeh_pe_report(
+                               "error_detected(permanent failure)", pe,
+                               eeh_report_failure, NULL);
+
                        pci_lock_rescan_remove();
                        list_for_each_entry(hose, &hose_list, list_node) {
                                phb_pe = eeh_phb_pe_get(hose);
@@ -1192,16 +1203,6 @@ void eeh_handle_special_event(void)
                                    (phb_pe->state & EEH_PE_RECOVERING))
                                        continue;
 
-                               eeh_for_each_pe(pe, tmp_pe)
-                                       eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
-                                               edev->mode &= ~EEH_DEV_NO_HANDLER;
-
-                               /* Notify all devices to be down */
-                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
-                               eeh_set_channel_state(pe, pci_channel_io_perm_failure);
-                               eeh_pe_report(
-                                       "error_detected(permanent failure)", pe,
-                                       eeh_report_failure, NULL);
                                bus = eeh_pe_bus_get(phb_pe);
                                if (!bus) {
                                        pr_err("%s: Cannot find PCI bus for "
index 0713daa..16af0d8 100644 (file)
@@ -783,7 +783,7 @@ fast_exception_return:
 1:     lis     r3,exc_exit_restart_end@ha
        addi    r3,r3,exc_exit_restart_end@l
        cmplw   r12,r3
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        bge     2b
 #else
        bge     3f
@@ -791,7 +791,7 @@ fast_exception_return:
        lis     r4,exc_exit_restart@ha
        addi    r4,r4,exc_exit_restart@l
        cmplw   r12,r4
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        blt     2b
 #else
        blt     3f
@@ -1354,12 +1354,17 @@ _GLOBAL(enter_rtas)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
        RFI
-1:     tophys(r9,r1)
+1:     tophys_novmstack r9, r1
+#ifdef CONFIG_VMAP_STACK
+       li      r0, MSR_KERNEL & ~MSR_IR        /* can take DTLB miss */
+       mtmsr   r0
+       isync
+#endif
        lwz     r8,INT_FRAME_SIZE+4(r9) /* get return address */
        lwz     r9,8(r9)        /* original msr value */
        addi    r1,r1,INT_FRAME_SIZE
        li      r0,0
-       tophys(r7, r2)
+       tophys_novmstack r7, r2
        stw     r0, THREAD + RTAS_SP(r7)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
index 0493fca..97c8879 100644 (file)
@@ -290,17 +290,55 @@ MachineCheck:
 7:     EXCEPTION_PROLOG_2
        addi    r3,r1,STACK_FRAME_OVERHEAD
 #ifdef CONFIG_PPC_CHRP
-       bne     cr1,1f
+#ifdef CONFIG_VMAP_STACK
+       mfspr   r4, SPRN_SPRG_THREAD
+       tovirt(r4, r4)
+       lwz     r4, RTAS_SP(r4)
+       cmpwi   cr1, r4, 0
 #endif
-       EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1:     b       machine_check_in_rtas
+       beq     cr1, machine_check_tramp
+       b       machine_check_in_rtas
+#else
+       b       machine_check_tramp
 #endif
 
 /* Data access exception. */
        . = 0x300
        DO_KVM  0x300
 DataAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mfspr   r10, SPRN_SPRG_THREAD
+BEGIN_MMU_FTR_SECTION
+       stw     r11, THR11(r10)
+       mfspr   r10, SPRN_DSISR
+       mfcr    r11
+#ifdef CONFIG_PPC_KUAP
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
+#else
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
+#endif
+       mfspr   r10, SPRN_SPRG_THREAD
+       beq     hash_page_dsi
+.Lhash_page_dsi_cont:
+       mtcr    r11
+       lwz     r11, THR11(r10)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r11, SPRN_DAR
+       stw     r11, DAR(r10)
+       mfspr   r11, SPRN_DSISR
+       stw     r11, DSISR(r10)
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       b       handle_page_fault_tramp_1
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG handle_dar_dsisr=1
        get_and_save_dar_dsisr_on_stack r4, r5, r11
 BEGIN_MMU_FTR_SECTION
@@ -316,11 +354,32 @@ BEGIN_MMU_FTR_SECTION
 FTR_SECTION_ELSE
        b       handle_page_fault_tramp_2
 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 
 /* Instruction access exception. */
        . = 0x400
        DO_KVM  0x400
 InstructionAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r10, SPRN_SPRG_THREAD
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+BEGIN_MMU_FTR_SECTION
+       andis.  r11, r11, SRR1_ISI_NOPT@h       /* no pte found? */
+       bne     hash_page_isi
+.Lhash_page_isi_cont:
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       EXCEPTION_PROLOG_2
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG
        andis.  r0,r9,SRR1_ISI_NOPT@h   /* no pte found? */
        beq     1f                      /* if so, try to put a PTE */
@@ -329,6 +388,7 @@ InstructionAccess:
 BEGIN_MMU_FTR_SECTION
        bl      hash_page
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 1:     mr      r4,r12
        andis.  r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
        stw     r4, _DAR(r11)
@@ -344,7 +404,7 @@ Alignment:
        EXCEPTION_PROLOG handle_dar_dsisr=1
        save_dar_dsisr_on_stack r4, r5, r11
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_STD(0x600, alignment_exception)
+       b       alignment_exception_tramp
 
 /* Program check exception */
        EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
@@ -645,15 +705,100 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 
        . = 0x3000
 
+machine_check_tramp:
+       EXC_XFER_STD(0x200, machine_check_exception)
+
+alignment_exception_tramp:
+       EXC_XFER_STD(0x600, alignment_exception)
+
 handle_page_fault_tramp_1:
+#ifdef CONFIG_VMAP_STACK
+       EXCEPTION_PROLOG_2 handle_dar_dsisr=1
+#endif
        lwz     r4, _DAR(r11)
        lwz     r5, _DSISR(r11)
        /* fall through */
 handle_page_fault_tramp_2:
        EXC_XFER_LITE(0x300, handle_page_fault)
 
+#ifdef CONFIG_VMAP_STACK
+.macro save_regs_thread                thread
+       stw     r0, THR0(\thread)
+       stw     r3, THR3(\thread)
+       stw     r4, THR4(\thread)
+       stw     r5, THR5(\thread)
+       stw     r6, THR6(\thread)
+       stw     r8, THR8(\thread)
+       stw     r9, THR9(\thread)
+       mflr    r0
+       stw     r0, THLR(\thread)
+       mfctr   r0
+       stw     r0, THCTR(\thread)
+.endm
+
+.macro restore_regs_thread     thread
+       lwz     r0, THLR(\thread)
+       mtlr    r0
+       lwz     r0, THCTR(\thread)
+       mtctr   r0
+       lwz     r0, THR0(\thread)
+       lwz     r3, THR3(\thread)
+       lwz     r4, THR4(\thread)
+       lwz     r5, THR5(\thread)
+       lwz     r6, THR6(\thread)
+       lwz     r8, THR8(\thread)
+       lwz     r9, THR9(\thread)
+.endm
+
+hash_page_dsi:
+       save_regs_thread        r10
+       mfdsisr r3
+       mfdar   r4
+       mfsrr0  r5
+       mfsrr1  r9
+       rlwinm  r3, r3, 32 - 15, _PAGE_RW       /* DSISR_STORE -> _PAGE_RW */
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       b       .Lhash_page_dsi_cont
+
+hash_page_isi:
+       mr      r11, r10
+       mfspr   r10, SPRN_SPRG_THREAD
+       save_regs_thread        r10
+       li      r3, 0
+       lwz     r4, SRR0(r10)
+       lwz     r9, SRR1(r10)
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       mr      r10, r11
+       b       .Lhash_page_isi_cont
+
+       .globl fast_hash_page_return
+fast_hash_page_return:
+       andis.  r10, r9, SRR1_ISI_NOPT@h        /* Set on ISI, cleared on DSI */
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       bne     1f
+
+       /* DSI */
+       mtcr    r11
+       lwz     r11, THR11(r10)
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
+1:     /* ISI */
+       mtcr    r11
+       mfspr   r11, SPRN_SPRG_SCRATCH1
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
 stack_overflow:
        vmap_stack_overflow_exception
+#endif
 
 AltiVecUnavailable:
        EXCEPTION_PROLOG
index a6a5fbb..9db162f 100644 (file)
 .endm
 
 .macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mtcr    r10
+FTR_SECTION_ELSE
+       stw     r10, _CCR(r11)
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#else
        stw     r10,_CCR(r11)           /* save registers */
+#endif
+       mfspr   r10, SPRN_SPRG_SCRATCH0
        stw     r12,GPR12(r11)
        stw     r9,GPR9(r11)
-       mfspr   r10,SPRN_SPRG_SCRATCH0
        stw     r10,GPR10(r11)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mfcr    r10
+       stw     r10, _CCR(r11)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        mfspr   r12,SPRN_SPRG_SCRATCH1
        stw     r12,GPR11(r11)
        mflr    r10
        stw     r10, _DSISR(r11)
        .endif
        lwz     r9, SRR1(r12)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       andi.   r10, r9, MSR_PR
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        lwz     r12, SRR0(r12)
 #else
        mfspr   r12,SPRN_SRR0
index 9922306..073a651 100644 (file)
@@ -256,7 +256,7 @@ InstructionTLBMiss:
         * set.  All other Linux PTE bits control the behavior
         * of the MMU.
         */
-       rlwimi  r10, r10, 0, 0x0f00     /* Clear bits 20-23 */
+       rlwinm  r10, r10, 0, ~0x0f00    /* Clear bits 20-23 */
        rlwimi  r10, r10, 4, 0x0400     /* Copy _PAGE_EXEC into bit 21 */
        ori     r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
        mtspr   SPRN_MI_RPN, r10        /* Update TLB entry */
index 0ffdd18..433d97b 100644 (file)
@@ -166,7 +166,11 @@ BEGIN_FTR_SECTION
        mfspr   r9,SPRN_HID0
        andis.  r9,r9,HID0_NAP@h
        beq     1f
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_msscr0@ha
+#else
        addis   r9,r11,(nap_save_msscr0-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_msscr0@l(r9)
        mtspr   SPRN_MSSCR0, r9
        sync
@@ -174,7 +178,11 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
 BEGIN_FTR_SECTION
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_hid1@ha
+#else
        addis   r9,r11,(nap_save_hid1-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_hid1@l(r9)
        mtspr   SPRN_HID1, r9
 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
index e6c30ce..d215f95 100644 (file)
@@ -200,14 +200,27 @@ unsigned long get_tm_stackpointer(struct task_struct *tsk)
         * normal/non-checkpointed stack pointer.
         */
 
+       unsigned long ret = tsk->thread.regs->gpr[1];
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        BUG_ON(tsk != current);
 
        if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+               preempt_disable();
                tm_reclaim_current(TM_CAUSE_SIGNAL);
                if (MSR_TM_TRANSACTIONAL(tsk->thread.regs->msr))
-                       return tsk->thread.ckpt_regs.gpr[1];
+                       ret = tsk->thread.ckpt_regs.gpr[1];
+
+               /*
+                * If we treclaim, we must clear the current thread's TM bits
+                * before re-enabling preemption. Otherwise we might be
+                * preempted and have the live MSR[TS] changed behind our back
+                * (tm_recheckpoint_new_task() would recheckpoint). Besides, we
+                * enter the signal handler in non-transactional state.
+                */
+               tsk->thread.regs->msr &= ~MSR_TS_MASK;
+               preempt_enable();
        }
 #endif
-       return tsk->thread.regs->gpr[1];
+       return ret;
 }
index 98600b2..1b090a7 100644 (file)
@@ -489,19 +489,11 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
  */
 static int save_tm_user_regs(struct pt_regs *regs,
                             struct mcontext __user *frame,
-                            struct mcontext __user *tm_frame, int sigret)
+                            struct mcontext __user *tm_frame, int sigret,
+                            unsigned long msr)
 {
-       unsigned long msr = regs->msr;
-
        WARN_ON(tm_suspend_disabled);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
        /* Save both sets of general registers */
        if (save_general_regs(&current->thread.ckpt_regs, frame)
            || save_general_regs(regs, tm_frame))
@@ -912,6 +904,10 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -944,13 +940,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_frame = &rt_sf->uc_transact.uc_mcontext;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (__put_user((unsigned long)&rt_sf->uc_transact,
                               &rt_sf->uc.uc_link) ||
                    __put_user((unsigned long)tm_frame,
                               &rt_sf->uc_transact.uc_regs))
                        goto badframe;
-               if (save_tm_user_regs(regs, frame, tm_frame, sigret))
+               if (save_tm_user_regs(regs, frame, tm_frame, sigret, msr))
                        goto badframe;
        }
        else
@@ -1369,6 +1365,10 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -1402,9 +1402,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_mctx = &frame->mctx_transact;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
-                                     sigret))
+                                     sigret, msr))
                        goto badframe;
        }
        else
index 1175155..84ed2e7 100644 (file)
@@ -192,7 +192,8 @@ static long setup_sigcontext(struct sigcontext __user *sc,
 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
                                 struct sigcontext __user *tm_sc,
                                 struct task_struct *tsk,
-                                int signr, sigset_t *set, unsigned long handler)
+                                int signr, sigset_t *set, unsigned long handler,
+                                unsigned long msr)
 {
        /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
         * process never used altivec yet (MSR_VEC is zero in pt_regs of
@@ -207,12 +208,11 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
        elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
 #endif
        struct pt_regs *regs = tsk->thread.regs;
-       unsigned long msr = tsk->thread.regs->msr;
        long err = 0;
 
        BUG_ON(tsk != current);
 
-       BUG_ON(!MSR_TM_ACTIVE(regs->msr));
+       BUG_ON(!MSR_TM_ACTIVE(msr));
 
        WARN_ON(tm_suspend_disabled);
 
@@ -222,13 +222,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
         */
        msr |= tsk->thread.ckpt_regs.msr & (MSR_FP | MSR_VEC | MSR_VSX);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
 #ifdef CONFIG_ALTIVEC
        err |= __put_user(v_regs, &sc->v_regs);
        err |= __put_user(tm_v_regs, &tm_sc->v_regs);
@@ -824,6 +817,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        unsigned long newsp = 0;
        long err = 0;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -841,7 +838,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                /* The ucontext_t passed to userland points to the second
                 * ucontext_t (for transactional state) with its uc_link ptr.
                 */
@@ -849,7 +846,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
                err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
                                            &frame->uc_transact.uc_mcontext,
                                            tsk, ksig->sig, NULL,
-                                           (unsigned long)ksig->ka.sa.sa_handler);
+                                           (unsigned long)ksig->ka.sa.sa_handler,
+                                           msr);
        } else
 #endif
        {
index c11b0a0..2015c4f 100644 (file)
 #include <asm/feature-fixups.h>
 #include <asm/code-patching-asm.h>
 
-#ifdef CONFIG_VMAP_STACK
-#define ADDR_OFFSET    0
-#else
-#define ADDR_OFFSET    PAGE_OFFSET
-#endif
-
 #ifdef CONFIG_SMP
        .section .bss
        .align  2
@@ -53,8 +47,8 @@ mmu_hash_lock:
        .text
 _GLOBAL(hash_page)
 #ifdef CONFIG_SMP
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@h
-       ori     r8, r8, (mmu_hash_lock - ADDR_OFFSET)@l
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@h
+       ori     r8, r8, (mmu_hash_lock - PAGE_OFFSET)@l
        lis     r0,0x0fff
        b       10f
 11:    lwz     r6,0(r8)
@@ -72,12 +66,9 @@ _GLOBAL(hash_page)
        cmplw   0,r4,r0
        ori     r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
        mfspr   r5, SPRN_SPRG_PGDIR     /* phys page-table root */
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r5, r5)
-#endif
        blt+    112f                    /* assume user more likely */
-       lis     r5, (swapper_pg_dir - ADDR_OFFSET)@ha   /* if kernel address, use */
-       addi    r5 ,r5 ,(swapper_pg_dir - ADDR_OFFSET)@l        /* kernel page table */
+       lis     r5, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
+       addi    r5 ,r5 ,(swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
        rlwimi  r3,r9,32-12,29,29       /* MSR_PR -> _PAGE_USER */
 112:
 #ifndef CONFIG_PTE_64BIT
@@ -89,9 +80,6 @@ _GLOBAL(hash_page)
        lwzx    r8,r8,r5                /* Get L1 entry */
        rlwinm. r8,r8,0,0,20            /* extract pt base address */
 #endif
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r8, r8)
-#endif
 #ifdef CONFIG_SMP
        beq-    hash_page_out           /* return if no mapping */
 #else
@@ -143,30 +131,36 @@ retry:
        bne-    retry                   /* retry if someone got there first */
 
        mfsrin  r3,r4                   /* get segment reg for segment */
+#ifndef CONFIG_VMAP_STACK
        mfctr   r0
        stw     r0,_CTR(r11)
+#endif
        bl      create_hpte             /* add the hash table entry */
 
 #ifdef CONFIG_SMP
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
 #endif
 
+#ifdef CONFIG_VMAP_STACK
+       b       fast_hash_page_return
+#else
        /* Return from the exception */
        lwz     r5,_CTR(r11)
        mtctr   r5
        lwz     r0,GPR0(r11)
        lwz     r8,GPR8(r11)
        b       fast_exception_return
+#endif
 
 #ifdef CONFIG_SMP
 hash_page_out:
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
        blr
 #endif /* CONFIG_SMP */
 
@@ -341,7 +335,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        patch_site      1f, patch__hash_page_A1
        patch_site      2f, patch__hash_page_A2
        /* Get the address of the primary PTE group in the hash table (r3) */
-0:     lis     r0, (Hash_base - ADDR_OFFSET)@h /* base address of hash table */
+0:     lis     r0, (Hash_base - PAGE_OFFSET)@h /* base address of hash table */
 1:     rlwimi  r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
 2:     rlwinm  r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
        xor     r3,r3,r0                /* make primary hash */
@@ -355,10 +349,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    10f                     /* no PTE: go look for an empty slot */
        tlbie   r4
 
-       lis     r4, (htab_hash_searches - ADDR_OFFSET)@ha
-       lwz     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       lis     r4, (htab_hash_searches - PAGE_OFFSET)@ha
+       lwz     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1                 /* count how many searches we do */
-       stw     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       stw     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
 
        /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
        mtctr   r0
@@ -390,10 +384,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    found_empty
 
        /* update counter of times that the primary PTEG is full */
-       lis     r4, (primary_pteg_full - ADDR_OFFSET)@ha
-       lwz     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       lis     r4, (primary_pteg_full - PAGE_OFFSET)@ha
+       lwz     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1
-       stw     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       stw     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
 
        patch_site      0f, patch__hash_page_C
        /* Search the secondary PTEG for an empty slot */
@@ -427,8 +421,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
         * lockup here but that shouldn't happen
         */
 
-1:     lis     r4, (next_slot - ADDR_OFFSET)@ha        /* get next evict slot */
-       lwz     r6, (next_slot - ADDR_OFFSET)@l(r4)
+1:     lis     r4, (next_slot - PAGE_OFFSET)@ha        /* get next evict slot */
+       lwz     r6, (next_slot - PAGE_OFFSET)@l(r4)
        addi    r6,r6,HPTE_SIZE                 /* search for candidate */
        andi.   r6,r6,7*HPTE_SIZE
        stw     r6,next_slot@l(r4)
index 0a1c65a..f888cbb 100644 (file)
@@ -413,7 +413,7 @@ void __init MMU_init_hw(void)
 void __init MMU_init_hw_patch(void)
 {
        unsigned int hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
-       unsigned int hash;
+       unsigned int hash = (unsigned int)Hash - PAGE_OFFSET;
 
        if (ppc_md.progress)
                ppc_md.progress("hash:patch", 0x345);
@@ -425,11 +425,6 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:create_hpte
         */
-       if (IS_ENABLED(CONFIG_VMAP_STACK))
-               hash = (unsigned int)Hash;
-       else
-               hash = (unsigned int)Hash - PAGE_OFFSET;
-
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__hash_page_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__hash_page_A2, 0x7c0, hash_mb2 << 6);
@@ -439,8 +434,7 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:flush_hash_page
         */
-       modify_instruction_site(&patch__flush_hash_A0, 0xffff,
-                               ((unsigned int)Hash - PAGE_OFFSET) >> 16);
+       modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__flush_hash_A2, 0x7c0, hash_mb2 << 6);
        modify_instruction_site(&patch__flush_hash_B, 0xffff, hmask);
index 73d4873..33b3461 100644 (file)
@@ -53,20 +53,24 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (pshift >= pdshift) {
                cachep = PGT_CACHE(PTE_T_ORDER);
                num_hugepd = 1 << (pshift - pdshift);
+               new = NULL;
        } else if (IS_ENABLED(CONFIG_PPC_8xx)) {
-               cachep = PGT_CACHE(PTE_INDEX_SIZE);
+               cachep = NULL;
                num_hugepd = 1;
+               new = pte_alloc_one(mm);
        } else {
                cachep = PGT_CACHE(pdshift - pshift);
                num_hugepd = 1;
+               new = NULL;
        }
 
-       if (!cachep) {
+       if (!cachep && !new) {
                WARN_ONCE(1, "No page table cache created for hugetlb tables");
                return -ENOMEM;
        }
 
-       new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
+       if (cachep)
+               new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -97,7 +101,10 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (i < num_hugepd) {
                for (i = i - 1 ; i >= 0; i--, hpdp--)
                        *hpdp = __hugepd(0);
-               kmem_cache_free(cachep, new);
+               if (cachep)
+                       kmem_cache_free(cachep, new);
+               else
+                       pte_free(mm, new);
        } else {
                kmemleak_ignore(new);
        }
@@ -324,8 +331,7 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        if (shift >= pdshift)
                hugepd_free(tlb, hugepte);
        else if (IS_ENABLED(CONFIG_PPC_8xx))
-               pgtable_free_tlb(tlb, hugepte,
-                                get_hugepd_cache_index(PTE_INDEX_SIZE));
+               pgtable_free_tlb(tlb, hugepte, 0);
        else
                pgtable_free_tlb(tlb, hugepte,
                                 get_hugepd_cache_index(pdshift - shift));
@@ -639,12 +645,13 @@ static int __init hugetlbpage_init(void)
                 * if we have pdshift and shift value same, we don't
                 * use pgt cache for hugepd.
                 */
-               if (pdshift > shift && IS_ENABLED(CONFIG_PPC_8xx))
-                       pgtable_cache_add(PTE_INDEX_SIZE);
-               else if (pdshift > shift)
-                       pgtable_cache_add(pdshift - shift);
-               else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) || IS_ENABLED(CONFIG_PPC_8xx))
+               if (pdshift > shift) {
+                       if (!IS_ENABLED(CONFIG_PPC_8xx))
+                               pgtable_cache_add(pdshift - shift);
+               } else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) ||
+                          IS_ENABLED(CONFIG_PPC_8xx)) {
                        pgtable_cache_add(PTE_T_ORDER);
+               }
 
                configured = true;
        }
index 16dd95b..db5664d 100644 (file)
@@ -185,8 +185,7 @@ u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
 
 static void __init kasan_early_hash_table(void)
 {
-       unsigned int hash = IS_ENABLED(CONFIG_VMAP_STACK) ? (unsigned int)early_hash :
-                                                           __pa(early_hash);
+       unsigned int hash = __pa(early_hash);
 
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
index e8c84d2..0ec9640 100644 (file)
@@ -3435,6 +3435,11 @@ getstring(char *s, int size)
        int c;
 
        c = skipbl();
+       if (c == '\n') {
+               *s = 0;
+               return;
+       }
+
        do {
                if( size > 1 ){
                        *s++ = c;
index 8dab0bb..8a45a37 100644 (file)
@@ -1,2 +1,4 @@
 Image
 Image.gz
+loader
+loader.lds
index 435b655..8e18d2c 100644 (file)
 #define EXC_LOAD_PAGE_FAULT    13
 #define EXC_STORE_PAGE_FAULT   15
 
+/* PMP configuration */
+#define PMP_R                  0x01
+#define PMP_W                  0x02
+#define PMP_X                  0x04
+#define PMP_A                  0x18
+#define PMP_A_TOR              0x08
+#define PMP_A_NA4              0x10
+#define PMP_A_NAPOT            0x18
+#define PMP_L                  0x80
+
 /* symbolic CSR names: */
 #define CSR_CYCLE              0xc00
 #define CSR_TIME               0xc01
 #define CSR_MCAUSE             0x342
 #define CSR_MTVAL              0x343
 #define CSR_MIP                        0x344
+#define CSR_PMPCFG0            0x3a0
+#define CSR_PMPADDR0           0x3b0
 #define CSR_MHARTID            0xf14
 
 #ifdef CONFIG_RISCV_M_MODE
index 271860f..85f2073 100644 (file)
@@ -58,6 +58,12 @@ _start_kernel:
        /* Reset all registers except ra, a0, a1 */
        call reset_regs
 
+       /* Setup a PMP to permit access to all of memory. */
+       li a0, -1
+       csrw CSR_PMPADDR0, a0
+       li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
+       csrw CSR_PMPCFG0, a0
+
        /*
         * The hartid in a0 is expected later on, and we have no firmware
         * to hand it to us.
index f4cad51..ffb3d94 100644 (file)
@@ -156,6 +156,6 @@ void __init trap_init(void)
        csr_write(CSR_SCRATCH, 0);
        /* Set the exception vector address */
        csr_write(CSR_TVEC, &handle_exception);
-       /* Enable all interrupts */
-       csr_write(CSR_IE, -1);
+       /* Enable interrupts */
+       csr_write(CSR_IE, IE_SIE | IE_EIE);
 }
index f0cc860..ec0ca90 100644 (file)
@@ -19,18 +19,20 @@ asmlinkage void __init kasan_early_init(void)
        for (i = 0; i < PTRS_PER_PTE; ++i)
                set_pte(kasan_early_shadow_pte + i,
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       PAGE_KERNEL));
+                              PAGE_KERNEL));
 
        for (i = 0; i < PTRS_PER_PMD; ++i)
                set_pmd(kasan_early_shadow_pmd + i,
-                pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pmd(PFN_DOWN
+                               (__pa((uintptr_t) kasan_early_shadow_pte)),
+                               __pgprot(_PAGE_TABLE)));
 
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        /* init for swapper_pg_dir */
        pgd = pgd_offset_k(KASAN_SHADOW_START);
@@ -38,37 +40,43 @@ asmlinkage void __init kasan_early_init(void)
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
 }
 
 static void __init populate(void *start, void *end)
 {
-       unsigned long i;
+       unsigned long i, offset;
        unsigned long vaddr = (unsigned long)start & PAGE_MASK;
        unsigned long vend = PAGE_ALIGN((unsigned long)end);
        unsigned long n_pages = (vend - vaddr) / PAGE_SIZE;
+       unsigned long n_ptes =
+           ((n_pages + PTRS_PER_PTE) & -PTRS_PER_PTE) / PTRS_PER_PTE;
        unsigned long n_pmds =
-               (n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 :
-                                               n_pages / PTRS_PER_PTE;
+           ((n_ptes + PTRS_PER_PMD) & -PTRS_PER_PMD) / PTRS_PER_PMD;
+
+       pte_t *pte =
+           memblock_alloc(n_ptes * PTRS_PER_PTE * sizeof(pte_t), PAGE_SIZE);
+       pmd_t *pmd =
+           memblock_alloc(n_pmds * PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
        pgd_t *pgd = pgd_offset_k(vaddr);
-       pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE);
-       pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
 
        for (i = 0; i < n_pages; i++) {
                phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
-
-               set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
+               set_pte(&pte[i], pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
        }
 
-       for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD)
-               set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))),
+       for (i = 0, offset = 0; i < n_ptes; i++, offset += PTRS_PER_PTE)
+               set_pmd(&pmd[i],
+                       pfn_pmd(PFN_DOWN(__pa(&pte[offset])),
                                __pgprot(_PAGE_TABLE)));
 
-       for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE)
-               set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))),
+       for (i = 0, offset = 0; i < n_pmds; i++, offset += PTRS_PER_PMD)
+               set_pgd(&pgd[i],
+                       pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
                                __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
@@ -81,7 +89,8 @@ void __init kasan_init(void)
        unsigned long i;
 
        kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
-                       (void *)kasan_mem_to_shadow((void *)VMALLOC_END));
+                                   (void *)kasan_mem_to_shadow((void *)
+                                                               VMALLOC_END));
 
        for_each_memblock(memory, reg) {
                void *start = (void *)__va(reg->base);
@@ -90,14 +99,14 @@ void __init kasan_init(void)
                if (start >= end)
                        break;
 
-               populate(kasan_mem_to_shadow(start),
-                        kasan_mem_to_shadow(end));
+               populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end));
        };
 
        for (i = 0; i < PTRS_PER_PTE; i++)
                set_pte(&kasan_early_shadow_pte[i],
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED)));
+                              __pgprot(_PAGE_PRESENT | _PAGE_READ |
+                                       _PAGE_ACCESSED)));
 
        memset(kasan_early_shadow_page, 0, PAGE_SIZE);
        init_task.kasan_depth = 0;
index e0e3a46..8dfa2cf 100644 (file)
@@ -146,7 +146,7 @@ all: bzImage
 #KBUILD_IMAGE is necessary for packaging targets like rpm-pkg, deb-pkg...
 KBUILD_IMAGE   := $(boot)/bzImage
 
-install: vmlinux
+install:
        $(Q)$(MAKE) $(build)=$(boot) $@
 
 bzImage: vmlinux
index e2c47d3..0ff9261 100644 (file)
@@ -70,7 +70,7 @@ $(obj)/compressed/vmlinux: $(obj)/startup.a FORCE
 $(obj)/startup.a: $(OBJECTS) FORCE
        $(call if_changed,ar)
 
-install: $(CONFIGURE) $(obj)/bzImage
+install:
        sh -x  $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
              System.map "$(INSTALL_PATH)"
 
index 5d12352..5591243 100644 (file)
@@ -75,7 +75,7 @@ static unsigned long get_random(unsigned long limit)
                *(unsigned long *) prng.parm_block ^= seed;
                for (i = 0; i < 16; i++) {
                        cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block,
-                                 (char *) entropy, (char *) entropy,
+                                 (u8 *) entropy, (u8 *) entropy,
                                  sizeof(entropy));
                        memcpy(prng.parm_block, entropy, sizeof(entropy));
                }
index 2e60c80..0c86ba1 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
@@ -474,7 +475,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_EMULEX is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_GOOGLE is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -684,7 +684,6 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -748,7 +747,6 @@ CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_GDB_SCRIPTS=y
 CONFIG_FRAME_WARN=1024
 CONFIG_HEADERS_INSTALL=y
-CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
@@ -772,9 +770,9 @@ CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_DEBUG_PER_CPU_MAPS=y
 CONFIG_DEBUG_SHIRQ=y
+CONFIG_PANIC_ON_OOPS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_ON_OOPS=y
 CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
@@ -783,9 +781,20 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
+CONFIG_LATENCYTOP=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_HIST_TRIGGERS=y
+CONFIG_S390_PTDUMP=y
 CONFIG_NOTIFIER_ERROR_INJECTION=m
 CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
@@ -796,15 +805,6 @@ CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
-CONFIG_LATENCYTOP=y
-CONFIG_IRQSOFF_TRACER=y
-CONFIG_PREEMPT_TRACER=y
-CONFIG_SCHED_TRACER=y
-CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
-CONFIG_HIST_TRIGGERS=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_TEST_SORT=y
@@ -814,5 +814,3 @@ CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
index 25f7998..6b27d86 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
@@ -470,7 +471,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_EMULEX is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_GOOGLE is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -677,7 +677,6 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -739,18 +738,18 @@ CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
 CONFIG_HIST_TRIGGERS=y
+CONFIG_S390_PTDUMP=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
index 85e944f..1019efd 100644 (file)
@@ -42,7 +42,7 @@ void __storage_key_init_range(unsigned long start, unsigned long end);
 
 static inline void storage_key_init_range(unsigned long start, unsigned long end)
 {
-       if (PAGE_DEFAULT_KEY)
+       if (PAGE_DEFAULT_KEY != 0)
                __storage_key_init_range(start, end);
 }
 
index 361ef5e..aadb3d0 100644 (file)
@@ -84,7 +84,6 @@ void s390_update_cpu_mhz(void);
 void cpu_detect_mhz_feature(void);
 
 extern const struct seq_operations cpuinfo_op;
-extern int sysctl_ieee_emulation_warnings;
 extern void execve_tail(void);
 extern void __bpon(void);
 
index 71e3f01..1e3517b 100644 (file)
@@ -201,7 +201,7 @@ struct slib {
  * @scount: SBAL count
  * @sflags: whole SBAL flags
  * @length: length
- * @addr: address
+ * @addr: absolute data address
 */
 struct qdio_buffer_element {
        u8 eflags;
@@ -211,7 +211,7 @@ struct qdio_buffer_element {
        u8 scount;
        u8 sflags;
        u32 length;
-       void *addr;
+       u64 addr;
 } __attribute__ ((packed, aligned(16)));
 
 /**
@@ -227,7 +227,7 @@ struct qdio_buffer {
  * @sbal: absolute SBAL address
  */
 struct sl_element {
-       unsigned long sbal;
+       u64 sbal;
 } __attribute__ ((packed));
 
 /**
index 748456c..9557c5a 100644 (file)
@@ -29,9 +29,6 @@
 #define __PAGE_OFFSET __PAGE_OFFSET_BASE
 #include "../../mm/ident_map.c"
 
-/* Used by pgtable.h asm code to force instruction serialization. */
-unsigned long __force_order;
-
 /* Used to track our page table allocation area. */
 struct alloc_pgt_data {
        unsigned char *pgt_buf;
index 03946eb..2a8f2bd 100644 (file)
@@ -292,6 +292,14 @@ enum x86emul_mode {
 #define X86EMUL_SMM_MASK             (1 << 6)
 #define X86EMUL_SMM_INSIDE_NMI_MASK  (1 << 7)
 
+/*
+ * fastop functions are declared as taking a never-defined fastop parameter,
+ * so they can't be called from C directly.
+ */
+struct fastop;
+
+typedef void (*fastop_t)(struct fastop *);
+
 struct x86_emulate_ctxt {
        const struct x86_emulate_ops *ops;
 
@@ -324,7 +332,10 @@ struct x86_emulate_ctxt {
        struct operand src;
        struct operand src2;
        struct operand dst;
-       int (*execute)(struct x86_emulate_ctxt *ctxt);
+       union {
+               int (*execute)(struct x86_emulate_ctxt *ctxt);
+               fastop_t fop;
+       };
        int (*check_perm)(struct x86_emulate_ctxt *ctxt);
        /*
         * The following six fields are cleared together,
index 40a0c0f..98959e8 100644 (file)
@@ -1122,6 +1122,7 @@ struct kvm_x86_ops {
        int (*handle_exit)(struct kvm_vcpu *vcpu,
                enum exit_fastpath_completion exit_fastpath);
        int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+       void (*update_emulated_instruction)(struct kvm_vcpu *vcpu);
        void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
        u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
        void (*patch_hypercall)(struct kvm_vcpu *vcpu,
@@ -1146,7 +1147,7 @@ struct kvm_x86_ops {
        void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
        void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
        void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
-       void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
+       int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
        int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
        int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
        int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);
index ebe1685..d5e517d 100644 (file)
 #define MSR_K7_HWCR                    0xc0010015
 #define MSR_K7_HWCR_SMMLOCK_BIT                0
 #define MSR_K7_HWCR_SMMLOCK            BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
+#define MSR_K7_HWCR_IRPERF_EN_BIT      30
+#define MSR_K7_HWCR_IRPERF_EN          BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
 #define MSR_K7_FID_VID_CTL             0xc0010041
 #define MSR_K7_FID_VID_STATUS          0xc0010042
 
index 2a85287..8521af3 100644 (file)
@@ -72,7 +72,7 @@
 #define SECONDARY_EXEC_MODE_BASED_EPT_EXEC     VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC)
 #define SECONDARY_EXEC_PT_USE_GPA              VMCS_CONTROL_BIT(PT_USE_GPA)
 #define SECONDARY_EXEC_TSC_SCALING              VMCS_CONTROL_BIT(TSC_SCALING)
-#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE   0x04000000
+#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE   VMCS_CONTROL_BIT(USR_WAIT_PAUSE)
 
 #define PIN_BASED_EXT_INTR_MASK                 VMCS_CONTROL_BIT(INTR_EXITING)
 #define PIN_BASED_NMI_EXITING                   VMCS_CONTROL_BIT(NMI_EXITING)
index a50e4a0..9915990 100644 (file)
@@ -81,6 +81,7 @@
 #define VMX_FEATURE_MODE_BASED_EPT_EXEC        ( 2*32+ 22) /* "ept_mode_based_exec" Enable separate EPT EXEC bits for supervisor vs. user */
 #define VMX_FEATURE_PT_USE_GPA         ( 2*32+ 24) /* "" Processor Trace logs GPAs */
 #define VMX_FEATURE_TSC_SCALING                ( 2*32+ 25) /* Scale hardware TSC when read in guest */
+#define VMX_FEATURE_USR_WAIT_PAUSE     ( 2*32+ 26) /* Enable TPAUSE, UMONITOR, UMWAIT in guest */
 #define VMX_FEATURE_ENCLV_EXITING      ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */
 
 #endif /* _ASM_X86_VMXFEATURES_H */
index 503d3f4..3f3f780 100644 (file)
@@ -390,6 +390,7 @@ struct kvm_sync_regs {
 #define KVM_STATE_NESTED_GUEST_MODE    0x00000001
 #define KVM_STATE_NESTED_RUN_PENDING   0x00000002
 #define KVM_STATE_NESTED_EVMCS         0x00000004
+#define KVM_STATE_NESTED_MTF_PENDING   0x00000008
 
 #define KVM_STATE_NESTED_SMM_GUEST_MODE        0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON     0x00000002
index ac83a0f..1f875fb 100644 (file)
@@ -28,6 +28,7 @@
 
 static const int amd_erratum_383[];
 static const int amd_erratum_400[];
+static const int amd_erratum_1054[];
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
 
 /*
@@ -972,6 +973,15 @@ static void init_amd(struct cpuinfo_x86 *c)
        /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
        if (!cpu_has(c, X86_FEATURE_XENPV))
                set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+
+       /*
+        * Turn on the Instructions Retired free counter on machines not
+        * susceptible to erratum #1054 "Instructions Retired Performance
+        * Counter May Be Inaccurate".
+        */
+       if (cpu_has(c, X86_FEATURE_IRPERF) &&
+           !cpu_has_amd_erratum(c, amd_erratum_1054))
+               msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
 }
 
 #ifdef CONFIG_X86_32
@@ -1099,6 +1109,10 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
        AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
+/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
+static const int amd_erratum_1054[] =
+       AMD_OSVW_ERRATUM(0, AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
+
 
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
index b3a50d9..52de616 100644 (file)
@@ -1163,9 +1163,12 @@ static const struct sysfs_ops threshold_ops = {
        .store                  = store,
 };
 
+static void threshold_block_release(struct kobject *kobj);
+
 static struct kobj_type threshold_ktype = {
        .sysfs_ops              = &threshold_ops,
        .default_attrs          = default_attrs,
+       .release                = threshold_block_release,
 };
 
 static const char *get_name(unsigned int bank, struct threshold_block *b)
@@ -1198,8 +1201,9 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
        return buf_mcatype;
 }
 
-static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
-                                    unsigned int block, u32 address)
+static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb,
+                                    unsigned int bank, unsigned int block,
+                                    u32 address)
 {
        struct threshold_block *b = NULL;
        u32 low, high;
@@ -1243,16 +1247,12 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
 
        INIT_LIST_HEAD(&b->miscj);
 
-       if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
-               list_add(&b->miscj,
-                        &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-       } else {
-               per_cpu(threshold_banks, cpu)[bank]->blocks = b;
-       }
+       if (tb->blocks)
+               list_add(&b->miscj, &tb->blocks->miscj);
+       else
+               tb->blocks = b;
 
-       err = kobject_init_and_add(&b->kobj, &threshold_ktype,
-                                  per_cpu(threshold_banks, cpu)[bank]->kobj,
-                                  get_name(bank, b));
+       err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
        if (err)
                goto out_free;
 recurse:
@@ -1260,7 +1260,7 @@ recurse:
        if (!address)
                return 0;
 
-       err = allocate_threshold_blocks(cpu, bank, block, address);
+       err = allocate_threshold_blocks(cpu, tb, bank, block, address);
        if (err)
                goto out_free;
 
@@ -1345,8 +1345,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
                goto out_free;
        }
 
-       per_cpu(threshold_banks, cpu)[bank] = b;
-
        if (is_shared_bank(bank)) {
                refcount_set(&b->cpus, 1);
 
@@ -1357,9 +1355,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
                }
        }
 
-       err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank));
-       if (!err)
-               goto out;
+       err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank));
+       if (err)
+               goto out_free;
+
+       per_cpu(threshold_banks, cpu)[bank] = b;
+
+       return 0;
 
  out_free:
        kfree(b);
@@ -1368,8 +1370,12 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
        return err;
 }
 
-static void deallocate_threshold_block(unsigned int cpu,
-                                                unsigned int bank)
+static void threshold_block_release(struct kobject *kobj)
+{
+       kfree(to_block(kobj));
+}
+
+static void deallocate_threshold_block(unsigned int cpu, unsigned int bank)
 {
        struct threshold_block *pos = NULL;
        struct threshold_block *tmp = NULL;
@@ -1379,13 +1385,11 @@ static void deallocate_threshold_block(unsigned int cpu,
                return;
 
        list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
-               kobject_put(&pos->kobj);
                list_del(&pos->miscj);
-               kfree(pos);
+               kobject_put(&pos->kobj);
        }
 
-       kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
-       per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+       kobject_put(&head->blocks->kobj);
 }
 
 static void __threshold_remove_blocks(struct threshold_bank *b)
index ddbc619..dd19fb3 100644 (file)
 #define NR_FASTOP (ilog2(sizeof(ulong)) + 1)
 #define FASTOP_SIZE 8
 
-/*
- * fastop functions have a special calling convention:
- *
- * dst:    rax        (in/out)
- * src:    rdx        (in/out)
- * src2:   rcx        (in)
- * flags:  rflags     (in/out)
- * ex:     rsi        (in:fastop pointer, out:zero if exception)
- *
- * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
- * different operand sizes can be reached by calculation, rather than a jump
- * table (which would be bigger than the code).
- *
- * fastop functions are declared as taking a never-defined fastop parameter,
- * so they can't be called from C directly.
- */
-
-struct fastop;
-
 struct opcode {
        u64 flags : 56;
        u64 intercept : 8;
@@ -311,8 +292,19 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
 #define ON64(x)
 #endif
 
-typedef void (*fastop_t)(struct fastop *);
-
+/*
+ * fastop functions have a special calling convention:
+ *
+ * dst:    rax        (in/out)
+ * src:    rdx        (in/out)
+ * src2:   rcx        (in)
+ * flags:  rflags     (in/out)
+ * ex:     rsi        (in:fastop pointer, out:zero if exception)
+ *
+ * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
+ * different operand sizes can be reached by calculation, rather than a jump
+ * table (which would be bigger than the code).
+ */
 static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
 
 #define __FOP_FUNC(name) \
@@ -5683,7 +5675,7 @@ special_insn:
 
        if (ctxt->execute) {
                if (ctxt->d & Fastop)
-                       rc = fastop(ctxt, (fastop_t)ctxt->execute);
+                       rc = fastop(ctxt, ctxt->fop);
                else
                        rc = ctxt->execute(ctxt);
                if (rc != X86EMUL_CONTINUE)
index 79afa0b..c47d2ac 100644 (file)
@@ -417,7 +417,7 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
 
                        kvm_set_msi_irq(vcpu->kvm, entry, &irq);
 
-                       if (irq.level &&
+                       if (irq.trig_mode &&
                            kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
                                                irq.dest_id, irq.dest_mode))
                                __set_bit(irq.vector, ioapic_handled_vectors);
index afcd30d..e3099c6 100644 (file)
@@ -627,9 +627,11 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
 static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
 {
        u8 val;
-       if (pv_eoi_get_user(vcpu, &val) < 0)
+       if (pv_eoi_get_user(vcpu, &val) < 0) {
                printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n",
                           (unsigned long long)vcpu->arch.pv_eoi.msr_val);
+               return false;
+       }
        return val & 0x1;
 }
 
@@ -1046,11 +1048,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                                                       apic->regs + APIC_TMR);
                }
 
-               if (vcpu->arch.apicv_active)
-                       kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
-               else {
+               if (kvm_x86_ops->deliver_posted_interrupt(vcpu, vector)) {
                        kvm_lapic_set_irr(vector, apic);
-
                        kvm_make_request(KVM_REQ_EVENT, vcpu);
                        kvm_vcpu_kick(vcpu);
                }
index 3c6522b..ffcd96f 100644 (file)
@@ -339,7 +339,7 @@ TRACE_EVENT(
                /* These depend on page entry type, so compute them now.  */
                __field(bool, r)
                __field(bool, x)
-               __field(u8, u)
+               __field(signed char, u)
        ),
 
        TP_fast_assign(
index bef0ba3..ad3f5b1 100644 (file)
@@ -1005,33 +1005,32 @@ static void svm_cpu_uninit(int cpu)
 static int svm_cpu_init(int cpu)
 {
        struct svm_cpu_data *sd;
-       int r;
 
        sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
        if (!sd)
                return -ENOMEM;
        sd->cpu = cpu;
-       r = -ENOMEM;
        sd->save_area = alloc_page(GFP_KERNEL);
        if (!sd->save_area)
-               goto err_1;
+               goto free_cpu_data;
 
        if (svm_sev_enabled()) {
-               r = -ENOMEM;
                sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1,
                                              sizeof(void *),
                                              GFP_KERNEL);
                if (!sd->sev_vmcbs)
-                       goto err_1;
+                       goto free_save_area;
        }
 
        per_cpu(svm_data, cpu) = sd;
 
        return 0;
 
-err_1:
+free_save_area:
+       __free_page(sd->save_area);
+free_cpu_data:
        kfree(sd);
-       return r;
+       return -ENOMEM;
 
 }
 
@@ -1350,6 +1349,24 @@ static __init void svm_adjust_mmio_mask(void)
        kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK);
 }
 
+static void svm_hardware_teardown(void)
+{
+       int cpu;
+
+       if (svm_sev_enabled()) {
+               bitmap_free(sev_asid_bitmap);
+               bitmap_free(sev_reclaim_asid_bitmap);
+
+               sev_flush_asids();
+       }
+
+       for_each_possible_cpu(cpu)
+               svm_cpu_uninit(cpu);
+
+       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
+       iopm_base = 0;
+}
+
 static __init int svm_hardware_setup(void)
 {
        int cpu;
@@ -1463,29 +1480,10 @@ static __init int svm_hardware_setup(void)
        return 0;
 
 err:
-       __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
-       iopm_base = 0;
+       svm_hardware_teardown();
        return r;
 }
 
-static __exit void svm_hardware_unsetup(void)
-{
-       int cpu;
-
-       if (svm_sev_enabled()) {
-               bitmap_free(sev_asid_bitmap);
-               bitmap_free(sev_reclaim_asid_bitmap);
-
-               sev_flush_asids();
-       }
-
-       for_each_possible_cpu(cpu)
-               svm_cpu_uninit(cpu);
-
-       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
-       iopm_base = 0;
-}
-
 static void init_seg(struct vmcb_seg *seg)
 {
        seg->selector = 0;
@@ -5232,6 +5230,9 @@ static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
        struct vmcb *vmcb = svm->vmcb;
        bool activated = kvm_vcpu_apicv_active(vcpu);
 
+       if (!avic)
+               return;
+
        if (activated) {
                /**
                 * During AVIC temporary deactivation, guest could update
@@ -5255,8 +5256,11 @@ static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
        return;
 }
 
-static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
+static int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
 {
+       if (!vcpu->arch.apicv_active)
+               return -1;
+
        kvm_lapic_set_irr(vec, vcpu->arch.apic);
        smp_mb__after_atomic();
 
@@ -5268,6 +5272,8 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
                put_cpu();
        } else
                kvm_vcpu_wake_up(vcpu);
+
+       return 0;
 }
 
 static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
@@ -7378,7 +7384,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
        .hardware_setup = svm_hardware_setup,
-       .hardware_unsetup = svm_hardware_unsetup,
+       .hardware_unsetup = svm_hardware_teardown,
        .check_processor_compatibility = svm_check_processor_compat,
        .hardware_enable = svm_hardware_enable,
        .hardware_disable = svm_hardware_disable,
@@ -7433,6 +7439,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .run = svm_vcpu_run,
        .handle_exit = handle_exit,
        .skip_emulated_instruction = skip_emulated_instruction,
+       .update_emulated_instruction = NULL,
        .set_interrupt_shadow = svm_set_interrupt_shadow,
        .get_interrupt_shadow = svm_get_interrupt_shadow,
        .patch_hypercall = svm_patch_hypercall,
index 283bdb7..f486e26 100644 (file)
@@ -12,6 +12,7 @@ extern bool __read_mostly enable_ept;
 extern bool __read_mostly enable_unrestricted_guest;
 extern bool __read_mostly enable_ept_ad_bits;
 extern bool __read_mostly enable_pml;
+extern bool __read_mostly enable_apicv;
 extern int __read_mostly pt_mode;
 
 #define PT_MODE_SYSTEM         0
index 3589cd3..e920d78 100644 (file)
@@ -3161,10 +3161,10 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
  * or KVM_SET_NESTED_STATE).  Otherwise it's called from vmlaunch/vmresume.
  *
  * Returns:
- *     NVMX_ENTRY_SUCCESS: Entered VMX non-root mode
- *     NVMX_ENTRY_VMFAIL:  Consistency check VMFail
- *     NVMX_ENTRY_VMEXIT:  Consistency check VMExit
- *     NVMX_ENTRY_KVM_INTERNAL_ERROR: KVM internal error
+ *     NVMX_VMENTRY_SUCCESS: Entered VMX non-root mode
+ *     NVMX_VMENTRY_VMFAIL:  Consistency check VMFail
+ *     NVMX_VMENTRY_VMEXIT:  Consistency check VMExit
+ *     NVMX_VMENTRY_KVM_INTERNAL_ERROR: KVM internal error
  */
 enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
                                                        bool from_vmentry)
@@ -3609,8 +3609,15 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
        unsigned long exit_qual;
        bool block_nested_events =
            vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
+       bool mtf_pending = vmx->nested.mtf_pending;
        struct kvm_lapic *apic = vcpu->arch.apic;
 
+       /*
+        * Clear the MTF state. If a higher priority VM-exit is delivered first,
+        * this state is discarded.
+        */
+       vmx->nested.mtf_pending = false;
+
        if (lapic_in_kernel(vcpu) &&
                test_bit(KVM_APIC_INIT, &apic->pending_events)) {
                if (block_nested_events)
@@ -3621,8 +3628,28 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
                return 0;
        }
 
+       /*
+        * Process any exceptions that are not debug traps before MTF.
+        */
+       if (vcpu->arch.exception.pending &&
+           !vmx_pending_dbg_trap(vcpu) &&
+           nested_vmx_check_exception(vcpu, &exit_qual)) {
+               if (block_nested_events)
+                       return -EBUSY;
+               nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
+               return 0;
+       }
+
+       if (mtf_pending) {
+               if (block_nested_events)
+                       return -EBUSY;
+               nested_vmx_update_pending_dbg(vcpu);
+               nested_vmx_vmexit(vcpu, EXIT_REASON_MONITOR_TRAP_FLAG, 0, 0);
+               return 0;
+       }
+
        if (vcpu->arch.exception.pending &&
-               nested_vmx_check_exception(vcpu, &exit_qual)) {
+           nested_vmx_check_exception(vcpu, &exit_qual)) {
                if (block_nested_events)
                        return -EBUSY;
                nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
@@ -5285,24 +5312,17 @@ fail:
        return 1;
 }
 
-
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-                                      struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+                                int size)
 {
-       unsigned long exit_qualification;
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        gpa_t bitmap, last_bitmap;
-       unsigned int port;
-       int size;
        u8 b;
 
-       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
-               return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
-       port = exit_qualification >> 16;
-       size = (exit_qualification & 7) + 1;
-
        last_bitmap = (gpa_t)-1;
        b = -1;
 
@@ -5329,8 +5349,26 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        return false;
 }
 
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+                                      struct vmcs12 *vmcs12)
+{
+       unsigned long exit_qualification;
+       unsigned short port;
+       int size;
+
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+       port = exit_qualification >> 16;
+       size = (exit_qualification & 7) + 1;
+
+       return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
- * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
+ * Return 1 if we should exit from L2 to L1 to handle an MSR access,
  * rather than handle it ourselves in L0. I.e., check whether L1 expressed
  * disinterest in the current event (read or write a specific MSR) by using an
  * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
@@ -5712,6 +5750,9 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
 
                        if (vmx->nested.nested_run_pending)
                                kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
+
+                       if (vmx->nested.mtf_pending)
+                               kvm_state.flags |= KVM_STATE_NESTED_MTF_PENDING;
                }
        }
 
@@ -5892,6 +5933,9 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
        vmx->nested.nested_run_pending =
                !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
 
+       vmx->nested.mtf_pending =
+               !!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING);
+
        ret = -EINVAL;
        if (nested_cpu_has_shadow_vmcs(vmcs12) &&
            vmcs12->vmcs_link_pointer != -1ull) {
@@ -5949,8 +5993,7 @@ void nested_vmx_set_vmcs_shadowing_bitmap(void)
  * bit in the high half is on if the corresponding bit in the control field
  * may be on. See also vmx_control_verify().
  */
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-                               bool apicv)
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
 {
        /*
         * Note that as a general rule, the high half of the MSRs (bits in
@@ -5977,7 +6020,7 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
                PIN_BASED_EXT_INTR_MASK |
                PIN_BASED_NMI_EXITING |
                PIN_BASED_VIRTUAL_NMIS |
-               (apicv ? PIN_BASED_POSTED_INTR : 0);
+               (enable_apicv ? PIN_BASED_POSTED_INTR : 0);
        msrs->pinbased_ctls_high |=
                PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
                PIN_BASED_VMX_PREEMPTION_TIMER;
index fc874d4..9aeda46 100644 (file)
@@ -17,8 +17,7 @@ enum nvmx_vmentry_status {
 };
 
 void vmx_leave_nested(struct kvm_vcpu *vcpu);
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-                               bool apicv);
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps);
 void nested_vmx_hardware_unsetup(void);
 __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
 void nested_vmx_set_vmcs_shadowing_bitmap(void);
@@ -34,6 +33,8 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
 int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
                        u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
 void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu);
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+                                int size);
 
 static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
 {
@@ -175,6 +176,11 @@ static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
        return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
 }
 
+static inline int nested_cpu_has_mtf(struct vmcs12 *vmcs12)
+{
+       return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
+}
+
 static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12)
 {
        return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);
index 3be25ec..63aaf44 100644 (file)
@@ -95,7 +95,7 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
-static bool __read_mostly enable_apicv = 1;
+bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
@@ -1175,6 +1175,10 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
                                           vmx->guest_msrs[i].mask);
 
        }
+
+       if (vmx->nested.need_vmcs12_to_shadow_sync)
+               nested_sync_vmcs12_to_shadow(vcpu);
+
        if (vmx->guest_state_loaded)
                return;
 
@@ -1599,6 +1603,40 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+
+/*
+ * Recognizes a pending MTF VM-exit and records the nested state for later
+ * delivery.
+ */
+static void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       if (!is_guest_mode(vcpu))
+               return;
+
+       /*
+        * Per the SDM, MTF takes priority over debug-trap exceptions besides
+        * T-bit traps. As instruction emulation is completed (i.e. at the
+        * instruction boundary), any #DB exception pending delivery must be a
+        * debug-trap. Record the pending MTF state to be delivered in
+        * vmx_check_nested_events().
+        */
+       if (nested_cpu_has_mtf(vmcs12) &&
+           (!vcpu->arch.exception.pending ||
+            vcpu->arch.exception.nr == DB_VECTOR))
+               vmx->nested.mtf_pending = true;
+       else
+               vmx->nested.mtf_pending = false;
+}
+
+static int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       vmx_update_emulated_instruction(vcpu);
+       return skip_emulated_instruction(vcpu);
+}
+
 static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
 {
        /*
@@ -3818,24 +3856,29 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
  * 2. If target vcpu isn't running(root mode), kick it to pick up the
  * interrupt from PIR in next vmentry.
  */
-static void vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
+static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        int r;
 
        r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
        if (!r)
-               return;
+               return 0;
+
+       if (!vcpu->arch.apicv_active)
+               return -1;
 
        if (pi_test_and_set_pir(vector, &vmx->pi_desc))
-               return;
+               return 0;
 
        /* If a previous notification has sent the IPI, nothing to do.  */
        if (pi_test_and_set_on(&vmx->pi_desc))
-               return;
+               return 0;
 
        if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
                kvm_vcpu_kick(vcpu);
+
+       return 0;
 }
 
 /*
@@ -6482,8 +6525,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
                vmcs_write32(PLE_WINDOW, vmx->ple_window);
        }
 
-       if (vmx->nested.need_vmcs12_to_shadow_sync)
-               nested_sync_vmcs12_to_shadow(vcpu);
+       /*
+        * We did this in prepare_switch_to_guest, because it needs to
+        * be within srcu_read_lock.
+        */
+       WARN_ON_ONCE(vmx->nested.need_vmcs12_to_shadow_sync);
 
        if (kvm_register_is_dirty(vcpu, VCPU_REGS_RSP))
                vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
@@ -6757,8 +6803,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
 
        if (nested)
                nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
-                                          vmx_capability.ept,
-                                          kvm_vcpu_apicv_active(vcpu));
+                                          vmx_capability.ept);
        else
                memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs));
 
@@ -6839,8 +6884,7 @@ static int __init vmx_check_processor_compat(void)
        if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0)
                return -EIO;
        if (nested)
-               nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept,
-                                          enable_apicv);
+               nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept);
        if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
                printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
                                smp_processor_id());
@@ -7101,6 +7145,39 @@ static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
        to_vmx(vcpu)->req_immediate_exit = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+                                 struct x86_instruction_info *info)
+{
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       unsigned short port;
+       bool intercept;
+       int size;
+
+       if (info->intercept == x86_intercept_in ||
+           info->intercept == x86_intercept_ins) {
+               port = info->src_val;
+               size = info->dst_bytes;
+       } else {
+               port = info->dst_val;
+               size = info->src_bytes;
+       }
+
+       /*
+        * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+        * VM-exits depend on the 'unconditional IO exiting' VM-execution
+        * control.
+        *
+        * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+        */
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               intercept = nested_cpu_has(vmcs12,
+                                          CPU_BASED_UNCOND_IO_EXITING);
+       else
+               intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+       return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
                               struct x86_instruction_info *info,
                               enum x86_intercept_stage stage)
@@ -7108,19 +7185,31 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+       switch (info->intercept) {
        /*
         * RDPID causes #UD if disabled through secondary execution controls.
         * Because it is marked as EmulateOnUD, we need to intercept it here.
         */
-       if (info->intercept == x86_intercept_rdtscp &&
-           !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
-               ctxt->exception.vector = UD_VECTOR;
-               ctxt->exception.error_code_valid = false;
-               return X86EMUL_PROPAGATE_FAULT;
-       }
+       case x86_intercept_rdtscp:
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+                       ctxt->exception.vector = UD_VECTOR;
+                       ctxt->exception.error_code_valid = false;
+                       return X86EMUL_PROPAGATE_FAULT;
+               }
+               break;
+
+       case x86_intercept_in:
+       case x86_intercept_ins:
+       case x86_intercept_out:
+       case x86_intercept_outs:
+               return vmx_check_intercept_io(vcpu, info);
 
        /* TODO: check more intercepts... */
-       return X86EMUL_CONTINUE;
+       default:
+               break;
+       }
+
+       return X86EMUL_UNHANDLEABLE;
 }
 
 #ifdef CONFIG_X86_64
@@ -7702,7 +7791,7 @@ static __init int hardware_setup(void)
 
        if (nested) {
                nested_vmx_setup_ctls_msrs(&vmcs_config.nested,
-                                          vmx_capability.ept, enable_apicv);
+                                          vmx_capability.ept);
 
                r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers);
                if (r)
@@ -7786,7 +7875,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
 
        .run = vmx_vcpu_run,
        .handle_exit = vmx_handle_exit,
-       .skip_emulated_instruction = skip_emulated_instruction,
+       .skip_emulated_instruction = vmx_skip_emulated_instruction,
+       .update_emulated_instruction = vmx_update_emulated_instruction,
        .set_interrupt_shadow = vmx_set_interrupt_shadow,
        .get_interrupt_shadow = vmx_get_interrupt_shadow,
        .patch_hypercall = vmx_patch_hypercall,
index 7f42cf3..e64da06 100644 (file)
@@ -150,6 +150,9 @@ struct nested_vmx {
        /* L2 must run next, and mustn't decide to exit to L1. */
        bool nested_run_pending;
 
+       /* Pending MTF VM-exit into L1.  */
+       bool mtf_pending;
+
        struct loaded_vmcs vmcs02;
 
        /*
index fb5d64e..359fcd3 100644 (file)
@@ -6891,6 +6891,8 @@ restart:
                        kvm_rip_write(vcpu, ctxt->eip);
                        if (r && ctxt->tf)
                                r = kvm_vcpu_do_singlestep(vcpu);
+                       if (kvm_x86_ops->update_emulated_instruction)
+                               kvm_x86_ops->update_emulated_instruction(vcpu);
                        __kvm_set_rflags(vcpu, ctxt->eflags);
                }
 
index 1f756ff..7940912 100644 (file)
@@ -896,14 +896,15 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
        int ret;
+#ifdef CONFIG_X86_64
+       unsigned int which;
+       u64 base;
+#endif
 
        ret = 0;
 
        switch (msr) {
 #ifdef CONFIG_X86_64
-               unsigned which;
-               u64 base;
-
        case MSR_FS_BASE:               which = SEGBASE_FS; goto set;
        case MSR_KERNEL_GS_BASE:        which = SEGBASE_GS_USER; goto set;
        case MSR_GS_BASE:               which = SEGBASE_GS_KERNEL; goto set;
index cd3612e..8ef65c0 100644 (file)
@@ -853,14 +853,17 @@ static void reset_fdc_info(int mode)
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+       unsigned int new_fdc = fdc;
+
        if (drive >= 0 && drive < N_DRIVE) {
-               fdc = FDC(drive);
+               new_fdc = FDC(drive);
                current_drive = drive;
        }
-       if (fdc != 1 && fdc != 0) {
+       if (new_fdc >= N_FDC) {
                pr_info("bad fdc value\n");
                return;
        }
+       fdc = new_fdc;
        set_dor(fdc, ~0, 8);
 #if N_FDC > 1
        set_dor(1 - fdc, ~8, 0);
index ae79a7c..fa70415 100644 (file)
@@ -730,7 +730,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (data->has_sp) {
                input2 = input_allocate_device();
                if (!input2) {
-                       input_free_device(input2);
+                       ret = -ENOMEM;
                        goto exit;
                }
 
index 6ac8bec..d732d1d 100644 (file)
@@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                unsigned long **bit, int *max)
 {
        if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
-                       usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
+                       usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
+                       usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
                /* The fn key on Apple USB keyboards */
                set_bit(EV_REP, hi->input->evbit);
                hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
index 3f6abd1..db6da21 100644 (file)
@@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {
 struct bigben_device {
        struct hid_device *hid;
        struct hid_report *report;
+       bool removed;
        u8 led_state;         /* LED1 = 1 .. LED4 = 8 */
        u8 right_motor_on;    /* right motor off/on 0/1 */
        u8 left_motor_force;  /* left motor force 0-255 */
@@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work)
                struct bigben_device, worker);
        struct hid_field *report_field = bigben->report->field[0];
 
+       if (bigben->removed)
+               return;
+
        if (bigben->work_led) {
                bigben->work_led = false;
                report_field->value[0] = 0x01; /* 1 = led message */
@@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work)
 static int hid_bigben_play_effect(struct input_dev *dev, void *data,
                         struct ff_effect *effect)
 {
-       struct bigben_device *bigben = data;
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct bigben_device *bigben = hid_get_drvdata(hid);
        u8 right_motor_on;
        u8 left_motor_force;
 
+       if (!bigben) {
+               hid_err(hid, "no device data\n");
+               return 0;
+       }
+
        if (effect->type != FF_RUMBLE)
                return 0;
 
@@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid)
 {
        struct bigben_device *bigben = hid_get_drvdata(hid);
 
+       bigben->removed = true;
        cancel_work_sync(&bigben->worker);
-       hid_hw_close(hid);
        hid_hw_stop(hid);
 }
 
@@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid,
                return -ENOMEM;
        hid_set_drvdata(hid, bigben);
        bigben->hid = hid;
+       bigben->removed = false;
 
        error = hid_parse(hid);
        if (error) {
@@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid,
 
        INIT_WORK(&bigben->worker, bigben_worker);
 
-       error = input_ff_create_memless(hidinput->input, bigben,
+       error = input_ff_create_memless(hidinput->input, NULL,
                hid_bigben_play_effect);
        if (error)
-               return error;
+               goto error_hw_stop;
 
        name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
 
@@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid,
                        sizeof(struct led_classdev) + name_sz,
                        GFP_KERNEL
                );
-               if (!led)
-                       return -ENOMEM;
+               if (!led) {
+                       error = -ENOMEM;
+                       goto error_hw_stop;
+               }
                name = (void *)(&led[1]);
                snprintf(name, name_sz,
                        "%s:red:bigben%d",
@@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid,
                bigben->leds[n] = led;
                error = devm_led_classdev_register(&hid->dev, led);
                if (error)
-                       return error;
+                       goto error_hw_stop;
        }
 
        /* initial state: LED1 is on, no rumble effect */
@@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid,
        hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
 
        return 0;
+
+error_hw_stop:
+       hid_hw_stop(hid);
+       return error;
 }
 
 static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
index 851fe54..359616e 100644 (file)
@@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
 
        rsize = ((report->size - 1) >> 3) + 1;
 
-       if (rsize > HID_MAX_BUFFER_SIZE)
+       if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
+               rsize = HID_MAX_BUFFER_SIZE - 1;
+       else if (rsize > HID_MAX_BUFFER_SIZE)
                rsize = HID_MAX_BUFFER_SIZE;
 
        if (csize < rsize) {
index c436e12..6c55682 100644 (file)
@@ -41,8 +41,9 @@ static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
        /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
-       { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
-                        USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_SYNAPTICS,
+                    USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
index 70e1cb9..094f4f1 100644 (file)
@@ -1256,36 +1256,35 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
 {
        int status;
 
-       long charge_sts = (long)data[2];
+       long flags = (long) data[2];
 
-       *level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
-       switch (data[2] & 0xe0) {
-       case 0x00:
-               status = POWER_SUPPLY_STATUS_CHARGING;
-               break;
-       case 0x20:
-               status = POWER_SUPPLY_STATUS_FULL;
-               *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
-               break;
-       case 0x40:
+       if (flags & 0x80)
+               switch (flags & 0x07) {
+               case 0:
+                       status = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               case 1:
+                       status = POWER_SUPPLY_STATUS_FULL;
+                       *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+                       break;
+               case 2:
+                       status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+                       break;
+               default:
+                       status = POWER_SUPPLY_STATUS_UNKNOWN;
+                       break;
+               }
+       else
                status = POWER_SUPPLY_STATUS_DISCHARGING;
-               break;
-       case 0xe0:
-               status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-               break;
-       default:
-               status = POWER_SUPPLY_STATUS_UNKNOWN;
-       }
 
        *charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
-       if (test_bit(3, &charge_sts)) {
+       if (test_bit(3, &flags)) {
                *charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
        }
-       if (test_bit(4, &charge_sts)) {
+       if (test_bit(4, &flags)) {
                *charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
        }
-
-       if (test_bit(5, &charge_sts)) {
+       if (test_bit(5, &flags)) {
                *level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
        }
 
index d31ea82..a66f080 100644 (file)
@@ -342,6 +342,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                .driver_data = (void *)&sipodev_desc
        },
        {
+               .ident = "Trekstor SURFBOOK E11B",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
+       {
                .ident = "Direkt-Tek DTLAPY116-2",
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
index a970b80..4140dea 100644 (file)
@@ -932,9 +932,9 @@ void hiddev_disconnect(struct hid_device *hid)
        hiddev->exist = 0;
 
        if (hiddev->open) {
-               mutex_unlock(&hiddev->existancelock);
                hid_hw_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
+               mutex_unlock(&hiddev->existancelock);
        } else {
                mutex_unlock(&hiddev->existancelock);
                kfree(hiddev);
index 4cf2545..0db8ef4 100644 (file)
@@ -355,7 +355,9 @@ static ssize_t show_str(struct device *dev,
        struct acpi_device *acpi_dev = to_acpi_device(dev);
        struct acpi_power_meter_resource *resource = acpi_dev->driver_data;
        acpi_string val;
+       int ret;
 
+       mutex_lock(&resource->lock);
        switch (attr->index) {
        case 0:
                val = resource->model_number;
@@ -372,8 +374,9 @@ static ssize_t show_str(struct device *dev,
                val = "";
                break;
        }
-
-       return sprintf(buf, "%s\n", val);
+       ret = sprintf(buf, "%s\n", val);
+       mutex_unlock(&resource->lock);
+       return ret;
 }
 
 static ssize_t show_val(struct device *dev,
@@ -817,11 +820,12 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
 
        resource = acpi_driver_data(device);
 
-       mutex_lock(&resource->lock);
        switch (event) {
        case METER_NOTIFY_CONFIG:
+               mutex_lock(&resource->lock);
                free_capabilities(resource);
                res = read_capabilities(resource);
+               mutex_unlock(&resource->lock);
                if (res)
                        break;
 
@@ -830,15 +834,12 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
                break;
        case METER_NOTIFY_TRIP:
                sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
-               update_meter(resource);
                break;
        case METER_NOTIFY_CAP:
                sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
-               update_cap(resource);
                break;
        case METER_NOTIFY_INTERVAL:
                sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
-               update_avg_interval(resource);
                break;
        case METER_NOTIFY_CAPPING:
                sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
@@ -848,7 +849,6 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
                WARN(1, "Unexpected event %d\n", event);
                break;
        }
-       mutex_unlock(&resource->lock);
 
        acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS,
                                        dev_name(&device->dev), event, 0);
@@ -912,8 +912,8 @@ static int acpi_power_meter_remove(struct acpi_device *device)
        resource = acpi_driver_data(device);
        hwmon_device_unregister(resource->hwmon_dev);
 
-       free_capabilities(resource);
        remove_attrs(resource);
+       free_capabilities(resource);
 
        kfree(resource);
        return 0;
index 7ffadc2..5a51201 100644 (file)
@@ -1346,8 +1346,13 @@ w83627ehf_is_visible(const void *drvdata, enum hwmon_sensor_types type,
                /* channel 0.., name 1.. */
                if (!(data->have_temp & (1 << channel)))
                        return 0;
-               if (attr == hwmon_temp_input || attr == hwmon_temp_label)
+               if (attr == hwmon_temp_input)
                        return 0444;
+               if (attr == hwmon_temp_label) {
+                       if (data->temp_label)
+                               return 0444;
+                       return 0;
+               }
                if (channel == 2 && data->temp3_val_only)
                        return 0;
                if (attr == hwmon_temp_max) {
index b273e42..a1a0352 100644 (file)
@@ -2575,6 +2575,17 @@ isert_wait4logout(struct isert_conn *isert_conn)
        }
 }
 
+static void
+isert_wait4cmds(struct iscsi_conn *conn)
+{
+       isert_info("iscsi_conn %p\n", conn);
+
+       if (conn->sess) {
+               target_sess_cmd_list_set_waiting(conn->sess->se_sess);
+               target_wait_for_sess_cmds(conn->sess->se_sess);
+       }
+}
+
 /**
  * isert_put_unsol_pending_cmds() - Drop commands waiting for
  *     unsolicitate dataout
@@ -2622,6 +2633,7 @@ static void isert_wait_conn(struct iscsi_conn *conn)
 
        ib_drain_qp(isert_conn->qp);
        isert_put_unsol_pending_cmds(conn);
+       isert_wait4cmds(conn);
        isert_wait4logout(isert_conn);
 
        queue_work(isert_release_wq, &isert_conn->release_work);
index ada59df..a4d8c90 100644 (file)
@@ -1165,8 +1165,8 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl,
 static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid,
                unsigned int dword11, void *buffer, size_t buflen, u32 *result)
 {
+       union nvme_result res = { 0 };
        struct nvme_command c;
-       union nvme_result res;
        int ret;
 
        memset(&c, 0, sizeof(c));
index 797c183..a11900c 100644 (file)
@@ -715,6 +715,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        }
 
        INIT_WORK(&ctrl->ana_work, nvme_ana_work);
+       kfree(ctrl->ana_log_buf);
        ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
        if (!ctrl->ana_log_buf) {
                error = -ENOMEM;
index 9c80f9f..ace4dd9 100644 (file)
@@ -2747,6 +2747,18 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
                    (dmi_match(DMI_BOARD_NAME, "PRIME B350M-A") ||
                     dmi_match(DMI_BOARD_NAME, "PRIME Z370-A")))
                        return NVME_QUIRK_NO_APST;
+       } else if ((pdev->vendor == 0x144d && (pdev->device == 0xa801 ||
+                   pdev->device == 0xa808 || pdev->device == 0xa809)) ||
+                  (pdev->vendor == 0x1e0f && pdev->device == 0x0001)) {
+               /*
+                * Forcing to use host managed nvme power settings for
+                * lowest idle power with quick resume latency on
+                * Samsung and Toshiba SSDs based on suspend behavior
+                * on Coffee Lake board for LENOVO C640
+                */
+               if ((dmi_match(DMI_BOARD_VENDOR, "LENOVO")) &&
+                    dmi_match(DMI_BOARD_NAME, "LNVNB161216"))
+                       return NVME_QUIRK_SIMPLE_SUSPEND;
        }
 
        return 0;
@@ -3109,7 +3121,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
-       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
+       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001),
+               .driver_data = NVME_QUIRK_SINGLE_VECTOR },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005),
                .driver_data = NVME_QUIRK_SINGLE_VECTOR |
index e69682c..62f2761 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/platform_data/wilco-ec.h>
 #include <linux/string.h>
-#include <linux/unaligned/le_memmove.h>
+#include <asm/unaligned.h>
 
 /* Operation code; what the EC should do with the property */
 enum ec_property_op {
index da642e8..4dd2eb6 100644 (file)
@@ -303,8 +303,10 @@ static void *
 cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
        struct ccwdev_iter *iter;
+       loff_t p = *offset;
 
-       if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+       (*offset)++;
+       if (p >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
                return NULL;
        iter = it;
        if (iter->devno == __MAX_SUBCHANNEL) {
@@ -314,7 +316,6 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
                        return NULL;
        } else
                iter->devno++;
-       (*offset)++;
        return iter;
 }
 
index 51038ec..dfcbe54 100644 (file)
@@ -135,7 +135,7 @@ static ssize_t chp_measurement_chars_read(struct file *filp,
        struct channel_path *chp;
        struct device *device;
 
-       device = container_of(kobj, struct device, kobj);
+       device = kobj_to_dev(kobj);
        chp = to_channelpath(device);
        if (chp->cmg == -1)
                return 0;
@@ -184,7 +184,7 @@ static ssize_t chp_measurement_read(struct file *filp, struct kobject *kobj,
        struct device *device;
        unsigned int size;
 
-       device = container_of(kobj, struct device, kobj);
+       device = kobj_to_dev(kobj);
        chp = to_channelpath(device);
        css = to_css(chp->dev.parent);
 
index 3ab8e80..e115623 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/io.h>
 #include <asm/qdio.h>
 
 #include "cio.h"
@@ -205,7 +206,7 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
 
        /* fill in sl */
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
-               q->sl->element[j].sbal = (unsigned long)q->sbal[j];
+               q->sl->element[j].sbal = virt_to_phys(q->sbal[j]);
 }
 
 static void setup_queues(struct qdio_irq *irq_ptr,
index d4caf46..2afe215 100644 (file)
@@ -887,7 +887,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
        /* empty pin tag */
        *p++ = 0x04;
        *p++ = 0;
-       /* encrytped key value tag and bytes */
+       /* encrypted key value tag and bytes */
        p += asn1tag_write(p, 0x04, enckey, enckeysize);
 
        /* reply cprb and payload */
@@ -1095,7 +1095,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
 
        /* Step 1: generate AES 256 bit random kek key */
        rc = ep11_genaeskey(card, domain, 256,
-                           0x00006c00, /* EN/DECRYTP, WRAP/UNWRAP */
+                           0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
                            kek, &keklen);
        if (rc) {
                DEBUG_ERR(
index 5efcaa4..8ca85c8 100644 (file)
@@ -1128,9 +1128,10 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        qeth_tx_complete_buf(buf, error, budget);
 
        for (i = 0; i < queue->max_elements; ++i) {
-               if (buf->buffer->element[i].addr && buf->is_header[i])
-                       kmem_cache_free(qeth_core_header_cache,
-                               buf->buffer->element[i].addr);
+               void *data = phys_to_virt(buf->buffer->element[i].addr);
+
+               if (data && buf->is_header[i])
+                       kmem_cache_free(qeth_core_header_cache, data);
                buf->is_header[i] = 0;
        }
 
@@ -2641,7 +2642,8 @@ static int qeth_init_input_buffer(struct qeth_card *card,
        buf->pool_entry = pool_entry;
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
                buf->buffer->element[i].length = PAGE_SIZE;
-               buf->buffer->element[i].addr =  pool_entry->elements[i];
+               buf->buffer->element[i].addr =
+                       virt_to_phys(pool_entry->elements[i]);
                if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
                        buf->buffer->element[i].eflags = SBAL_EFLAGS_LAST_ENTRY;
                else
@@ -3459,9 +3461,8 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
 
                while ((e < QDIO_MAX_ELEMENTS_PER_BUFFER) &&
                       buffer->element[e].addr) {
-                       unsigned long phys_aob_addr;
+                       unsigned long phys_aob_addr = buffer->element[e].addr;
 
-                       phys_aob_addr = (unsigned long) buffer->element[e].addr;
                        qeth_qdio_handle_aob(card, phys_aob_addr);
                        ++e;
                }
@@ -3750,7 +3751,7 @@ static unsigned int __qeth_fill_buffer(struct sk_buff *skb,
                elem_length = min_t(unsigned int, length,
                                    PAGE_SIZE - offset_in_page(data));
 
-               buffer->element[element].addr = data;
+               buffer->element[element].addr = virt_to_phys(data);
                buffer->element[element].length = elem_length;
                length -= elem_length;
                if (is_first_elem) {
@@ -3780,7 +3781,7 @@ static unsigned int __qeth_fill_buffer(struct sk_buff *skb,
                        elem_length = min_t(unsigned int, length,
                                            PAGE_SIZE - offset_in_page(data));
 
-                       buffer->element[element].addr = data;
+                       buffer->element[element].addr = virt_to_phys(data);
                        buffer->element[element].length = elem_length;
                        buffer->element[element].eflags =
                                SBAL_EFLAGS_MIDDLE_FRAG;
@@ -3820,7 +3821,7 @@ static unsigned int qeth_fill_buffer(struct qeth_qdio_out_buffer *buf,
                int element = buf->next_element_to_fill;
                is_first_elem = false;
 
-               buffer->element[element].addr = hdr;
+               buffer->element[element].addr = virt_to_phys(hdr);
                buffer->element[element].length = hd_len;
                buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG;
                /* remember to free cache-allocated qeth_hdr: */
@@ -4746,10 +4747,10 @@ static void qeth_qdio_establish_cq(struct qeth_card *card,
        if (card->options.cq == QETH_CQ_ENABLED) {
                int offset = QDIO_MAX_BUFFERS_PER_Q *
                             (card->qdio.no_in_queues - 1);
-               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-                       in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
-                               virt_to_phys(card->qdio.c_q->bufs[i].buffer);
-               }
+
+               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+                       in_sbal_ptrs[offset + i] =
+                               card->qdio.c_q->bufs[i].buffer;
 
                queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
        }
@@ -4783,10 +4784,9 @@ static int qeth_qdio_establish(struct qeth_card *card)
                rc = -ENOMEM;
                goto out_free_qib_param;
        }
-       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-               in_sbal_ptrs[i] = (struct qdio_buffer *)
-                       virt_to_phys(card->qdio.in_q->bufs[i].buffer);
-       }
+
+       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+               in_sbal_ptrs[i] = card->qdio.in_q->bufs[i].buffer;
 
        queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *),
                                   GFP_KERNEL);
@@ -4807,11 +4807,11 @@ static int qeth_qdio_establish(struct qeth_card *card)
                rc = -ENOMEM;
                goto out_free_queue_start_poll;
        }
+
        for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
-               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
-                       out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
-                               card->qdio.out_qs[i]->bufs[j]->buffer);
-               }
+               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++, k++)
+                       out_sbal_ptrs[k] =
+                               card->qdio.out_qs[i]->bufs[j]->buffer;
 
        memset(&init_data, 0, sizeof(struct qdio_initialize));
        init_data.cdev                   = CARD_DDEV(card);
@@ -5289,7 +5289,7 @@ next_packet:
                offset = 0;
        }
 
-       hdr = element->addr + offset;
+       hdr = phys_to_virt(element->addr) + offset;
        offset += sizeof(*hdr);
        skb = NULL;
 
@@ -5388,7 +5388,7 @@ use_skb:
 walk_packet:
        while (skb_len) {
                int data_len = min(skb_len, (int)(element->length - offset));
-               char *data = element->addr + offset;
+               char *data = phys_to_virt(element->addr) + offset;
 
                skb_len -= data_len;
                offset += data_len;
index 223a805..cae9b7f 100644 (file)
@@ -2510,7 +2510,7 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
        for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
 
                sbale = &sbal->element[idx];
-               req_id = (unsigned long) sbale->addr;
+               req_id = sbale->addr;
                fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id);
 
                if (!fsf_req) {
index 661436a..f0d6296 100644 (file)
@@ -98,7 +98,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
                        memset(pl, 0,
                               ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
                        sbale = qdio->res_q[idx]->element;
-                       req_id = (u64) sbale->addr;
+                       req_id = sbale->addr;
                        scount = min(sbale->scount + 1,
                                     ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
                                     /* incl. signaling SBAL */
@@ -199,7 +199,7 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                                             q_req->sbal_number);
                        return -EINVAL;
                }
-               sbale->addr = sg_virt(sg);
+               sbale->addr = sg_phys(sg);
                sbale->length = sg->length;
        }
        return 0;
@@ -418,7 +418,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
                sbale->length = 0;
                sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
                sbale->sflags = 0;
-               sbale->addr = NULL;
+               sbale->addr = 0;
        }
 
        if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
index 2a816a3..6b43d6b 100644 (file)
@@ -122,14 +122,14 @@ void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                                        % QDIO_MAX_BUFFERS_PER_Q;
 
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
-       sbale->addr = (void *) req_id;
+       sbale->addr = req_id;
        sbale->eflags = 0;
        sbale->sflags = SBAL_SFLAGS0_COMMAND | sbtype;
 
        if (unlikely(!data))
                return;
        sbale++;
-       sbale->addr = data;
+       sbale->addr = virt_to_phys(data);
        sbale->length = len;
 }
 
@@ -152,7 +152,7 @@ void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
        BUG_ON(q_req->sbale_curr == qdio->max_sbale_per_sbal - 1);
        q_req->sbale_curr++;
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->addr = data;
+       sbale->addr = virt_to_phys(data);
        sbale->length = len;
 }
 
index f3b36fd..b2ad965 100644 (file)
@@ -623,7 +623,8 @@ retry_alloc:
 
        fusion->io_request_frames =
                        dma_pool_alloc(fusion->io_request_frames_pool,
-                               GFP_KERNEL, &fusion->io_request_frames_phys);
+                               GFP_KERNEL | __GFP_NOWARN,
+                               &fusion->io_request_frames_phys);
        if (!fusion->io_request_frames) {
                if (instance->max_fw_cmds >= (MEGASAS_REDUCE_QD_COUNT * 2)) {
                        instance->max_fw_cmds -= MEGASAS_REDUCE_QD_COUNT;
@@ -661,7 +662,7 @@ retry_alloc:
 
                fusion->io_request_frames =
                        dma_pool_alloc(fusion->io_request_frames_pool,
-                                      GFP_KERNEL,
+                                      GFP_KERNEL | __GFP_NOWARN,
                                       &fusion->io_request_frames_phys);
 
                if (!fusion->io_request_frames) {
index b94ed4e..09e55ea 100644 (file)
@@ -1165,9 +1165,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
                conn->cid);
 
-       if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
-               return iscsit_add_reject_cmd(cmd,
-                               ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
+       target_get_sess_cmd(&cmd->se_cmd, true);
 
        cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
                                                     scsilun_to_int(&hdr->lun));
@@ -2004,9 +2002,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                              conn->sess->se_sess, 0, DMA_NONE,
                              TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
 
-       if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
-               return iscsit_add_reject_cmd(cmd,
-                               ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
+       target_get_sess_cmd(&cmd->se_cmd, true);
 
        /*
         * TASK_REASSIGN for ERL=2 / connection stays inside of
@@ -4149,6 +4145,9 @@ int iscsit_close_connection(
        iscsit_stop_nopin_response_timer(conn);
        iscsit_stop_nopin_timer(conn);
 
+       if (conn->conn_transport->iscsit_wait_conn)
+               conn->conn_transport->iscsit_wait_conn(conn);
+
        /*
         * During Connection recovery drop unacknowledged out of order
         * commands for this connection, and prepare the other commands
@@ -4231,11 +4230,6 @@ int iscsit_close_connection(
         * must wait until they have completed.
         */
        iscsit_check_conn_usage_count(conn);
-       target_sess_cmd_list_set_waiting(sess->se_sess);
-       target_wait_for_sess_cmds(sess->se_sess);
-
-       if (conn->conn_transport->iscsit_wait_conn)
-               conn->conn_transport->iscsit_wait_conn(conn);
 
        ahash_request_free(conn->conn_tx_hash);
        if (conn->conn_rx_hash) {
index ea482d4..0ae9e60 100644 (file)
@@ -666,6 +666,11 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
 
        target_remove_from_state_list(cmd);
 
+       /*
+        * Clear struct se_cmd->se_lun before the handoff to FE.
+        */
+       cmd->se_lun = NULL;
+
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        /*
         * Determine if frontend context caller is requesting the stopping of
@@ -693,6 +698,17 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
        return cmd->se_tfo->check_stop_free(cmd);
 }
 
+static void transport_lun_remove_cmd(struct se_cmd *cmd)
+{
+       struct se_lun *lun = cmd->se_lun;
+
+       if (!lun)
+               return;
+
+       if (cmpxchg(&cmd->lun_ref_active, true, false))
+               percpu_ref_put(&lun->lun_ref);
+}
+
 static void target_complete_failure_work(struct work_struct *work)
 {
        struct se_cmd *cmd = container_of(work, struct se_cmd, work);
@@ -783,6 +799,8 @@ static void target_handle_abort(struct se_cmd *cmd)
 
        WARN_ON_ONCE(kref_read(&cmd->cmd_kref) == 0);
 
+       transport_lun_remove_cmd(cmd);
+
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
@@ -1708,6 +1726,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
 
+       transport_lun_remove_cmd(se_cmd);
        transport_cmd_check_stop_to_fabric(se_cmd);
 }
 
@@ -1898,6 +1917,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
                goto queue_full;
 
 check_stop:
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
        return;
 
@@ -2195,6 +2215,7 @@ queue_status:
                transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
                return;
        }
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
@@ -2289,6 +2310,7 @@ static void target_complete_ok_work(struct work_struct *work)
                if (ret)
                        goto queue_full;
 
+               transport_lun_remove_cmd(cmd);
                transport_cmd_check_stop_to_fabric(cmd);
                return;
        }
@@ -2314,6 +2336,7 @@ static void target_complete_ok_work(struct work_struct *work)
                        if (ret)
                                goto queue_full;
 
+                       transport_lun_remove_cmd(cmd);
                        transport_cmd_check_stop_to_fabric(cmd);
                        return;
                }
@@ -2349,6 +2372,7 @@ queue_rsp:
                        if (ret)
                                goto queue_full;
 
+                       transport_lun_remove_cmd(cmd);
                        transport_cmd_check_stop_to_fabric(cmd);
                        return;
                }
@@ -2384,6 +2408,7 @@ queue_status:
                break;
        }
 
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
        return;
 
@@ -2710,6 +2735,9 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
                 */
                if (cmd->state_active)
                        target_remove_from_state_list(cmd);
+
+               if (cmd->se_lun)
+                       transport_lun_remove_cmd(cmd);
        }
        if (aborted)
                cmd->free_compl = &compl;
@@ -2781,9 +2809,6 @@ static void target_release_cmd_kref(struct kref *kref)
        struct completion *abrt_compl = se_cmd->abrt_compl;
        unsigned long flags;
 
-       if (se_cmd->lun_ref_active)
-               percpu_ref_put(&se_cmd->se_lun->lun_ref);
-
        if (se_sess) {
                spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
                list_del_init(&se_cmd->se_cmd_list);
index 4e32b64..191f971 100644 (file)
@@ -3,6 +3,6 @@
 config AMDTEE
        tristate "AMD-TEE"
        default m
-       depends on CRYPTO_DEV_SP_PSP
+       depends on CRYPTO_DEV_SP_PSP && CRYPTO_DEV_CCP_DD
        help
          This implements AMD's Trusted Execution Environment (TEE) driver.
index 70650b2..17240c5 100644 (file)
@@ -33,7 +33,9 @@ asmlinkage __visible void xen_maybe_preempt_hcall(void)
                 * cpu.
                 */
                __this_cpu_write(xen_in_preemptible_hcall, false);
-               _cond_resched();
+               local_irq_enable();
+               cond_resched();
+               local_irq_disable();
                __this_cpu_write(xen_in_preemptible_hcall, true);
        }
 }
index 89422aa..c6c9a6a 100644 (file)
@@ -3200,6 +3200,7 @@ int __cold open_ctree(struct super_block *sb,
        if (IS_ERR(fs_info->fs_root)) {
                err = PTR_ERR(fs_info->fs_root);
                btrfs_warn(fs_info, "failed to read fs tree: %d", err);
+               fs_info->fs_root = NULL;
                goto fail_qgroup;
        }
 
@@ -4276,6 +4277,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                cond_resched();
                spin_lock(&delayed_refs->lock);
        }
+       btrfs_qgroup_destroy_extent_records(trans);
 
        spin_unlock(&delayed_refs->lock);
 
@@ -4501,7 +4503,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
        wake_up(&fs_info->transaction_wait);
 
        btrfs_destroy_delayed_inodes(fs_info);
-       btrfs_assert_delayed_root_empty(fs_info);
 
        btrfs_destroy_marked_extents(fs_info, &cur_trans->dirty_pages,
                                     EXTENT_DIRTY);
index 0163fdd..a7bc661 100644 (file)
@@ -4430,6 +4430,8 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
 
        ret = alloc_reserved_file_extent(trans, 0, root_objectid, 0, owner,
                                         offset, ins, 1);
+       if (ret)
+               btrfs_pin_extent(fs_info, ins->objectid, ins->offset, 1);
        btrfs_put_block_group(block_group);
        return ret;
 }
index 36deef6..1ccb3f8 100644 (file)
@@ -4103,8 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->reada = READA_BACK;
 
-       lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
-                        &cached_state);
+       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
+               lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
+                                &cached_state);
 
        /*
         * We want to drop from the next block forward in case this new size is
@@ -4368,11 +4369,10 @@ out:
                if (!ret && last_size > new_size)
                        last_size = new_size;
                btrfs_ordered_update_i_size(inode, last_size, NULL);
+               unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start,
+                                    (u64)-1, &cached_state);
        }
 
-       unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
-                            &cached_state);
-
        btrfs_free_path(path);
        return ret;
 }
@@ -9824,6 +9824,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_key ins;
        u64 cur_offset = start;
+       u64 clear_offset = start;
        u64 i_size;
        u64 cur_bytes;
        u64 last_alloc = (u64)-1;
@@ -9858,6 +9859,15 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                                btrfs_end_transaction(trans);
                        break;
                }
+
+               /*
+                * We've reserved this space, and thus converted it from
+                * ->bytes_may_use to ->bytes_reserved.  Any error that happens
+                * from here on out we will only need to clear our reservation
+                * for the remaining unreserved area, so advance our
+                * clear_offset by our extent size.
+                */
+               clear_offset += ins.offset;
                btrfs_dec_block_group_reservations(fs_info, ins.objectid);
 
                last_alloc = ins.offset;
@@ -9937,9 +9947,9 @@ next:
                if (own_trans)
                        btrfs_end_transaction(trans);
        }
-       if (cur_offset < end)
-               btrfs_free_reserved_data_space(inode, NULL, cur_offset,
-                       end - cur_offset + 1);
+       if (clear_offset < end)
+               btrfs_free_reserved_data_space(inode, NULL, clear_offset,
+                       end - clear_offset + 1);
        return ret;
 }
 
index ecb9fb6..a65f189 100644 (file)
@@ -679,10 +679,15 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
                }
                btrfs_start_ordered_extent(inode, ordered, 1);
                end = ordered->file_offset;
+               /*
+                * If the ordered extent had an error save the error but don't
+                * exit without waiting first for all other ordered extents in
+                * the range to complete.
+                */
                if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags))
                        ret = -EIO;
                btrfs_put_ordered_extent(ordered);
-               if (ret || end == 0 || end == start)
+               if (end == 0 || end == start)
                        break;
                end--;
        }
index 98d9a50..ff1870f 100644 (file)
@@ -4002,3 +4002,16 @@ out:
        }
        return ret;
 }
+
+void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
+{
+       struct btrfs_qgroup_extent_record *entry;
+       struct btrfs_qgroup_extent_record *next;
+       struct rb_root *root;
+
+       root = &trans->delayed_refs.dirty_extent_root;
+       rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
+               ulist_free(entry->old_roots);
+               kfree(entry);
+       }
+}
index 236f122..1bc6544 100644 (file)
@@ -414,5 +414,6 @@ int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
                u64 last_snapshot);
 int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
                struct btrfs_root *root, struct extent_buffer *eb);
+void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
 
 #endif
index 33dcc88..beb6c69 100644 (file)
@@ -121,6 +121,8 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
                BUG_ON(!list_empty(&transaction->list));
                WARN_ON(!RB_EMPTY_ROOT(
                                &transaction->delayed_refs.href_root.rb_root));
+               WARN_ON(!RB_EMPTY_ROOT(
+                               &transaction->delayed_refs.dirty_extent_root));
                if (transaction->delayed_refs.pending_csums)
                        btrfs_err(transaction->fs_info,
                                  "pending csums is %llu",
index 5f993a4..8fd0b3c 100644 (file)
@@ -270,6 +270,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
        ext4_group_t ngroups = ext4_get_groups_count(sb);
        struct ext4_group_desc *desc;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct buffer_head *bh_p;
 
        if (block_group >= ngroups) {
                ext4_error(sb, "block_group >= groups_count - block_group = %u,"
@@ -280,7 +281,14 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
 
        group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
        offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
-       if (!sbi->s_group_desc[group_desc]) {
+       bh_p = sbi_array_rcu_deref(sbi, s_group_desc, group_desc);
+       /*
+        * sbi_array_rcu_deref returns with rcu unlocked, this is ok since
+        * the pointer being dereferenced won't be dereferenced again. By
+        * looking at the usage in add_new_gdb() the value isn't modified,
+        * just the pointer, and so it remains valid.
+        */
+       if (!bh_p) {
                ext4_error(sb, "Group descriptor not loaded - "
                           "block_group = %u, group_desc = %u, desc = %u",
                           block_group, group_desc, offset);
@@ -288,10 +296,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
        }
 
        desc = (struct ext4_group_desc *)(
-               (__u8 *)sbi->s_group_desc[group_desc]->b_data +
+               (__u8 *)bh_p->b_data +
                offset * EXT4_DESC_SIZE(sb));
        if (bh)
-               *bh = sbi->s_group_desc[group_desc];
+               *bh = bh_p;
        return desc;
 }
 
index 4441331..61b37a0 100644 (file)
@@ -1400,7 +1400,7 @@ struct ext4_sb_info {
        loff_t s_bitmap_maxbytes;       /* max bytes for bitmap files */
        struct buffer_head * s_sbh;     /* Buffer containing the super block */
        struct ext4_super_block *s_es;  /* Pointer to the super block in the buffer */
-       struct buffer_head **s_group_desc;
+       struct buffer_head * __rcu *s_group_desc;
        unsigned int s_mount_opt;
        unsigned int s_mount_opt2;
        unsigned int s_mount_flags;
@@ -1462,7 +1462,7 @@ struct ext4_sb_info {
 #endif
 
        /* for buddy allocator */
-       struct ext4_group_info ***s_group_info;
+       struct ext4_group_info ** __rcu *s_group_info;
        struct inode *s_buddy_cache;
        spinlock_t s_md_lock;
        unsigned short *s_mb_offsets;
@@ -1512,7 +1512,7 @@ struct ext4_sb_info {
        unsigned int s_extent_max_zeroout_kb;
 
        unsigned int s_log_groups_per_flex;
-       struct flex_groups *s_flex_groups;
+       struct flex_groups * __rcu *s_flex_groups;
        ext4_group_t s_flex_groups_allocated;
 
        /* workqueue for reserved extent conversions (buffered io) */
@@ -1552,8 +1552,11 @@ struct ext4_sb_info {
        struct ratelimit_state s_warning_ratelimit_state;
        struct ratelimit_state s_msg_ratelimit_state;
 
-       /* Barrier between changing inodes' journal flags and writepages ops. */
-       struct percpu_rw_semaphore s_journal_flag_rwsem;
+       /*
+        * Barrier between writepages ops and changing any inode's JOURNAL_DATA
+        * or EXTENTS flag.
+        */
+       struct percpu_rw_semaphore s_writepages_rwsem;
        struct dax_device *s_daxdev;
 #ifdef CONFIG_EXT4_DEBUG
        unsigned long s_simulate_fail;
@@ -1577,6 +1580,23 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
 }
 
 /*
+ * Returns: sbi->field[index]
+ * Used to access an array element from the following sbi fields which require
+ * rcu protection to avoid dereferencing an invalid pointer due to reassignment
+ * - s_group_desc
+ * - s_group_info
+ * - s_flex_group
+ */
+#define sbi_array_rcu_deref(sbi, field, index)                            \
+({                                                                        \
+       typeof(*((sbi)->field)) _v;                                        \
+       rcu_read_lock();                                                   \
+       _v = ((typeof(_v)*)rcu_dereference((sbi)->field))[index];          \
+       rcu_read_unlock();                                                 \
+       _v;                                                                \
+})
+
+/*
  * Simulate_fail codes
  */
 #define EXT4_SIM_BBITMAP_EIO   1
@@ -2730,6 +2750,7 @@ extern int ext4_generic_delete_entry(handle_t *handle,
 extern bool ext4_empty_dir(struct inode *inode);
 
 /* resize.c */
+extern void ext4_kvfree_array_rcu(void *to_free);
 extern int ext4_group_add(struct super_block *sb,
                                struct ext4_new_group_data *input);
 extern int ext4_group_extend(struct super_block *sb,
@@ -2976,13 +2997,13 @@ static inline
 struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
                                            ext4_group_t group)
 {
-        struct ext4_group_info ***grp_info;
+        struct ext4_group_info **grp_info;
         long indexv, indexh;
         BUG_ON(group >= EXT4_SB(sb)->s_groups_count);
-        grp_info = EXT4_SB(sb)->s_group_info;
         indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
         indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
-        return grp_info[indexv][indexh];
+        grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
+        return grp_info[indexh];
 }
 
 /*
@@ -3032,7 +3053,7 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
                     !inode_is_locked(inode));
        down_write(&EXT4_I(inode)->i_data_sem);
        if (newsize > EXT4_I(inode)->i_disksize)
-               EXT4_I(inode)->i_disksize = newsize;
+               WRITE_ONCE(EXT4_I(inode)->i_disksize, newsize);
        up_write(&EXT4_I(inode)->i_data_sem);
 }
 
index c66e8f9..f95ee99 100644 (file)
@@ -328,11 +328,13 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
 
        percpu_counter_inc(&sbi->s_freeinodes_counter);
        if (sbi->s_log_groups_per_flex) {
-               ext4_group_t f = ext4_flex_group(sbi, block_group);
+               struct flex_groups *fg;
 
-               atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+               fg = sbi_array_rcu_deref(sbi, s_flex_groups,
+                                        ext4_flex_group(sbi, block_group));
+               atomic_inc(&fg->free_inodes);
                if (is_directory)
-                       atomic_dec(&sbi->s_flex_groups[f].used_dirs);
+                       atomic_dec(&fg->used_dirs);
        }
        BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
        fatal = ext4_handle_dirty_metadata(handle, NULL, bh2);
@@ -368,12 +370,13 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
                            int flex_size, struct orlov_stats *stats)
 {
        struct ext4_group_desc *desc;
-       struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups;
 
        if (flex_size > 1) {
-               stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
-               stats->free_clusters = atomic64_read(&flex_group[g].free_clusters);
-               stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
+               struct flex_groups *fg = sbi_array_rcu_deref(EXT4_SB(sb),
+                                                            s_flex_groups, g);
+               stats->free_inodes = atomic_read(&fg->free_inodes);
+               stats->free_clusters = atomic64_read(&fg->free_clusters);
+               stats->used_dirs = atomic_read(&fg->used_dirs);
                return;
        }
 
@@ -1054,7 +1057,8 @@ got:
                if (sbi->s_log_groups_per_flex) {
                        ext4_group_t f = ext4_flex_group(sbi, group);
 
-                       atomic_inc(&sbi->s_flex_groups[f].used_dirs);
+                       atomic_inc(&sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                       f)->used_dirs);
                }
        }
        if (ext4_has_group_desc_csum(sb)) {
@@ -1077,7 +1081,8 @@ got:
 
        if (sbi->s_log_groups_per_flex) {
                flex_group = ext4_flex_group(sbi, group);
-               atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
+               atomic_dec(&sbi_array_rcu_deref(sbi, s_flex_groups,
+                                               flex_group)->free_inodes);
        }
 
        inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
index e60aca7..fa0ff78 100644 (file)
@@ -2465,7 +2465,7 @@ update_disksize:
         * truncate are avoided by checking i_size under i_data_sem.
         */
        disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT;
-       if (disksize > EXT4_I(inode)->i_disksize) {
+       if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) {
                int err2;
                loff_t i_size;
 
@@ -2628,7 +2628,7 @@ static int ext4_writepages(struct address_space *mapping,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return -EIO;
 
-       percpu_down_read(&sbi->s_journal_flag_rwsem);
+       percpu_down_read(&sbi->s_writepages_rwsem);
        trace_ext4_writepages(inode, wbc);
 
        /*
@@ -2849,7 +2849,7 @@ unplug:
 out_writepages:
        trace_ext4_writepages_result(inode, wbc, ret,
                                     nr_to_write - wbc->nr_to_write);
-       percpu_up_read(&sbi->s_journal_flag_rwsem);
+       percpu_up_read(&sbi->s_writepages_rwsem);
        return ret;
 }
 
@@ -2864,13 +2864,13 @@ static int ext4_dax_writepages(struct address_space *mapping,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return -EIO;
 
-       percpu_down_read(&sbi->s_journal_flag_rwsem);
+       percpu_down_read(&sbi->s_writepages_rwsem);
        trace_ext4_writepages(inode, wbc);
 
        ret = dax_writeback_mapping_range(mapping, sbi->s_daxdev, wbc);
        trace_ext4_writepages_result(inode, wbc, ret,
                                     nr_to_write - wbc->nr_to_write);
-       percpu_up_read(&sbi->s_journal_flag_rwsem);
+       percpu_up_read(&sbi->s_writepages_rwsem);
        return ret;
 }
 
@@ -5861,7 +5861,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                }
        }
 
-       percpu_down_write(&sbi->s_journal_flag_rwsem);
+       percpu_down_write(&sbi->s_writepages_rwsem);
        jbd2_journal_lock_updates(journal);
 
        /*
@@ -5878,7 +5878,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                err = jbd2_journal_flush(journal);
                if (err < 0) {
                        jbd2_journal_unlock_updates(journal);
-                       percpu_up_write(&sbi->s_journal_flag_rwsem);
+                       percpu_up_write(&sbi->s_writepages_rwsem);
                        return err;
                }
                ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
@@ -5886,7 +5886,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        ext4_set_aops(inode);
 
        jbd2_journal_unlock_updates(journal);
-       percpu_up_write(&sbi->s_journal_flag_rwsem);
+       percpu_up_write(&sbi->s_writepages_rwsem);
 
        if (val)
                up_write(&EXT4_I(inode)->i_mmap_sem);
index f648381..51a78eb 100644 (file)
@@ -2356,7 +2356,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned size;
-       struct ext4_group_info ***new_groupinfo;
+       struct ext4_group_info ***old_groupinfo, ***new_groupinfo;
 
        size = (ngroups + EXT4_DESC_PER_BLOCK(sb) - 1) >>
                EXT4_DESC_PER_BLOCK_BITS(sb);
@@ -2369,13 +2369,16 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
                ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
                return -ENOMEM;
        }
-       if (sbi->s_group_info) {
-               memcpy(new_groupinfo, sbi->s_group_info,
+       rcu_read_lock();
+       old_groupinfo = rcu_dereference(sbi->s_group_info);
+       if (old_groupinfo)
+               memcpy(new_groupinfo, old_groupinfo,
                       sbi->s_group_info_size * sizeof(*sbi->s_group_info));
-               kvfree(sbi->s_group_info);
-       }
-       sbi->s_group_info = new_groupinfo;
+       rcu_read_unlock();
+       rcu_assign_pointer(sbi->s_group_info, new_groupinfo);
        sbi->s_group_info_size = size / sizeof(*sbi->s_group_info);
+       if (old_groupinfo)
+               ext4_kvfree_array_rcu(old_groupinfo);
        ext4_debug("allocated s_groupinfo array for %d meta_bg's\n", 
                   sbi->s_group_info_size);
        return 0;
@@ -2387,6 +2390,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 {
        int i;
        int metalen = 0;
+       int idx = group >> EXT4_DESC_PER_BLOCK_BITS(sb);
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_group_info **meta_group_info;
        struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
@@ -2405,12 +2409,12 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
                                 "for a buddy group");
                        goto exit_meta_group_info;
                }
-               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] =
-                       meta_group_info;
+               rcu_read_lock();
+               rcu_dereference(sbi->s_group_info)[idx] = meta_group_info;
+               rcu_read_unlock();
        }
 
-       meta_group_info =
-               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)];
+       meta_group_info = sbi_array_rcu_deref(sbi, s_group_info, idx);
        i = group & (EXT4_DESC_PER_BLOCK(sb) - 1);
 
        meta_group_info[i] = kmem_cache_zalloc(cachep, GFP_NOFS);
@@ -2458,8 +2462,13 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 exit_group_info:
        /* If a meta_group_info table has been allocated, release it now */
        if (group % EXT4_DESC_PER_BLOCK(sb) == 0) {
-               kfree(sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]);
-               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = NULL;
+               struct ext4_group_info ***group_info;
+
+               rcu_read_lock();
+               group_info = rcu_dereference(sbi->s_group_info);
+               kfree(group_info[idx]);
+               group_info[idx] = NULL;
+               rcu_read_unlock();
        }
 exit_meta_group_info:
        return -ENOMEM;
@@ -2472,6 +2481,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        int err;
        struct ext4_group_desc *desc;
+       struct ext4_group_info ***group_info;
        struct kmem_cache *cachep;
 
        err = ext4_mb_alloc_groupinfo(sb, ngroups);
@@ -2507,11 +2517,16 @@ err_freebuddy:
        while (i-- > 0)
                kmem_cache_free(cachep, ext4_get_group_info(sb, i));
        i = sbi->s_group_info_size;
+       rcu_read_lock();
+       group_info = rcu_dereference(sbi->s_group_info);
        while (i-- > 0)
-               kfree(sbi->s_group_info[i]);
+               kfree(group_info[i]);
+       rcu_read_unlock();
        iput(sbi->s_buddy_cache);
 err_freesgi:
-       kvfree(sbi->s_group_info);
+       rcu_read_lock();
+       kvfree(rcu_dereference(sbi->s_group_info));
+       rcu_read_unlock();
        return -ENOMEM;
 }
 
@@ -2700,7 +2715,7 @@ int ext4_mb_release(struct super_block *sb)
        ext4_group_t ngroups = ext4_get_groups_count(sb);
        ext4_group_t i;
        int num_meta_group_infos;
-       struct ext4_group_info *grinfo;
+       struct ext4_group_info *grinfo, ***group_info;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
 
@@ -2719,9 +2734,12 @@ int ext4_mb_release(struct super_block *sb)
                num_meta_group_infos = (ngroups +
                                EXT4_DESC_PER_BLOCK(sb) - 1) >>
                        EXT4_DESC_PER_BLOCK_BITS(sb);
+               rcu_read_lock();
+               group_info = rcu_dereference(sbi->s_group_info);
                for (i = 0; i < num_meta_group_infos; i++)
-                       kfree(sbi->s_group_info[i]);
-               kvfree(sbi->s_group_info);
+                       kfree(group_info[i]);
+               kvfree(group_info);
+               rcu_read_unlock();
        }
        kfree(sbi->s_mb_offsets);
        kfree(sbi->s_mb_maxs);
@@ -3020,7 +3038,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                ext4_group_t flex_group = ext4_flex_group(sbi,
                                                          ac->ac_b_ex.fe_group);
                atomic64_sub(ac->ac_b_ex.fe_len,
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                 flex_group)->free_clusters);
        }
 
        err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -4918,7 +4937,8 @@ do_more:
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
                atomic64_add(count_clusters,
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                 flex_group)->free_clusters);
        }
 
        /*
@@ -5075,7 +5095,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
                atomic64_add(clusters_freed,
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                 flex_group)->free_clusters);
        }
 
        ext4_mb_unload_buddy(&e4b);
index 89725fa..fb6520f 100644 (file)
@@ -407,6 +407,7 @@ static int free_ext_block(handle_t *handle, struct inode *inode)
 
 int ext4_ext_migrate(struct inode *inode)
 {
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        handle_t *handle;
        int retval = 0, i;
        __le32 *i_data;
@@ -431,6 +432,8 @@ int ext4_ext_migrate(struct inode *inode)
                 */
                return retval;
 
+       percpu_down_write(&sbi->s_writepages_rwsem);
+
        /*
         * Worst case we can touch the allocation bitmaps, a bgd
         * block, and a block to link in the orphan list.  We do need
@@ -441,7 +444,7 @@ int ext4_ext_migrate(struct inode *inode)
 
        if (IS_ERR(handle)) {
                retval = PTR_ERR(handle);
-               return retval;
+               goto out_unlock;
        }
        goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
                EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
@@ -452,7 +455,7 @@ int ext4_ext_migrate(struct inode *inode)
        if (IS_ERR(tmp_inode)) {
                retval = PTR_ERR(tmp_inode);
                ext4_journal_stop(handle);
-               return retval;
+               goto out_unlock;
        }
        i_size_write(tmp_inode, i_size_read(inode));
        /*
@@ -494,7 +497,7 @@ int ext4_ext_migrate(struct inode *inode)
                 */
                ext4_orphan_del(NULL, tmp_inode);
                retval = PTR_ERR(handle);
-               goto out;
+               goto out_tmp_inode;
        }
 
        ei = EXT4_I(inode);
@@ -576,10 +579,11 @@ err_out:
        ext4_ext_tree_init(handle, tmp_inode);
 out_stop:
        ext4_journal_stop(handle);
-out:
+out_tmp_inode:
        unlock_new_inode(tmp_inode);
        iput(tmp_inode);
-
+out_unlock:
+       percpu_up_write(&sbi->s_writepages_rwsem);
        return retval;
 }
 
@@ -589,7 +593,8 @@ out:
 int ext4_ind_migrate(struct inode *inode)
 {
        struct ext4_extent_header       *eh;
-       struct ext4_super_block         *es = EXT4_SB(inode->i_sb)->s_es;
+       struct ext4_sb_info             *sbi = EXT4_SB(inode->i_sb);
+       struct ext4_super_block         *es = sbi->s_es;
        struct ext4_inode_info          *ei = EXT4_I(inode);
        struct ext4_extent              *ex;
        unsigned int                    i, len;
@@ -613,9 +618,13 @@ int ext4_ind_migrate(struct inode *inode)
        if (test_opt(inode->i_sb, DELALLOC))
                ext4_alloc_da_blocks(inode);
 
+       percpu_down_write(&sbi->s_writepages_rwsem);
+
        handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               goto out_unlock;
+       }
 
        down_write(&EXT4_I(inode)->i_data_sem);
        ret = ext4_ext_check_inode(inode);
@@ -650,5 +659,7 @@ int ext4_ind_migrate(struct inode *inode)
 errout:
        ext4_journal_stop(handle);
        up_write(&EXT4_I(inode)->i_data_sem);
+out_unlock:
+       percpu_up_write(&sbi->s_writepages_rwsem);
        return ret;
 }
index ceff4b4..b05ea72 100644 (file)
@@ -1511,6 +1511,7 @@ restart:
                /*
                 * We deal with the read-ahead logic here.
                 */
+               cond_resched();
                if (ra_ptr >= ra_max) {
                        /* Refill the readahead buffer */
                        ra_ptr = 0;
index 86a2500..a50b512 100644 (file)
 
 #include "ext4_jbd2.h"
 
+struct ext4_rcu_ptr {
+       struct rcu_head rcu;
+       void *ptr;
+};
+
+static void ext4_rcu_ptr_callback(struct rcu_head *head)
+{
+       struct ext4_rcu_ptr *ptr;
+
+       ptr = container_of(head, struct ext4_rcu_ptr, rcu);
+       kvfree(ptr->ptr);
+       kfree(ptr);
+}
+
+void ext4_kvfree_array_rcu(void *to_free)
+{
+       struct ext4_rcu_ptr *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+
+       if (ptr) {
+               ptr->ptr = to_free;
+               call_rcu(&ptr->rcu, ext4_rcu_ptr_callback);
+               return;
+       }
+       synchronize_rcu();
+       kvfree(to_free);
+}
+
 int ext4_resize_begin(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -542,8 +569,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
                                brelse(gdb);
                                goto out;
                        }
-                       memcpy(gdb->b_data, sbi->s_group_desc[j]->b_data,
-                              gdb->b_size);
+                       memcpy(gdb->b_data, sbi_array_rcu_deref(sbi,
+                               s_group_desc, j)->b_data, gdb->b_size);
                        set_buffer_uptodate(gdb);
 
                        err = ext4_handle_dirty_metadata(handle, NULL, gdb);
@@ -860,13 +887,15 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        }
        brelse(dind);
 
-       o_group_desc = EXT4_SB(sb)->s_group_desc;
+       rcu_read_lock();
+       o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc);
        memcpy(n_group_desc, o_group_desc,
               EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
+       rcu_read_unlock();
        n_group_desc[gdb_num] = gdb_bh;
-       EXT4_SB(sb)->s_group_desc = n_group_desc;
+       rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc);
        EXT4_SB(sb)->s_gdb_count++;
-       kvfree(o_group_desc);
+       ext4_kvfree_array_rcu(o_group_desc);
 
        le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
        err = ext4_handle_dirty_super(handle, sb);
@@ -909,9 +938,11 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
                return err;
        }
 
-       o_group_desc = EXT4_SB(sb)->s_group_desc;
+       rcu_read_lock();
+       o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc);
        memcpy(n_group_desc, o_group_desc,
               EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
+       rcu_read_unlock();
        n_group_desc[gdb_num] = gdb_bh;
 
        BUFFER_TRACE(gdb_bh, "get_write_access");
@@ -922,9 +953,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
                return err;
        }
 
-       EXT4_SB(sb)->s_group_desc = n_group_desc;
+       rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc);
        EXT4_SB(sb)->s_gdb_count++;
-       kvfree(o_group_desc);
+       ext4_kvfree_array_rcu(o_group_desc);
        return err;
 }
 
@@ -1188,7 +1219,8 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
                 * use non-sparse filesystems anymore.  This is already checked above.
                 */
                if (gdb_off) {
-                       gdb_bh = sbi->s_group_desc[gdb_num];
+                       gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
+                                                    gdb_num);
                        BUFFER_TRACE(gdb_bh, "get_write_access");
                        err = ext4_journal_get_write_access(handle, gdb_bh);
 
@@ -1270,7 +1302,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
                /*
                 * get_write_access() has been called on gdb_bh by ext4_add_new_desc().
                 */
-               gdb_bh = sbi->s_group_desc[gdb_num];
+               gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, gdb_num);
                /* Update group descriptor block for new group */
                gdp = (struct ext4_group_desc *)(gdb_bh->b_data +
                                                 gdb_off * EXT4_DESC_SIZE(sb));
@@ -1398,11 +1430,14 @@ static void ext4_update_super(struct super_block *sb,
                   percpu_counter_read(&sbi->s_freeclusters_counter));
        if (ext4_has_feature_flex_bg(sb) && sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group;
+               struct flex_groups *fg;
+
                flex_group = ext4_flex_group(sbi, group_data[0].group);
+               fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group);
                atomic64_add(EXT4_NUM_B2C(sbi, free_blocks),
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &fg->free_clusters);
                atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,
-                          &sbi->s_flex_groups[flex_group].free_inodes);
+                          &fg->free_inodes);
        }
 
        /*
@@ -1497,7 +1532,8 @@ exit_journal:
                for (; gdb_num <= gdb_num_end; gdb_num++) {
                        struct buffer_head *gdb_bh;
 
-                       gdb_bh = sbi->s_group_desc[gdb_num];
+                       gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
+                                                    gdb_num);
                        if (old_gdb == gdb_bh->b_blocknr)
                                continue;
                        update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
index f464dff..ff1b764 100644 (file)
@@ -1014,6 +1014,8 @@ static void ext4_put_super(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
+       struct buffer_head **group_desc;
+       struct flex_groups **flex_groups;
        int aborted = 0;
        int i, err;
 
@@ -1046,15 +1048,23 @@ static void ext4_put_super(struct super_block *sb)
        if (!sb_rdonly(sb))
                ext4_commit_super(sb, 1);
 
+       rcu_read_lock();
+       group_desc = rcu_dereference(sbi->s_group_desc);
        for (i = 0; i < sbi->s_gdb_count; i++)
-               brelse(sbi->s_group_desc[i]);
-       kvfree(sbi->s_group_desc);
-       kvfree(sbi->s_flex_groups);
+               brelse(group_desc[i]);
+       kvfree(group_desc);
+       flex_groups = rcu_dereference(sbi->s_flex_groups);
+       if (flex_groups) {
+               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
+                       kvfree(flex_groups[i]);
+               kvfree(flex_groups);
+       }
+       rcu_read_unlock();
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
+       percpu_free_rwsem(&sbi->s_writepages_rwsem);
 #ifdef CONFIG_QUOTA
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(get_qf_name(sb, sbi, i));
@@ -2380,8 +2390,8 @@ done:
 int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       struct flex_groups *new_groups;
-       int size;
+       struct flex_groups **old_groups, **new_groups;
+       int size, i;
 
        if (!sbi->s_log_groups_per_flex)
                return 0;
@@ -2390,22 +2400,37 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
        if (size <= sbi->s_flex_groups_allocated)
                return 0;
 
-       size = roundup_pow_of_two(size * sizeof(struct flex_groups));
-       new_groups = kvzalloc(size, GFP_KERNEL);
+       new_groups = kvzalloc(roundup_pow_of_two(size *
+                             sizeof(*sbi->s_flex_groups)), GFP_KERNEL);
        if (!new_groups) {
-               ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups",
-                        size / (int) sizeof(struct flex_groups));
+               ext4_msg(sb, KERN_ERR,
+                        "not enough memory for %d flex group pointers", size);
                return -ENOMEM;
        }
-
-       if (sbi->s_flex_groups) {
-               memcpy(new_groups, sbi->s_flex_groups,
-                      (sbi->s_flex_groups_allocated *
-                       sizeof(struct flex_groups)));
-               kvfree(sbi->s_flex_groups);
+       for (i = sbi->s_flex_groups_allocated; i < size; i++) {
+               new_groups[i] = kvzalloc(roundup_pow_of_two(
+                                        sizeof(struct flex_groups)),
+                                        GFP_KERNEL);
+               if (!new_groups[i]) {
+                       for (i--; i >= sbi->s_flex_groups_allocated; i--)
+                               kvfree(new_groups[i]);
+                       kvfree(new_groups);
+                       ext4_msg(sb, KERN_ERR,
+                                "not enough memory for %d flex groups", size);
+                       return -ENOMEM;
+               }
        }
-       sbi->s_flex_groups = new_groups;
-       sbi->s_flex_groups_allocated = size / sizeof(struct flex_groups);
+       rcu_read_lock();
+       old_groups = rcu_dereference(sbi->s_flex_groups);
+       if (old_groups)
+               memcpy(new_groups, old_groups,
+                      (sbi->s_flex_groups_allocated *
+                       sizeof(struct flex_groups *)));
+       rcu_read_unlock();
+       rcu_assign_pointer(sbi->s_flex_groups, new_groups);
+       sbi->s_flex_groups_allocated = size;
+       if (old_groups)
+               ext4_kvfree_array_rcu(old_groups);
        return 0;
 }
 
@@ -2413,6 +2438,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_group_desc *gdp = NULL;
+       struct flex_groups *fg;
        ext4_group_t flex_group;
        int i, err;
 
@@ -2430,12 +2456,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
                gdp = ext4_get_group_desc(sb, i, NULL);
 
                flex_group = ext4_flex_group(sbi, i);
-               atomic_add(ext4_free_inodes_count(sb, gdp),
-                          &sbi->s_flex_groups[flex_group].free_inodes);
+               fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group);
+               atomic_add(ext4_free_inodes_count(sb, gdp), &fg->free_inodes);
                atomic64_add(ext4_free_group_clusters(sb, gdp),
-                            &sbi->s_flex_groups[flex_group].free_clusters);
-               atomic_add(ext4_used_dirs_count(sb, gdp),
-                          &sbi->s_flex_groups[flex_group].used_dirs);
+                            &fg->free_clusters);
+               atomic_add(ext4_used_dirs_count(sb, gdp), &fg->used_dirs);
        }
 
        return 1;
@@ -3009,7 +3034,7 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
                return 0;
        }
 
-#if !defined(CONFIG_QUOTA) || !defined(CONFIG_QFMT_V2)
+#if !IS_ENABLED(CONFIG_QUOTA) || !IS_ENABLED(CONFIG_QFMT_V2)
        if (!readonly && (ext4_has_feature_quota(sb) ||
                          ext4_has_feature_project(sb))) {
                ext4_msg(sb, KERN_ERR,
@@ -3634,9 +3659,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev);
        char *orig_data = kstrdup(data, GFP_KERNEL);
-       struct buffer_head *bh;
+       struct buffer_head *bh, **group_desc;
        struct ext4_super_block *es = NULL;
        struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+       struct flex_groups **flex_groups;
        ext4_fsblk_t block;
        ext4_fsblk_t sb_block = get_sb_block(&data);
        ext4_fsblk_t logical_sb_block;
@@ -4290,9 +4316,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        goto failed_mount;
                }
        }
-       sbi->s_group_desc = kvmalloc_array(db_count,
-                                          sizeof(struct buffer_head *),
-                                          GFP_KERNEL);
+       rcu_assign_pointer(sbi->s_group_desc,
+                          kvmalloc_array(db_count,
+                                         sizeof(struct buffer_head *),
+                                         GFP_KERNEL));
        if (sbi->s_group_desc == NULL) {
                ext4_msg(sb, KERN_ERR, "not enough memory");
                ret = -ENOMEM;
@@ -4308,14 +4335,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        for (i = 0; i < db_count; i++) {
+               struct buffer_head *bh;
+
                block = descriptor_loc(sb, logical_sb_block, i);
-               sbi->s_group_desc[i] = sb_bread_unmovable(sb, block);
-               if (!sbi->s_group_desc[i]) {
+               bh = sb_bread_unmovable(sb, block);
+               if (!bh) {
                        ext4_msg(sb, KERN_ERR,
                               "can't read group descriptor %d", i);
                        db_count = i;
                        goto failed_mount2;
                }
+               rcu_read_lock();
+               rcu_dereference(sbi->s_group_desc)[i] = bh;
+               rcu_read_unlock();
        }
        sbi->s_gdb_count = db_count;
        if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
@@ -4594,7 +4626,7 @@ no_journal:
                err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
                                          GFP_KERNEL);
        if (!err)
-               err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem);
+               err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
 
        if (err) {
                ext4_msg(sb, KERN_ERR, "insufficient memory");
@@ -4682,13 +4714,19 @@ failed_mount7:
        ext4_unregister_li_request(sb);
 failed_mount6:
        ext4_mb_release(sb);
-       if (sbi->s_flex_groups)
-               kvfree(sbi->s_flex_groups);
+       rcu_read_lock();
+       flex_groups = rcu_dereference(sbi->s_flex_groups);
+       if (flex_groups) {
+               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
+                       kvfree(flex_groups[i]);
+               kvfree(flex_groups);
+       }
+       rcu_read_unlock();
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
+       percpu_free_rwsem(&sbi->s_writepages_rwsem);
 failed_mount5:
        ext4_ext_release(sb);
        ext4_release_system_zone(sb);
@@ -4717,9 +4755,12 @@ failed_mount3:
        if (sbi->s_mmp_tsk)
                kthread_stop(sbi->s_mmp_tsk);
 failed_mount2:
+       rcu_read_lock();
+       group_desc = rcu_dereference(sbi->s_group_desc);
        for (i = 0; i < db_count; i++)
-               brelse(sbi->s_group_desc[i]);
-       kvfree(sbi->s_group_desc);
+               brelse(group_desc[i]);
+       kvfree(group_desc);
+       rcu_read_unlock();
 failed_mount:
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
index 5a82601..de650df 100644 (file)
@@ -1260,6 +1260,9 @@ static void __io_req_aux_free(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
 
+       if (req->flags & REQ_F_NEED_CLEANUP)
+               io_cleanup_req(req);
+
        kfree(req->io);
        if (req->file) {
                if (req->flags & REQ_F_FIXED_FILE)
@@ -1275,9 +1278,6 @@ static void __io_free_req(struct io_kiocb *req)
 {
        __io_req_aux_free(req);
 
-       if (req->flags & REQ_F_NEED_CLEANUP)
-               io_cleanup_req(req);
-
        if (req->flags & REQ_F_INFLIGHT) {
                struct io_ring_ctx *ctx = req->ctx;
                unsigned long flags;
@@ -1672,11 +1672,17 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 }
 
-static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                           long min)
+static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
+                          long min)
 {
        int iters = 0, ret = 0;
 
+       /*
+        * We disallow the app entering submit/complete with polling, but we
+        * still need to lock the ring to prevent racing with polled issue
+        * that got punted to a workqueue.
+        */
+       mutex_lock(&ctx->uring_lock);
        do {
                int tmin = 0;
 
@@ -1712,21 +1718,6 @@ static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                ret = 0;
        } while (min && !*nr_events && !need_resched());
 
-       return ret;
-}
-
-static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                          long min)
-{
-       int ret;
-
-       /*
-        * We disallow the app entering submit/complete with polling, but we
-        * still need to lock the ring to prevent racing with polled issue
-        * that got punted to a workqueue.
-        */
-       mutex_lock(&ctx->uring_lock);
-       ret = __io_iopoll_check(ctx, nr_events, min);
        mutex_unlock(&ctx->uring_lock);
        return ret;
 }
@@ -2517,6 +2508,9 @@ static void io_fallocate_finish(struct io_wq_work **workptr)
        struct io_kiocb *nxt = NULL;
        int ret;
 
+       if (io_req_cancelled(req))
+               return;
+
        ret = vfs_fallocate(req->file, req->sync.mode, req->sync.off,
                                req->sync.len);
        if (ret < 0)
@@ -2904,6 +2898,7 @@ static void io_close_finish(struct io_wq_work **workptr)
        struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
        struct io_kiocb *nxt = NULL;
 
+       /* not cancellable, don't do io_req_cancelled() */
        __io_close_finish(req, &nxt);
        if (nxt)
                io_wq_assign_next(workptr, nxt);
@@ -3071,7 +3066,7 @@ static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        if (req->io)
                                return -EAGAIN;
                        if (io_alloc_async_ctx(req)) {
-                               if (kmsg && kmsg->iov != kmsg->fast_iov)
+                               if (kmsg->iov != kmsg->fast_iov)
                                        kfree(kmsg->iov);
                                return -ENOMEM;
                        }
@@ -3225,7 +3220,7 @@ static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        if (req->io)
                                return -EAGAIN;
                        if (io_alloc_async_ctx(req)) {
-                               if (kmsg && kmsg->iov != kmsg->fast_iov)
+                               if (kmsg->iov != kmsg->fast_iov)
                                        kfree(kmsg->iov);
                                return -ENOMEM;
                        }
@@ -5114,7 +5109,7 @@ static int io_sq_thread(void *data)
                                 */
                                mutex_lock(&ctx->uring_lock);
                                if (!list_empty(&ctx->poll_list))
-                                       __io_iopoll_check(ctx, &nr_events, 0);
+                                       io_iopoll_getevents(ctx, &nr_events, 0);
                                else
                                        inflight = 0;
                                mutex_unlock(&ctx->uring_lock);
@@ -5139,6 +5134,18 @@ static int io_sq_thread(void *data)
                 */
                if (!to_submit || ret == -EBUSY) {
                        /*
+                        * Drop cur_mm before scheduling, we can't hold it for
+                        * long periods (or over schedule()). Do this before
+                        * adding ourselves to the waitqueue, as the unuse/drop
+                        * may sleep.
+                        */
+                       if (cur_mm) {
+                               unuse_mm(cur_mm);
+                               mmput(cur_mm);
+                               cur_mm = NULL;
+                       }
+
+                       /*
                         * We're polling. If we're within the defined idle
                         * period, then let us spin without work before going
                         * to sleep. The exception is if we got EBUSY doing
@@ -5152,18 +5159,6 @@ static int io_sq_thread(void *data)
                                continue;
                        }
 
-                       /*
-                        * Drop cur_mm before scheduling, we can't hold it for
-                        * long periods (or over schedule()). Do this before
-                        * adding ourselves to the waitqueue, as the unuse/drop
-                        * may sleep.
-                        */
-                       if (cur_mm) {
-                               unuse_mm(cur_mm);
-                               mmput(cur_mm);
-                               cur_mm = NULL;
-                       }
-
                        prepare_to_wait(&ctx->sqo_wait, &wait,
                                                TASK_INTERRUPTIBLE);
 
index 2dd848a..d181948 100644 (file)
@@ -936,8 +936,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
        char *frozen_buffer = NULL;
        unsigned long start_lock, time_lock;
 
-       if (is_handle_aborted(handle))
-               return -EROFS;
        journal = transaction->t_journal;
 
        jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
@@ -1189,6 +1187,9 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
        struct journal_head *jh;
        int rc;
 
+       if (is_handle_aborted(handle))
+               return -EROFS;
+
        if (jbd2_write_access_granted(handle, bh, false))
                return 0;
 
@@ -1326,6 +1327,9 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
        struct journal_head *jh;
        char *committed_data = NULL;
 
+       if (is_handle_aborted(handle))
+               return -EROFS;
+
        if (jbd2_write_access_granted(handle, bh, true))
                return 0;
 
index 7e18c93..d11e183 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+#define BOOTCONFIG_MAGIC       "#BOOTCONFIG\n"
+#define BOOTCONFIG_MAGIC_LEN   12
+
 /* XBC tree node */
 struct xbc_node {
        u16 next;
index cd41f20..875f711 100644 (file)
@@ -492,7 +492,7 @@ struct hid_report_enum {
 };
 
 #define HID_MIN_BUFFER_SIZE    64              /* make sure there is at least a packet size of space */
-#define HID_MAX_BUFFER_SIZE    4096            /* 4kb */
+#define HID_MAX_BUFFER_SIZE    8192            /* 8kb */
 #define HID_CONTROL_FIFO_SIZE  256             /* to init devices with >100 reports */
 #define HID_OUTPUT_FIFO_SIZE   64
 
index b2d4757..8d062e8 100644 (file)
@@ -192,7 +192,7 @@ enum {
        IRQ_DOMAIN_FLAG_HIERARCHY       = (1 << 0),
 
        /* Irq domain name was allocated in __irq_domain_add() */
-       IRQ_DOMAIN_NAME_ALLOCATED       = (1 << 6),
+       IRQ_DOMAIN_NAME_ALLOCATED       = (1 << 1),
 
        /* Irq domain is an IPI domain with virq per cpu */
        IRQ_DOMAIN_FLAG_IPI_PER_CPU     = (1 << 2),
index e89eb67..7944ad6 100644 (file)
@@ -889,6 +889,8 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
+int kvm_arch_post_init_vm(struct kvm *kvm);
+void kvm_arch_pre_destroy_vm(struct kvm *kvm);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 /*
index 533f567..b71b5c4 100644 (file)
@@ -627,7 +627,6 @@ struct iscsi_reject {
 #define ISCSI_REASON_BOOKMARK_INVALID  9
 #define ISCSI_REASON_BOOKMARK_NO_RESOURCES     10
 #define ISCSI_REASON_NEGOTIATION_RESET 11
-#define ISCSI_REASON_WAITING_FOR_LOGOUT        12
 
 /* Max. number of Key=Value pairs in a text message */
 #define MAX_KEY_VALUE_PAIRS    8192
index 452bc18..20a6ac3 100644 (file)
@@ -1226,13 +1226,12 @@ endif
 
 config BOOT_CONFIG
        bool "Boot config support"
-       depends on BLK_DEV_INITRD
-       default y
+       select BLK_DEV_INITRD
        help
          Extra boot config allows system admin to pass a config file as
          complemental extension of kernel cmdline when booting.
          The boot config file must be attached at the end of initramfs
-         with checksum and size.
+         with checksum, size and magic word.
          See <file:Documentation/admin-guide/bootconfig.rst> for details.
 
          If unsure, say Y.
index f95b014..ee4947a 100644 (file)
@@ -268,7 +268,6 @@ static int __init xbc_snprint_cmdline(char *buf, size_t size,
 {
        struct xbc_node *knode, *vnode;
        char *end = buf + size;
-       char c = '\"';
        const char *val;
        int ret;
 
@@ -279,25 +278,20 @@ static int __init xbc_snprint_cmdline(char *buf, size_t size,
                        return ret;
 
                vnode = xbc_node_get_child(knode);
-               ret = snprintf(buf, rest(buf, end), "%s%c", xbc_namebuf,
-                               vnode ? '=' : ' ');
-               if (ret < 0)
-                       return ret;
-               buf += ret;
-               if (!vnode)
+               if (!vnode) {
+                       ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
+                       if (ret < 0)
+                               return ret;
+                       buf += ret;
                        continue;
-
-               c = '\"';
+               }
                xbc_array_for_each_value(vnode, val) {
-                       ret = snprintf(buf, rest(buf, end), "%c%s", c, val);
+                       ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ",
+                                      xbc_namebuf, val);
                        if (ret < 0)
                                return ret;
                        buf += ret;
-                       c = ',';
                }
-               if (rest(buf, end) > 2)
-                       strcpy(buf, "\" ");
-               buf += 2;
        }
 
        return buf - (end - size);
@@ -335,7 +329,7 @@ static char * __init xbc_make_cmdline(const char *key)
        return new_cmdline;
 }
 
-u32 boot_config_checksum(unsigned char *p, u32 size)
+static u32 boot_config_checksum(unsigned char *p, u32 size)
 {
        u32 ret = 0;
 
@@ -374,7 +368,11 @@ static void __init setup_boot_config(const char *cmdline)
        if (!initrd_end)
                goto not_found;
 
-       hdr = (u32 *)(initrd_end - 8);
+       data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
+       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
+               goto not_found;
+
+       hdr = (u32 *)(data - 8);
        size = hdr[0];
        csum = hdr[1];
 
@@ -418,6 +416,14 @@ not_found:
 }
 #else
 #define setup_boot_config(cmdline)     do { } while (0)
+
+static int __init warn_bootconfig(char *str)
+{
+       pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOTCONFIG is not set.\n");
+       return 0;
+}
+early_param("bootconfig", warn_bootconfig);
+
 #endif
 
 /* Change NUL term back to "=", to make "param" the whole string. */
index 17b0d52..9ddfe2a 100644 (file)
@@ -1101,13 +1101,11 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
        audit_log_end(ab);
 }
 
-static int audit_set_feature(struct sk_buff *skb)
+static int audit_set_feature(struct audit_features *uaf)
 {
-       struct audit_features *uaf;
        int i;
 
        BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > ARRAY_SIZE(audit_feature_names));
-       uaf = nlmsg_data(nlmsg_hdr(skb));
 
        /* if there is ever a version 2 we should handle that here */
 
@@ -1175,6 +1173,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
        u32                     seq;
        void                    *data;
+       int                     data_len;
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
@@ -1188,6 +1187,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
        seq  = nlh->nlmsg_seq;
        data = nlmsg_data(nlh);
+       data_len = nlmsg_len(nlh);
 
        switch (msg_type) {
        case AUDIT_GET: {
@@ -1211,7 +1211,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                struct audit_status     s;
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
                if (s.mask & AUDIT_STATUS_ENABLED) {
                        err = audit_set_enabled(s.enabled);
                        if (err < 0)
@@ -1315,7 +1315,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return err;
                break;
        case AUDIT_SET_FEATURE:
-               err = audit_set_feature(skb);
+               if (data_len < sizeof(struct audit_features))
+                       return -EINVAL;
+               err = audit_set_feature(data);
                if (err)
                        return err;
                break;
@@ -1327,6 +1329,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                err = audit_filter(msg_type, AUDIT_FILTER_USER);
                if (err == 1) { /* match or error */
+                       char *str = data;
+
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
                                err = tty_audit_push();
@@ -1334,26 +1338,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                        break;
                        }
                        audit_log_user_recv_msg(&ab, msg_type);
-                       if (msg_type != AUDIT_USER_TTY)
+                       if (msg_type != AUDIT_USER_TTY) {
+                               /* ensure NULL termination */
+                               str[data_len - 1] = '\0';
                                audit_log_format(ab, " msg='%.*s'",
                                                 AUDIT_MESSAGE_TEXT_MAX,
-                                                (char *)data);
-                       else {
-                               int size;
-
+                                                str);
+                       } else {
                                audit_log_format(ab, " data=");
-                               size = nlmsg_len(nlh);
-                               if (size > 0 &&
-                                   ((unsigned char *)data)[size - 1] == '\0')
-                                       size--;
-                               audit_log_n_untrustedstring(ab, data, size);
+                               if (data_len > 0 && str[data_len - 1] == '\0')
+                                       data_len--;
+                               audit_log_n_untrustedstring(ab, str, data_len);
                        }
                        audit_log_end(ab);
                }
                break;
        case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
-               if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
+               if (data_len < sizeof(struct audit_rule_data))
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
                        audit_log_common_recv_msg(audit_context(), &ab,
@@ -1365,7 +1367,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        audit_log_end(ab);
                        return -EPERM;
                }
-               err = audit_rule_change(msg_type, seq, data, nlmsg_len(nlh));
+               err = audit_rule_change(msg_type, seq, data, data_len);
                break;
        case AUDIT_LIST_RULES:
                err = audit_list_rules_send(skb, seq);
@@ -1380,7 +1382,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_MAKE_EQUIV: {
                void *bufp = data;
                u32 sizes[2];
-               size_t msglen = nlmsg_len(nlh);
+               size_t msglen = data_len;
                char *old, *new;
 
                err = -EINVAL;
@@ -1456,7 +1458,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
                /* check if new data is valid */
                if ((s.enabled != 0 && s.enabled != 1) ||
                    (s.log_passwd != 0 && s.log_passwd != 1))
index b0126e9..026e34d 100644 (file)
@@ -456,6 +456,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
        bufp = data->buf;
        for (i = 0; i < data->field_count; i++) {
                struct audit_field *f = &entry->rule.fields[i];
+               u32 f_val;
 
                err = -EINVAL;
 
@@ -464,12 +465,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        goto exit_free;
 
                f->type = data->fields[i];
-               f->val = data->values[i];
+               f_val = data->values[i];
 
                /* Support legacy tests for a valid loginuid */
-               if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
+               if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) {
                        f->type = AUDIT_LOGINUID_SET;
-                       f->val = 0;
+                       f_val = 0;
                        entry->rule.pflags |= AUDIT_LOGINUID_LEGACY;
                }
 
@@ -485,7 +486,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SUID:
                case AUDIT_FSUID:
                case AUDIT_OBJ_UID:
-                       f->uid = make_kuid(current_user_ns(), f->val);
+                       f->uid = make_kuid(current_user_ns(), f_val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
                        break;
@@ -494,11 +495,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SGID:
                case AUDIT_FSGID:
                case AUDIT_OBJ_GID:
-                       f->gid = make_kgid(current_user_ns(), f->val);
+                       f->gid = make_kgid(current_user_ns(), f_val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
                case AUDIT_ARCH:
+                       f->val = f_val;
                        entry->rule.arch_f = f;
                        break;
                case AUDIT_SUBJ_USER:
@@ -511,11 +513,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_OBJ_TYPE:
                case AUDIT_OBJ_LEV_LOW:
                case AUDIT_OBJ_LEV_HIGH:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
+                       }
+                       entry->rule.buflen += f_val;
+                       f->lsm_str = str;
                        err = security_audit_rule_init(f->type, f->op, str,
                                                       (void **)&f->lsm_rule);
                        /* Keep currently invalid fields around in case they
@@ -524,68 +528,71 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                pr_warn("audit rule for LSM \'%s\' is invalid\n",
                                        str);
                                err = 0;
-                       }
-                       if (err) {
-                               kfree(str);
+                       } else if (err)
                                goto exit_free;
-                       } else
-                               f->lsm_str = str;
                        break;
                case AUDIT_WATCH:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
-                       err = audit_to_watch(&entry->rule, str, f->val, f->op);
+                       }
+                       err = audit_to_watch(&entry->rule, str, f_val, f->op);
                        if (err) {
                                kfree(str);
                                goto exit_free;
                        }
+                       entry->rule.buflen += f_val;
                        break;
                case AUDIT_DIR:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
+                       }
                        err = audit_make_tree(&entry->rule, str, f->op);
                        kfree(str);
                        if (err)
                                goto exit_free;
+                       entry->rule.buflen += f_val;
                        break;
                case AUDIT_INODE:
+                       f->val = f_val;
                        err = audit_to_inode(&entry->rule, f);
                        if (err)
                                goto exit_free;
                        break;
                case AUDIT_FILTERKEY:
-                       if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
+                       if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN)
                                goto exit_free;
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
+                       }
+                       entry->rule.buflen += f_val;
                        entry->rule.filterkey = str;
                        break;
                case AUDIT_EXE:
-                       if (entry->rule.exe || f->val > PATH_MAX)
+                       if (entry->rule.exe || f_val > PATH_MAX)
                                goto exit_free;
-                       str = audit_unpack_string(&bufp, &remain, f->val);
+                       str = audit_unpack_string(&bufp, &remain, f_val);
                        if (IS_ERR(str)) {
                                err = PTR_ERR(str);
                                goto exit_free;
                        }
-                       entry->rule.buflen += f->val;
-
-                       audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
+                       audit_mark = audit_alloc_mark(&entry->rule, str, f_val);
                        if (IS_ERR(audit_mark)) {
                                kfree(str);
                                err = PTR_ERR(audit_mark);
                                goto exit_free;
                        }
+                       entry->rule.buflen += f_val;
                        entry->rule.exe = audit_mark;
                        break;
+               default:
+                       f->val = f_val;
+                       break;
                }
        }
 
index 3924fbe..c9d8eb7 100644 (file)
@@ -128,8 +128,6 @@ static inline void unregister_handler_proc(unsigned int irq,
 
 extern bool irq_can_set_affinity_usr(unsigned int irq);
 
-extern int irq_select_affinity_usr(unsigned int irq);
-
 extern void irq_set_thread_affinity(struct irq_desc *desc);
 
 extern int irq_do_set_affinity(struct irq_data *data,
index 3089a60..7eee98c 100644 (file)
@@ -481,23 +481,9 @@ int irq_setup_affinity(struct irq_desc *desc)
 {
        return irq_select_affinity(irq_desc_get_irq(desc));
 }
-#endif
+#endif /* CONFIG_AUTO_IRQ_AFFINITY */
+#endif /* CONFIG_SMP */
 
-/*
- * Called when a bogus affinity is set via /proc/irq
- */
-int irq_select_affinity_usr(unsigned int irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       unsigned long flags;
-       int ret;
-
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       ret = irq_setup_affinity(desc);
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-       return ret;
-}
-#endif
 
 /**
  *     irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
index 9e5783d..32c071d 100644 (file)
@@ -111,6 +111,28 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
        return show_irq_affinity(AFFINITY_LIST, m);
 }
 
+#ifndef CONFIG_AUTO_IRQ_AFFINITY
+static inline int irq_select_affinity_usr(unsigned int irq)
+{
+       /*
+        * If the interrupt is started up already then this fails. The
+        * interrupt is assigned to an online CPU already. There is no
+        * point to move it around randomly. Tell user space that the
+        * selected mask is bogus.
+        *
+        * If not then any change to the affinity is pointless because the
+        * startup code invokes irq_setup_affinity() which will select
+        * a online CPU anyway.
+        */
+       return -EINVAL;
+}
+#else
+/* ALPHA magic affinity auto selector. Keep it for historical reasons. */
+static inline int irq_select_affinity_usr(unsigned int irq)
+{
+       return irq_select_affinity(irq);
+}
+#endif
 
 static ssize_t write_irq_affinity(int type, struct file *file,
                const char __user *buffer, size_t count, loff_t *pos)
index 9ad8dea..5b23963 100644 (file)
@@ -413,27 +413,32 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
 {
        struct sigqueue *q = NULL;
        struct user_struct *user;
+       int sigpending;
 
        /*
         * Protect access to @t credentials. This can go away when all
         * callers hold rcu read lock.
+        *
+        * NOTE! A pending signal will hold on to the user refcount,
+        * and we get/put the refcount only when the sigpending count
+        * changes from/to zero.
         */
        rcu_read_lock();
-       user = get_uid(__task_cred(t)->user);
-       atomic_inc(&user->sigpending);
+       user = __task_cred(t)->user;
+       sigpending = atomic_inc_return(&user->sigpending);
+       if (sigpending == 1)
+               get_uid(user);
        rcu_read_unlock();
 
-       if (override_rlimit ||
-           atomic_read(&user->sigpending) <=
-                       task_rlimit(t, RLIMIT_SIGPENDING)) {
+       if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) {
                q = kmem_cache_alloc(sigqueue_cachep, flags);
        } else {
                print_dropped_signal(sig);
        }
 
        if (unlikely(q == NULL)) {
-               atomic_dec(&user->sigpending);
-               free_uid(user);
+               if (atomic_dec_and_test(&user->sigpending))
+                       free_uid(user);
        } else {
                INIT_LIST_HEAD(&q->list);
                q->flags = 0;
@@ -447,8 +452,8 @@ static void __sigqueue_free(struct sigqueue *q)
 {
        if (q->flags & SIGQUEUE_PREALLOC)
                return;
-       atomic_dec(&q->user->sigpending);
-       free_uid(q->user);
+       if (atomic_dec_and_test(&q->user->sigpending))
+               free_uid(q->user);
        kmem_cache_free(sigqueue_cachep, q);
 }
 
index d396aaa..ad5b88a 100644 (file)
@@ -805,15 +805,6 @@ static struct ctl_table kern_table[] = {
                .extra2         = &maxolduid,
        },
 #ifdef CONFIG_S390
-#ifdef CONFIG_MATHEMU
-       {
-               .procname       = "ieee_emulation_warnings",
-               .data           = &sysctl_ieee_emulation_warnings,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
-#endif
        {
                .procname       = "userprocess_debug",
                .data           = &show_unhandled_signals,
index 91e8851..402eef8 100644 (file)
@@ -143,8 +143,8 @@ if FTRACE
 
 config BOOTTIME_TRACING
        bool "Boot-time Tracing support"
-       depends on BOOT_CONFIG && TRACING
-       default y
+       depends on TRACING
+       select BOOT_CONFIG
        help
          Enable developer to setup ftrace subsystem via supplemental
          kernel cmdline at boot time for debugging (tracing) driver
index 4aefe00..7d56d62 100644 (file)
@@ -111,11 +111,11 @@ static int __init test_gen_synth_cmd(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"hula hoops";    /* next_comm_field */
+       vals[1] = (u64)(long)"hula hoops";      /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed";        /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed";  /* my_string_field */
        vals[6] = 598;                  /* my_int_field */
 
        /* Now generate a gen_synth_test event */
@@ -218,11 +218,11 @@ static int __init test_empty_synth_event(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"tiddlywinks";   /* next_comm_field */
+       vals[1] = (u64)(long)"tiddlywinks";     /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed_2.0";    /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed_2.0";      /* my_string_field */
        vals[6] = 399;                  /* my_int_field */
 
        /* Now trace an empty_synth_test event */
@@ -290,11 +290,11 @@ static int __init test_create_synth_event(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"tiddlywinks";   /* next_comm_field */
+       vals[1] = (u64)(long)"tiddlywinks";     /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed";        /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed";  /* my_string_field */
        vals[6] = 398;                  /* my_int_field */
 
        /* Now generate a create_synth_test event */
@@ -330,7 +330,7 @@ static int __init test_add_next_synth_val(void)
                goto out;
 
        /* next_comm_field */
-       ret = synth_event_add_next_val((u64)"slinky", &trace_state);
+       ret = synth_event_add_next_val((u64)(long)"slinky", &trace_state);
        if (ret)
                goto out;
 
@@ -345,12 +345,12 @@ static int __init test_add_next_synth_val(void)
                goto out;
 
        /* cpu */
-       ret = synth_event_add_next_val(smp_processor_id(), &trace_state);
+       ret = synth_event_add_next_val(raw_smp_processor_id(), &trace_state);
        if (ret)
                goto out;
 
        /* my_string_field */
-       ret = synth_event_add_next_val((u64)"thneed_2.01", &trace_state);
+       ret = synth_event_add_next_val((u64)(long)"thneed_2.01", &trace_state);
        if (ret)
                goto out;
 
@@ -388,7 +388,7 @@ static int __init test_add_synth_val(void)
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("cpu", smp_processor_id(), &trace_state);
+       ret = synth_event_add_val("cpu", raw_smp_processor_id(), &trace_state);
        if (ret)
                goto out;
 
@@ -396,12 +396,12 @@ static int __init test_add_synth_val(void)
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("next_comm_field", (u64)"silly putty",
+       ret = synth_event_add_val("next_comm_field", (u64)(long)"silly putty",
                                  &trace_state);
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("my_string_field", (u64)"thneed_9",
+       ret = synth_event_add_val("my_string_field", (u64)(long)"thneed_9",
                                  &trace_state);
        if (ret)
                goto out;
@@ -423,13 +423,13 @@ static int __init test_trace_synth_event(void)
 
        /* Trace some bogus values just for testing */
        ret = synth_event_trace(create_synth_test, 7,   /* number of values */
-                               444,                    /* next_pid_field */
-                               (u64)"clackers",        /* next_comm_field */
-                               1000000,                /* ts_ns */
-                               1000,                   /* ts_ms */
-                               smp_processor_id(),     /* cpu */
-                               (u64)"Thneed",          /* my_string_field */
-                               999);                   /* my_int_field */
+                               (u64)444,               /* next_pid_field */
+                               (u64)(long)"clackers",  /* next_comm_field */
+                               (u64)1000000,           /* ts_ns */
+                               (u64)1000,              /* ts_ms */
+                               (u64)raw_smp_processor_id(), /* cpu */
+                               (u64)(long)"Thneed",    /* my_string_field */
+                               (u64)999);              /* my_int_field */
        return ret;
 }
 
index c797a15..6b11e4e 100644 (file)
@@ -1837,6 +1837,7 @@ static __init int init_trace_selftests(void)
 
        pr_info("Running postponed tracer tests:\n");
 
+       tracing_selftest_running = true;
        list_for_each_entry_safe(p, n, &postponed_selftests, list) {
                /* This loop can take minutes when sanitizers are enabled, so
                 * lets make sure we allow RCU processing.
@@ -1859,6 +1860,7 @@ static __init int init_trace_selftests(void)
                list_del(&p->list);
                kfree(p);
        }
+       tracing_selftest_running = false;
 
  out:
        mutex_unlock(&trace_types_lock);
index 483b3fd..5f6834a 100644 (file)
@@ -821,6 +821,29 @@ static const char *synth_field_fmt(char *type)
        return fmt;
 }
 
+static void print_synth_event_num_val(struct trace_seq *s,
+                                     char *print_fmt, char *name,
+                                     int size, u64 val, char *space)
+{
+       switch (size) {
+       case 1:
+               trace_seq_printf(s, print_fmt, name, (u8)val, space);
+               break;
+
+       case 2:
+               trace_seq_printf(s, print_fmt, name, (u16)val, space);
+               break;
+
+       case 4:
+               trace_seq_printf(s, print_fmt, name, (u32)val, space);
+               break;
+
+       default:
+               trace_seq_printf(s, print_fmt, name, val, space);
+               break;
+       }
+}
+
 static enum print_line_t print_synth_event(struct trace_iterator *iter,
                                           int flags,
                                           struct trace_event *event)
@@ -859,10 +882,13 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter,
                } else {
                        struct trace_print_flags __flags[] = {
                            __def_gfpflag_names, {-1, NULL} };
+                       char *space = (i == se->n_fields - 1 ? "" : " ");
 
-                       trace_seq_printf(s, print_fmt, se->fields[i]->name,
-                                        entry->fields[n_u64],
-                                        i == se->n_fields - 1 ? "" : " ");
+                       print_synth_event_num_val(s, print_fmt,
+                                                 se->fields[i]->name,
+                                                 se->fields[i]->size,
+                                                 entry->fields[n_u64],
+                                                 space);
 
                        if (strcmp(se->fields[i]->type, "gfp_t") == 0) {
                                trace_seq_puts(s, " (");
@@ -1805,6 +1831,8 @@ __synth_event_trace_start(struct trace_event_file *file,
        int entry_size, fields_size = 0;
        int ret = 0;
 
+       memset(trace_state, '\0', sizeof(*trace_state));
+
        /*
         * Normal event tracing doesn't get called at all unless the
         * ENABLED bit is set (which attaches the probe thus allowing
@@ -1885,6 +1913,11 @@ int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
                return ret;
        }
 
+       if (n_vals != state.event->n_fields) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        va_start(args, n_vals);
        for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
                u64 val;
@@ -1898,12 +1931,30 @@ int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       state.entry->fields[n_u64] = val;
+                       struct synth_field *field = state.event->fields[i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&state.entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&state.entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&state.entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               state.entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
        va_end(args);
-
+out:
        __synth_event_trace_end(&state);
 
        return ret;
@@ -1942,6 +1993,11 @@ int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
                return ret;
        }
 
+       if (n_vals != state.event->n_fields) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
                if (state.event->fields[i]->is_string) {
                        char *str_val = (char *)(long)vals[i];
@@ -1950,11 +2006,30 @@ int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       state.entry->fields[n_u64] = vals[i];
+                       struct synth_field *field = state.event->fields[i];
+                       u64 val = vals[i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&state.entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&state.entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&state.entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               state.entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
-
+out:
        __synth_event_trace_end(&state);
 
        return ret;
@@ -1997,8 +2072,6 @@ int synth_event_trace_start(struct trace_event_file *file,
        if (!trace_state)
                return -EINVAL;
 
-       memset(trace_state, '\0', sizeof(*trace_state));
-
        ret = __synth_event_trace_start(file, trace_state);
        if (ret == -ENOENT)
                ret = 0; /* just disabled, not really an error */
@@ -2069,8 +2142,25 @@ static int __synth_event_add_val(const char *field_name, u64 val,
 
                str_field = (char *)&entry->fields[field->offset];
                strscpy(str_field, str_val, STR_VAR_LEN_MAX);
-       } else
-               entry->fields[field->offset] = val;
+       } else {
+               switch (field->size) {
+               case 1:
+                       *(u8 *)&trace_state->entry->fields[field->offset] = (u8)val;
+                       break;
+
+               case 2:
+                       *(u16 *)&trace_state->entry->fields[field->offset] = (u16)val;
+                       break;
+
+               case 4:
+                       *(u32 *)&trace_state->entry->fields[field->offset] = (u32)val;
+                       break;
+
+               default:
+                       trace_state->entry->fields[field->offset] = val;
+                       break;
+               }
+       }
  out:
        return ret;
 }
index 3ea601a..ec3ce7f 100644 (file)
@@ -533,7 +533,7 @@ struct xbc_node *find_match_node(struct xbc_node *node, char *k)
 
 static int __init __xbc_add_key(char *k)
 {
-       struct xbc_node *node;
+       struct xbc_node *node, *child;
 
        if (!xbc_valid_keyword(k))
                return xbc_parse_error("Invalid keyword", k);
@@ -543,8 +543,12 @@ static int __init __xbc_add_key(char *k)
 
        if (!last_parent)       /* the first level */
                node = find_match_node(xbc_nodes, k);
-       else
-               node = find_match_node(xbc_node_get_child(last_parent), k);
+       else {
+               child = xbc_node_get_child(last_parent);
+               if (child && xbc_node_is_value(child))
+                       return xbc_parse_error("Subkey is mixed with value", k);
+               node = find_match_node(child, k);
+       }
 
        if (node)
                last_parent = node;
@@ -574,10 +578,10 @@ static int __init __xbc_parse_keys(char *k)
        return __xbc_add_key(k);
 }
 
-static int __init xbc_parse_kv(char **k, char *v)
+static int __init xbc_parse_kv(char **k, char *v, int op)
 {
        struct xbc_node *prev_parent = last_parent;
-       struct xbc_node *node;
+       struct xbc_node *child;
        char *next;
        int c, ret;
 
@@ -585,12 +589,19 @@ static int __init xbc_parse_kv(char **k, char *v)
        if (ret)
                return ret;
 
+       child = xbc_node_get_child(last_parent);
+       if (child) {
+               if (xbc_node_is_key(child))
+                       return xbc_parse_error("Value is mixed with subkey", v);
+               else if (op == '=')
+                       return xbc_parse_error("Value is redefined", v);
+       }
+
        c = __xbc_parse_value(&v, &next);
        if (c < 0)
                return c;
 
-       node = xbc_add_sibling(v, XBC_VALUE);
-       if (!node)
+       if (!xbc_add_sibling(v, XBC_VALUE))
                return -ENOMEM;
 
        if (c == ',') { /* Array */
@@ -763,7 +774,7 @@ int __init xbc_init(char *buf)
 
        p = buf;
        do {
-               q = strpbrk(p, "{}=;\n#");
+               q = strpbrk(p, "{}=+;\n#");
                if (!q) {
                        p = skip_spaces(p);
                        if (*p != '\0')
@@ -774,8 +785,15 @@ int __init xbc_init(char *buf)
                c = *q;
                *q++ = '\0';
                switch (c) {
+               case '+':
+                       if (*q++ != '=') {
+                               ret = xbc_parse_error("Wrong '+' operator",
+                                                       q - 2);
+                               break;
+                       }
+                       /* Fall through */
                case '=':
-                       ret = xbc_parse_kv(&p, q);
+                       ret = xbc_parse_kv(&p, q, c);
                        break;
                case '{':
                        ret = xbc_open_brace(&p, q);
index 6d83caf..ad0699c 100644 (file)
@@ -235,6 +235,9 @@ bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
                __le64 lens[2];
        } b __aligned(16);
 
+       if (WARN_ON(src_len > INT_MAX))
+               return false;
+
        chacha_load_key(b.k, key);
 
        b.iv[0] = 0;
index 6756b8b..d681a20 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -195,8 +195,6 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
        bool downgraded = false;
        LIST_HEAD(uf);
 
-       brk = untagged_addr(brk);
-
        if (down_write_killable(&mm->mmap_sem))
                return -EINTR;
 
@@ -1557,8 +1555,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
        struct file *file = NULL;
        unsigned long retval;
 
-       addr = untagged_addr(addr);
-
        if (!(flags & MAP_ANONYMOUS)) {
                audit_mmap_fd(fd, flags);
                file = fget(fd);
index 122938d..af36306 100644 (file)
@@ -607,7 +607,6 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
        LIST_HEAD(uf_unmap);
 
        addr = untagged_addr(addr);
-       new_addr = untagged_addr(new_addr);
 
        if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
                return ret;
index c8f7540..aad3ba7 100644 (file)
@@ -3386,8 +3386,6 @@ static const struct constant_table shmem_param_enums_huge[] = {
        {"always",      SHMEM_HUGE_ALWAYS },
        {"within_size", SHMEM_HUGE_WITHIN_SIZE },
        {"advise",      SHMEM_HUGE_ADVISE },
-       {"deny",        SHMEM_HUGE_DENY },
-       {"force",       SHMEM_HUGE_FORCE },
        {}
 };
 
index bae6254..752ff0a 100644 (file)
@@ -300,15 +300,15 @@ DT_BINDING_DIR := Documentation/devicetree/bindings
 DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml
 
 quiet_cmd_dtb_check =  CHECK   $@
-      cmd_dtb_check =  $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ ;
+      cmd_dtb_check =  $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
 
-define rule_dtc_dt_yaml
+define rule_dtc
        $(call cmd_and_fixdep,dtc,yaml)
        $(call cmd,dtb_check)
 endef
 
 $(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
-       $(call if_changed_rule,dtc_dt_yaml)
+       $(call if_changed_rule,dtc)
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
 
index e978a63..036e667 100644 (file)
@@ -4,10 +4,7 @@
 
 #include <stdio.h>
 
-/* controllable printf */
-extern int pr_output;
-#define printk(fmt, ...)       \
-       (pr_output ? printf(fmt, ##__VA_ARGS__) : 0)
+#define printk(fmt, ...) printf(fmt, ##__VA_ARGS__)
 
 #define pr_err printk
 #define pr_warn        printk
index e18eeb0..a9b9781 100644 (file)
@@ -14,8 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/bootconfig.h>
 
-int pr_output = 1;
-
 static int xbc_show_array(struct xbc_node *node)
 {
        const char *val;
@@ -131,15 +129,26 @@ int load_xbc_from_initrd(int fd, char **buf)
        struct stat stat;
        int ret;
        u32 size = 0, csum = 0, rcsum;
+       char magic[BOOTCONFIG_MAGIC_LEN];
 
        ret = fstat(fd, &stat);
        if (ret < 0)
                return -errno;
 
-       if (stat.st_size < 8)
+       if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
+               return 0;
+
+       if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
+               pr_err("Failed to lseek: %d\n", -errno);
+               return -errno;
+       }
+       if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
+               return -errno;
+       /* Check the bootconfig magic bytes */
+       if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
                return 0;
 
-       if (lseek(fd, -8, SEEK_END) < 0) {
+       if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
                pr_err("Failed to lseek: %d\n", -errno);
                return -errno;
        }
@@ -150,11 +159,14 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (read(fd, &csum, sizeof(u32)) < 0)
                return -errno;
 
-       /* Wrong size, maybe no boot config here */
-       if (stat.st_size < size + 8)
-               return 0;
+       /* Wrong size error  */
+       if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
+               pr_err("bootconfig size is too big\n");
+               return -E2BIG;
+       }
 
-       if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) {
+       if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
+                 SEEK_SET) < 0) {
                pr_err("Failed to lseek: %d\n", -errno);
                return -errno;
        }
@@ -163,17 +175,17 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (ret < 0)
                return ret;
 
-       /* Wrong Checksum, maybe no boot config here */
+       /* Wrong Checksum */
        rcsum = checksum((unsigned char *)*buf, size);
        if (csum != rcsum) {
                pr_err("checksum error: %d != %d\n", csum, rcsum);
-               return 0;
+               return -EINVAL;
        }
 
        ret = xbc_init(*buf);
-       /* Wrong data, maybe no boot config here */
+       /* Wrong data */
        if (ret < 0)
-               return 0;
+               return ret;
 
        return size;
 }
@@ -213,20 +225,15 @@ int delete_xbc(const char *path)
                return -errno;
        }
 
-       /*
-        * Suppress error messages in xbc_init() because it can be just a
-        * data which concidentally matches the size and checksum footer.
-        */
-       pr_output = 0;
        size = load_xbc_from_initrd(fd, &buf);
-       pr_output = 1;
        if (size < 0) {
                ret = size;
                pr_err("Failed to load a boot config from initrd: %d\n", ret);
        } else if (size > 0) {
                ret = fstat(fd, &stat);
                if (!ret)
-                       ret = ftruncate(fd, stat.st_size - size - 8);
+                       ret = ftruncate(fd, stat.st_size
+                                       - size - 8 - BOOTCONFIG_MAGIC_LEN);
                if (ret)
                        ret = -errno;
        } /* Ignore if there is no boot config in initrd */
@@ -295,6 +302,12 @@ int apply_xbc(const char *path, const char *xbc_path)
                pr_err("Failed to apply a boot config: %d\n", ret);
                return ret;
        }
+       /* Write a magic word of the bootconfig */
+       ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
+       if (ret < 0) {
+               pr_err("Failed to apply a boot config magic: %d\n", ret);
+               return ret;
+       }
        close(fd);
        free(data);
 
diff --git a/tools/bootconfig/samples/bad-mixed-kv1.bconf b/tools/bootconfig/samples/bad-mixed-kv1.bconf
new file mode 100644 (file)
index 0000000..1761547
--- /dev/null
@@ -0,0 +1,3 @@
+# value -> subkey pattern
+key = value
+key.subkey = another-value
diff --git a/tools/bootconfig/samples/bad-mixed-kv2.bconf b/tools/bootconfig/samples/bad-mixed-kv2.bconf
new file mode 100644 (file)
index 0000000..6b32e0c
--- /dev/null
@@ -0,0 +1,3 @@
+# subkey -> value pattern
+key.subkey = value
+key = another-value
diff --git a/tools/bootconfig/samples/bad-samekey.bconf b/tools/bootconfig/samples/bad-samekey.bconf
new file mode 100644 (file)
index 0000000..e8d983a
--- /dev/null
@@ -0,0 +1,6 @@
+# Same key value is not allowed
+key {
+       foo = value
+       bar = value2
+}
+key.foo = value
index 1de06de..1411f4c 100755 (executable)
@@ -9,7 +9,7 @@ TEMPCONF=`mktemp temp-XXXX.bconf`
 NG=0
 
 cleanup() {
-  rm -f $INITRD $TEMPCONF
+  rm -f $INITRD $TEMPCONF $OUTFILE
   exit $NG
 }
 
@@ -49,7 +49,7 @@ xpass $BOOTCONF -a $TEMPCONF $INITRD
 new_size=$(stat -c %s $INITRD)
 
 echo "File size check"
-xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9)
+xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
 
 echo "Apply command repeat test"
 xpass $BOOTCONF -a $TEMPCONF $INITRD
@@ -71,7 +71,6 @@ printf " \0\0\0 \0\0\0" >> $INITRD
 $BOOTCONF -a $TEMPCONF $INITRD > $OUTFILE 2>&1
 xfail grep -i "failed" $OUTFILE
 xfail grep -i "error" $OUTFILE
-rm $OUTFILE
 
 echo "Max node number check"
 
@@ -96,6 +95,19 @@ truncate -s 32764 $TEMPCONF
 echo "\"" >> $TEMPCONF # add 2 bytes + terminal ('\"\n\0')
 xpass $BOOTCONF -a $TEMPCONF $INITRD
 
+echo "Adding same-key values"
+cat > $TEMPCONF << EOF
+key = bar, baz
+key += qux
+EOF
+echo > $INITRD
+
+xpass $BOOTCONF -a $TEMPCONF $INITRD
+$BOOTCONF $INITRD > $OUTFILE
+xpass grep -q "bar" $OUTFILE
+xpass grep -q "baz" $OUTFILE
+xpass grep -q "qux" $OUTFILE
+
 echo "=== expected failure cases ==="
 for i in samples/bad-* ; do
   xfail $BOOTCONF -a $i $INITRD
index e59eb9e..180ad1e 100755 (executable)
@@ -24,6 +24,8 @@ KunitResult = namedtuple('KunitResult', ['status','result'])
 
 KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig'])
 
+KernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0]
+
 class KunitStatus(Enum):
        SUCCESS = auto()
        CONFIG_FAILURE = auto()
@@ -35,6 +37,13 @@ def create_default_kunitconfig():
                shutil.copyfile('arch/um/configs/kunit_defconfig',
                                kunit_kernel.kunitconfig_path)
 
+def get_kernel_root_path():
+       parts = sys.argv[0] if not __file__ else __file__
+       parts = os.path.realpath(parts).split('tools/testing/kunit')
+       if len(parts) != 2:
+               sys.exit(1)
+       return parts[0]
+
 def run_tests(linux: kunit_kernel.LinuxSourceTree,
              request: KunitRequest) -> KunitResult:
        config_start = time.time()
@@ -114,6 +123,9 @@ def main(argv, linux=None):
        cli_args = parser.parse_args(argv)
 
        if cli_args.subcommand == 'run':
+               if get_kernel_root_path():
+                       os.chdir(get_kernel_root_path())
+
                if cli_args.build_dir:
                        if not os.path.exists(cli_args.build_dir):
                                os.mkdir(cli_args.build_dir)
index cc5d844..d99ae75 100644 (file)
@@ -93,6 +93,20 @@ class LinuxSourceTree(object):
                        return False
                return True
 
+       def validate_config(self, build_dir):
+               kconfig_path = get_kconfig_path(build_dir)
+               validated_kconfig = kunit_config.Kconfig()
+               validated_kconfig.read_from_file(kconfig_path)
+               if not self._kconfig.is_subset_of(validated_kconfig):
+                       invalid = self._kconfig.entries() - validated_kconfig.entries()
+                       message = 'Provided Kconfig is not contained in validated .config. Following fields found in kunitconfig, ' \
+                                         'but not in .config: %s' % (
+                                       ', '.join([str(e) for e in invalid])
+                       )
+                       logging.error(message)
+                       return False
+               return True
+
        def build_config(self, build_dir):
                kconfig_path = get_kconfig_path(build_dir)
                if build_dir and not os.path.exists(build_dir):
@@ -103,12 +117,7 @@ class LinuxSourceTree(object):
                except ConfigError as e:
                        logging.error(e)
                        return False
-               validated_kconfig = kunit_config.Kconfig()
-               validated_kconfig.read_from_file(kconfig_path)
-               if not self._kconfig.is_subset_of(validated_kconfig):
-                       logging.error('Provided Kconfig is not contained in validated .config!')
-                       return False
-               return True
+               return self.validate_config(build_dir)
 
        def build_reconfig(self, build_dir):
                """Creates a new .config if it is not a subset of the .kunitconfig."""
@@ -133,12 +142,7 @@ class LinuxSourceTree(object):
                except (ConfigError, BuildError) as e:
                        logging.error(e)
                        return False
-               used_kconfig = kunit_config.Kconfig()
-               used_kconfig.read_from_file(get_kconfig_path(build_dir))
-               if not self._kconfig.is_subset_of(used_kconfig):
-                       logging.error('Provided Kconfig is not contained in final config!')
-                       return False
-               return True
+               return self.validate_config(build_dir)
 
        def run_kernel(self, args=[], timeout=None, build_dir=''):
                args.extend(['mem=256M'])
index cd1f5b3..d6e106f 100644 (file)
@@ -2,7 +2,7 @@
 all:
 
 TEST_PROGS := ftracetest
-TEST_FILES := test.d
+TEST_FILES := test.d settings
 EXTRA_CLEAN := $(OUTPUT)/logs/*
 
 include ../lib.mk
index 3876d8d..1acc9e1 100644 (file)
@@ -8,4 +8,6 @@ TEST_PROGS := \
        test-state.sh \
        test-ftrace.sh
 
+TEST_FILES := settings
+
 include ../lib.mk
index 93de520..ba450e6 100644 (file)
@@ -8,6 +8,8 @@ TEST_PROGS := mptcp_connect.sh
 
 TEST_GEN_FILES = mptcp_connect
 
+TEST_FILES := settings
+
 EXTRA_CLEAN := *.pcap
 
 include ../../lib.mk
index d646953..2af9d39 100644 (file)
@@ -4,7 +4,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 CLANG_FLAGS += -no-integrated-as
 endif
 
-CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ \
+CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L$(OUTPUT) -Wl,-rpath=./ \
          $(CLANG_FLAGS)
 LDLIBS += -lpthread
 
@@ -19,6 +19,8 @@ TEST_GEN_PROGS_EXTENDED = librseq.so
 
 TEST_PROGS = run_param_test.sh
 
+TEST_FILES := settings
+
 include ../lib.mk
 
 $(OUTPUT)/librseq.so: rseq.c rseq.h rseq-*.h
index 2d93d65..55198ec 100644 (file)
@@ -6,4 +6,6 @@ TEST_GEN_PROGS = rtctest
 
 TEST_GEN_PROGS_EXTENDED = setdate
 
+TEST_FILES := settings
+
 include ../lib.mk