From 000d6cbdcea4c300d772b81e2750c8566b18ce8f Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 14 Nov 2021 18:13:25 +0300 Subject: [PATCH] linux-headers-5.4.0-3.9 --- Makefile | 34 +- arch/e2k/include/asm-l/apicdef.h | 4 +- arch/e2k/include/asm-l/serial.h | 389 +-------- arch/e2k/include/asm/Kbuild | 5 +- arch/e2k/include/asm/aau_context.h | 36 +- arch/e2k/include/asm/aau_regs_access.h | 149 ++-- arch/e2k/include/asm/aau_regs_types.h | 31 +- arch/e2k/include/asm/atomic_api.h | 4 +- arch/e2k/include/asm/barrier.h | 1 - arch/e2k/include/asm/compiler.h | 5 +- arch/e2k/include/asm/copy-hw-stacks.h | 7 +- arch/e2k/include/asm/cpu_features.h | 64 ++ arch/e2k/include/asm/cpu_regs_types.h | 114 +-- arch/e2k/include/asm/e12c.h | 3 - arch/e2k/include/asm/e16c.h | 3 - arch/e2k/include/asm/e1cp.h | 3 - arch/e2k/include/asm/e2c3.h | 3 - arch/e2k/include/asm/e2k.h | 2 + arch/e2k/include/asm/e2k_api.h | 366 ++++++-- arch/e2k/include/asm/e2k_debug.h | 27 +- arch/e2k/include/asm/e2k_ptypes.h | 2 +- arch/e2k/include/asm/e2s.h | 3 - arch/e2k/include/asm/e8c.h | 3 - arch/e2k/include/asm/e8c2.h | 3 - arch/e2k/include/asm/epicdef.h | 4 +- arch/e2k/include/asm/es2.h | 3 - arch/e2k/include/asm/fast_syscalls.h | 242 +++++- arch/e2k/include/asm/fcntl.h | 1 - arch/e2k/include/asm/glob_regs.h | 2 - arch/e2k/include/asm/ioctl.h | 1 - arch/e2k/include/asm/ioctls.h | 17 - arch/e2k/include/asm/ipcbuf.h | 28 - arch/e2k/include/asm/kdebug.h | 11 +- arch/e2k/include/asm/kvm/aau_regs_access.h | 22 +- arch/e2k/include/asm/kvm/copy-hw-stacks.h | 14 +- arch/e2k/include/asm/kvm/gregs.h | 21 + arch/e2k/include/asm/kvm/guest.h | 1 + arch/e2k/include/asm/kvm/guest/aau_context.h | 73 +- arch/e2k/include/asm/kvm/guest/e2k_virt.h | 1 - .../e2k/include/asm/kvm/guest/fast_syscalls.h | 31 +- arch/e2k/include/asm/kvm/guest/mm_hooks.h | 6 +- arch/e2k/include/asm/kvm/guest/mmu_context.h | 3 +- arch/e2k/include/asm/kvm/guest/process.h | 15 +- arch/e2k/include/asm/kvm/guest/switch.h | 10 + arch/e2k/include/asm/kvm/guest/tlbflush.h | 136 +-- arch/e2k/include/asm/kvm/guest/trap_table.h | 13 +- arch/e2k/include/asm/kvm/guest/traps.h | 12 + arch/e2k/include/asm/kvm/gva_cache.h | 180 ++++ arch/e2k/include/asm/kvm/hypercall.h | 28 + arch/e2k/include/asm/kvm/mm.h | 2 + arch/e2k/include/asm/kvm/mm_hooks.h | 3 +- arch/e2k/include/asm/kvm/mmu_exc.h | 20 + arch/e2k/include/asm/kvm/mmu_pte.h | 58 ++ arch/e2k/include/asm/kvm/mmu_regs_access.h | 8 +- arch/e2k/include/asm/kvm/pv-emul.h | 1 - arch/e2k/include/asm/kvm/switch.h | 161 +--- arch/e2k/include/asm/kvm/tlbflush.h | 83 +- arch/e2k/include/asm/kvm/trace_kvm.h | 7 +- arch/e2k/include/asm/kvm/trace_kvm_hv.h | 38 +- arch/e2k/include/asm/kvm/trap_table.S.h | 5 +- arch/e2k/include/asm/kvm_host.h | 11 +- arch/e2k/include/asm/machdep.h | 186 ++-- arch/e2k/include/asm/mas.h | 2 +- arch/e2k/include/asm/mm_hooks.h | 10 +- arch/e2k/include/asm/mman.h | 4 +- arch/e2k/include/asm/mmu-regs-types-v2.h | 5 + arch/e2k/include/asm/mmu-regs-types-v6.h | 5 + arch/e2k/include/asm/mmu_context.h | 3 - arch/e2k/include/asm/mmu_regs.h | 57 +- arch/e2k/include/asm/mmu_regs_types.h | 159 +--- arch/e2k/include/asm/mmu_types.h | 109 ++- arch/e2k/include/asm/msgbuf.h | 27 - arch/e2k/include/asm/native_aau_regs_access.h | 27 +- arch/e2k/include/asm/native_mmu_regs_access.h | 18 +- arch/e2k/include/asm/page_io.h | 2 + arch/e2k/include/asm/param.h | 12 - arch/e2k/include/asm/paravirt/aau_context.h | 12 +- .../include/asm/paravirt/aau_regs_access.h | 12 +- arch/e2k/include/asm/paravirt/mm_hooks.h | 3 +- arch/e2k/include/asm/paravirt/pv_ops.h | 17 +- arch/e2k/include/asm/paravirt/tlbflush.h | 75 +- arch/e2k/include/asm/pgalloc.h | 2 +- arch/e2k/include/asm/pgtable_def.h | 10 +- arch/e2k/include/asm/poll.h | 1 - arch/e2k/include/asm/posix_types.h | 11 - arch/e2k/include/asm/preempt.h | 101 +++ arch/e2k/include/asm/processor.h | 5 +- arch/e2k/include/asm/ptrace.h | 18 +- arch/e2k/include/asm/regs_state.h | 12 +- arch/e2k/include/asm/sembuf.h | 22 - arch/e2k/include/asm/serial.h | 457 +--------- arch/e2k/include/asm/smp.h | 10 +- arch/e2k/include/asm/socket.h | 1 - arch/e2k/include/asm/sockios.h | 1 - arch/e2k/include/asm/statfs.h | 6 - arch/e2k/include/asm/string.h | 113 +-- arch/e2k/include/asm/system.h | 25 +- arch/e2k/include/asm/termbits.h | 6 - arch/e2k/include/asm/termios.h | 6 - arch/e2k/include/asm/thread_info.h | 6 +- arch/e2k/include/asm/tlb-context.h | 791 ------------------ arch/e2k/include/asm/tlb.h | 54 +- arch/e2k/include/asm/tlbflush.h | 186 ++-- arch/e2k/include/asm/trace-defs.h | 1 + arch/e2k/include/asm/trace-mmu-dtlb-v2.h | 2 - arch/e2k/include/asm/trace-mmu-dtlb-v6.h | 2 - arch/e2k/include/asm/trace-tlb-flush.h | 2 +- arch/e2k/include/asm/trace.h | 1 - arch/e2k/include/asm/trap_table.S.h | 31 +- arch/e2k/include/asm/trap_table.h | 21 +- arch/e2k/include/asm/traps.h | 16 + arch/e2k/include/asm/uaccess.h | 3 +- arch/e2k/include/asm/user.h | 6 +- arch/e2k/include/uapi/asm/auxvec.h | 4 - arch/e2k/include/uapi/asm/errno.h | 6 - arch/e2k/include/uapi/asm/fcntl.h | 2 - arch/e2k/include/uapi/asm/ioctl.h | 1 - arch/e2k/include/uapi/asm/ioctls.h | 17 - arch/e2k/include/uapi/asm/ipcbuf.h | 27 - arch/e2k/include/uapi/asm/kvm.h | 2 + arch/e2k/include/uapi/asm/msgbuf.h | 27 - arch/e2k/include/uapi/asm/param.h | 20 - arch/e2k/include/uapi/asm/poll.h | 1 - arch/e2k/include/uapi/asm/posix_types.h | 11 - arch/e2k/include/uapi/asm/sembuf.h | 22 - arch/e2k/include/uapi/asm/setup.h | 6 - arch/e2k/include/uapi/asm/shmbuf.h | 38 - arch/e2k/include/uapi/asm/siginfo.h | 8 - arch/e2k/include/uapi/asm/socket.h | 1 - arch/e2k/include/uapi/asm/sockios.h | 1 - arch/e2k/include/uapi/asm/statfs.h | 6 - arch/e2k/include/uapi/asm/termbits.h | 6 - arch/e2k/include/uapi/asm/termios.h | 6 - include/acpi/acexcep.h | 10 +- include/acpi/acpi_bus.h | 4 +- include/asm-generic/bitops/atomic.h | 6 +- include/asm-generic/sections.h | 3 + include/asm-generic/vmlinux.lds.h | 21 +- include/crypto/acompress.h | 2 + include/crypto/aead.h | 2 + include/crypto/akcipher.h | 2 + include/crypto/cast6.h | 4 +- include/crypto/hash.h | 12 +- include/crypto/internal/hash.h | 8 +- include/crypto/kpp.h | 2 + include/crypto/rng.h | 2 + include/crypto/serpent.h | 4 +- include/crypto/skcipher.h | 2 + include/crypto/xts.h | 2 - include/keys/system_keyring.h | 21 + include/linux/acpi.h | 9 +- include/linux/bio.h | 12 +- include/linux/bpf.h | 12 +- include/linux/bpf_verifier.h | 5 +- include/linux/can/can-ml.h | 12 + include/linux/can/skb.h | 8 +- include/linux/compiler-gcc.h | 6 + include/linux/compiler.h | 53 ++ include/linux/compiler_types.h | 4 + include/linux/console_struct.h | 1 + include/linux/cpuhotplug.h | 1 + include/linux/crypto.h | 9 +- include/linux/device-mapper.h | 5 + include/linux/device.h | 1 + include/linux/eeprom_93xx46.h | 2 + include/linux/efi.h | 6 +- include/linux/elevator.h | 2 +- include/linux/elfcore.h | 28 +- include/linux/extcon.h | 23 + include/linux/filter.h | 2 +- include/linux/fs.h | 1 - include/linux/fs_context.h | 1 + include/linux/hid.h | 5 +- include/linux/huge_mm.h | 27 +- include/linux/hugetlb.h | 20 +- include/linux/i2c.h | 2 + include/linux/icmpv6.h | 48 +- include/linux/if_macvlan.h | 3 +- .../linux/iio/common/cros_ec_sensors_core.h | 2 +- include/linux/inetdevice.h | 2 +- include/linux/intel-iommu.h | 2 + include/linux/iomap.h | 1 + include/linux/ipv6.h | 1 - include/linux/irq.h | 2 + include/linux/kexec.h | 5 + include/linux/key.h | 1 + include/linux/kprobes.h | 2 +- include/linux/kthread.h | 3 + include/linux/kvm_host.h | 14 +- include/linux/marvell_phy.h | 5 +- include/linux/memcontrol.h | 59 +- include/linux/mfd/abx500/ux500_chargalg.h | 2 +- include/linux/mfd/rohm-bd70528.h | 4 +- include/linux/mfd/rt5033-private.h | 4 +- include/linux/mlx4/device.h | 1 + include/linux/mlx5/mlx5_ifc.h | 8 +- include/linux/mlx5/transobj.h | 1 + include/linux/mm.h | 58 +- include/linux/mm_types.h | 4 +- include/linux/mmc/host.h | 3 - include/linux/mmdebug.h | 13 + include/linux/module.h | 26 +- include/linux/msi.h | 8 +- include/linux/mutex.h | 2 +- include/linux/netdev_features.h | 2 +- include/linux/netdevice.h | 39 +- include/linux/netfilter/x_tables.h | 7 +- include/linux/netfilter_arp/arp_tables.h | 5 +- include/linux/netfilter_bridge/ebtables.h | 5 +- include/linux/nfs_fs.h | 1 + include/linux/pagemap.h | 13 +- include/linux/pci_ids.h | 1 + include/linux/platform_data/gpio-omap.h | 3 + include/linux/pm.h | 1 + include/linux/power/bq27xxx_battery.h | 1 - include/linux/prandom.h | 2 +- include/linux/preempt.h | 4 +- include/linux/ptp_clock_kernel.h | 2 +- include/linux/rcupdate.h | 2 + include/linux/rmap.h | 6 +- include/linux/sched/mm.h | 3 +- include/linux/sched/signal.h | 19 +- include/linux/skbuff.h | 5 + include/linux/skmsg.h | 8 +- include/linux/smp.h | 2 +- include/linux/socket.h | 2 - include/linux/spi/spi.h | 3 + include/linux/stop_machine.h | 11 +- include/linux/sunrpc/xdr.h | 3 +- include/linux/swap.h | 1 + include/linux/sysfs.h | 16 + include/linux/tee_drv.h | 2 + include/linux/thread_info.h | 13 + include/linux/tracepoint.h | 10 + include/linux/tty_driver.h | 2 +- include/linux/u64_stats_sync.h | 7 +- include/linux/uio.h | 8 +- include/linux/usb/otg-fsm.h | 1 + include/linux/usb/pd.h | 2 +- include/linux/usb/usbnet.h | 2 + include/linux/usb_usual.h | 2 + include/linux/virtio.h | 1 + include/linux/virtio_net.h | 23 +- include/linux/wait.h | 2 +- include/linux/xarray.h | 22 + include/linux/zsmalloc.h | 2 +- include/media/media-dev-allocator.h | 2 +- include/media/rc-map.h | 7 + include/media/v4l2-subdev.h | 4 + include/net/act_api.h | 1 + include/net/addrconf.h | 1 - include/net/bluetooth/hci_core.h | 2 + include/net/busy_poll.h | 2 +- include/net/caif/caif_dev.h | 2 +- include/net/caif/cfcnfg.h | 2 +- include/net/caif/cfserl.h | 1 + include/net/cfg80211.h | 4 +- include/net/dst_metadata.h | 4 +- include/net/icmp.h | 10 + include/net/inet_connection_sock.h | 5 +- include/net/ip.h | 12 +- include/net/ip6_route.h | 18 +- include/net/llc_pdu.h | 31 +- include/net/net_namespace.h | 7 + include/net/netns/ipv4.h | 2 + include/net/netns/xfrm.h | 4 +- include/net/nexthop.h | 24 + include/net/nfc/nci_core.h | 1 + include/net/page_pool.h | 12 +- include/net/pkt_sched.h | 7 +- include/net/psample.h | 2 + include/net/red.h | 14 +- include/net/rtnetlink.h | 2 + include/net/sch_generic.h | 49 +- include/net/sctp/constants.h | 4 +- include/net/sctp/structs.h | 2 +- include/net/sock.h | 21 +- include/net/tc_act/tc_vlan.h | 1 + include/net/tcp.h | 12 +- include/net/xfrm.h | 3 +- include/scsi/libfcoe.h | 2 +- include/scsi/libiscsi.h | 11 +- include/scsi/scsi_transport_iscsi.h | 2 + include/sound/intel-nhlt.h | 5 + include/target/target_core_backend.h | 1 + include/trace/events/afs.h | 67 +- include/trace/events/writeback.h | 1 - include/uapi/linux/ethtool.h | 4 +- include/uapi/linux/icmpv6.h | 1 + include/uapi/linux/in.h | 3 + include/uapi/linux/input-event-codes.h | 1 + .../uapi/linux/netfilter/nfnetlink_cthelper.h | 2 +- include/uapi/linux/netfilter/xt_SECMARK.h | 6 + include/uapi/linux/tty_flags.h | 4 +- include/uapi/linux/usb/ch9.h | 3 + include/uapi/linux/usb/video.h | 3 +- include/xen/grant_table.h | 1 + include/xen/xenbus.h | 2 - 298 files changed, 3085 insertions(+), 3642 deletions(-) create mode 100644 arch/e2k/include/asm/cpu_features.h delete mode 100644 arch/e2k/include/asm/fcntl.h delete mode 100644 arch/e2k/include/asm/ioctl.h delete mode 100644 arch/e2k/include/asm/ioctls.h delete mode 100644 arch/e2k/include/asm/ipcbuf.h create mode 100644 arch/e2k/include/asm/kvm/gva_cache.h create mode 100644 arch/e2k/include/asm/kvm/mmu_exc.h create mode 100644 arch/e2k/include/asm/kvm/mmu_pte.h delete mode 100644 arch/e2k/include/asm/msgbuf.h delete mode 100644 arch/e2k/include/asm/param.h delete mode 100644 arch/e2k/include/asm/poll.h delete mode 100644 arch/e2k/include/asm/posix_types.h create mode 100644 arch/e2k/include/asm/preempt.h delete mode 100644 arch/e2k/include/asm/sembuf.h delete mode 100644 arch/e2k/include/asm/socket.h delete mode 100644 arch/e2k/include/asm/sockios.h delete mode 100644 arch/e2k/include/asm/statfs.h delete mode 100644 arch/e2k/include/asm/termbits.h delete mode 100644 arch/e2k/include/asm/termios.h delete mode 100644 arch/e2k/include/asm/tlb-context.h delete mode 100644 arch/e2k/include/uapi/asm/auxvec.h delete mode 100644 arch/e2k/include/uapi/asm/errno.h delete mode 100644 arch/e2k/include/uapi/asm/fcntl.h delete mode 100644 arch/e2k/include/uapi/asm/ioctl.h delete mode 100644 arch/e2k/include/uapi/asm/ioctls.h delete mode 100644 arch/e2k/include/uapi/asm/ipcbuf.h delete mode 100644 arch/e2k/include/uapi/asm/msgbuf.h delete mode 100644 arch/e2k/include/uapi/asm/param.h delete mode 100644 arch/e2k/include/uapi/asm/poll.h delete mode 100644 arch/e2k/include/uapi/asm/posix_types.h delete mode 100644 arch/e2k/include/uapi/asm/sembuf.h delete mode 100644 arch/e2k/include/uapi/asm/setup.h delete mode 100644 arch/e2k/include/uapi/asm/shmbuf.h delete mode 100644 arch/e2k/include/uapi/asm/socket.h delete mode 100644 arch/e2k/include/uapi/asm/sockios.h delete mode 100644 arch/e2k/include/uapi/asm/statfs.h delete mode 100644 arch/e2k/include/uapi/asm/termbits.h delete mode 100644 arch/e2k/include/uapi/asm/termios.h diff --git a/Makefile b/Makefile index 08e685c..3520e44 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 4 -SUBLEVEL = 91 -EXTRAVERSION = -3.6 +SUBLEVEL = 143 +EXTRAVERSION = -3.9 NAME = Kleptomaniac Octopus # *DOCUMENTATION* @@ -794,16 +794,16 @@ KBUILD_CFLAGS += -Wno-tautological-compare KBUILD_CFLAGS += -mno-global-merge else -# These warnings generated too much noise in a regular build. -# Use make W=1 to enable them (see scripts/Makefile.extrawarn) -KBUILD_CFLAGS += -Wno-unused-but-set-variable - # Warn about unmarked fall-throughs in switch statement. # Disabled for clang while comment to attribute conversion happens and # https://github.com/ClangBuiltLinux/linux/issues/636 is discussed. KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,) endif +# These warnings generated too much noise in a regular build. +# Use make W=1 to enable them (see scripts/Makefile.extrawarn) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) + KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls @@ -954,12 +954,6 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init) # change __FILE__ to the relative path from the srctree KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) -# ensure -fcf-protection is disabled when using retpoline as it is -# incompatible with -mindirect-branch=thunk-extern -ifdef CONFIG_RETPOLINE -KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) -endif - include scripts/Makefile.kasan include scripts/Makefile.extrawarn include scripts/Makefile.ubsan @@ -977,7 +971,7 @@ LDFLAGS_vmlinux += $(call ld-option, -X,) endif ifeq ($(CONFIG_RELR),y) -LDFLAGS_vmlinux += --pack-dyn-relocs=relr +LDFLAGS_vmlinux += --pack-dyn-relocs=relr --use-android-relr-tags endif # make the checker run with the right architecture @@ -1215,11 +1209,19 @@ define filechk_utsrelease.h endef define filechk_version.h - echo \#define LINUX_VERSION_CODE $(shell \ - expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ - echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' + if [ $(SUBLEVEL) -gt 255 ]; then \ + echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + 255); \ + else \ + echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \ + fi; \ + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + \ + ((c) > 255 ? 255 : (c)))' endef +$(version_h): PATCHLEVEL := $(if $(PATCHLEVEL), $(PATCHLEVEL), 0) +$(version_h): SUBLEVEL := $(if $(SUBLEVEL), $(SUBLEVEL), 0) $(version_h): FORCE $(call filechk,version.h) $(Q)rm -f $(old_version_h) diff --git a/arch/e2k/include/asm-l/apicdef.h b/arch/e2k/include/asm-l/apicdef.h index e9a1165..eb08907 100644 --- a/arch/e2k/include/asm-l/apicdef.h +++ b/arch/e2k/include/asm-l/apicdef.h @@ -8,8 +8,8 @@ * Ingo Molnar , 1999, 2000 */ -#define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000 -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 +#define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000UL +#define APIC_DEFAULT_PHYS_BASE 0xfee00000UL /* * This is the IO-APIC register space as specified diff --git a/arch/e2k/include/asm-l/serial.h b/arch/e2k/include/asm-l/serial.h index 93d673b..c5f7f33 100644 --- a/arch/e2k/include/asm-l/serial.h +++ b/arch/e2k/include/asm-l/serial.h @@ -16,28 +16,13 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif -#ifdef CONFIG_SERIAL_MANY_PORTS -#define FOURPORT_FLAGS ASYNC_FOURPORT -#define ACCENT_FLAGS 0 -#define BOCA_FLAGS 0 -#define HUB6_FLAGS 0 -#define RS_TABLE_SIZE 64 -#else -#define RS_TABLE_SIZE -#endif - -#define NS16550_SERIAL_PORT_0 0x3f8 -#define NS16550_SERIAL_PORT_1 0x2f8 -#define NS16550_SERIAL_PORT_2 0x3e8 -#define NS16550_SERIAL_PORT_3 0x2e8 - #ifdef CONFIG_E2K #define SERIAL_PORT_DFNS \ /* UART CLK PORT IRQ FLAGS */ \ @@ -91,370 +76,4 @@ #define AM85C30_D6 (0x01 << 6) #define AM85C30_D7 (0x01 << 7) -/* WR0 */ -/* D2,D1,D0 -* Register Access Pointer -* -* 000 - N0, [N8]* -* 001 - N1, [N9]* -* 010 - N2, [N10]* -* 011 - N3, [N11]* -* 100 - N4, [N12]* -* 101 - N5, [N13]* -* 110 - N6, [N14]* -* 111 - N7, [N15]* -* -* if Point High Register Group = 1 -* -* D5,D4,D3 -* -* SCC Command -* -* 000 - Null Code -* 001 - Point High Register Group -* 010 - Reset Ext/Status Interrupts -* 011 - Send Abort -* 100 - Enable Int. on Next Rx Character -* 101 - Reset Tx Int. Pending -* 110 - Error Reset -* 111 - Reset Highest IUS -* -* D7,D6 -* SCC Command -* -* 00 - Null Code -* 01 - Reset Rx CRC Checker -* 10 - Reset Tx CRC Generator -* 11 - Reset Tx Underrun/EOM Latch -*/ - -/* WR1 */ -/* D0 -* Ext. Int. Enable -* D1 -* Tx Int. Enable -* D2 -* Parity is Special Condition -* D4,D3 -* Rx Int Mode -* -* 00 - Rx Int Disable -* 01 - Rx Int on First Char. or Special Condition -* 10 - Int on All Rx Char. or Special Condition -* 11 - Rx Int. on Special Condition Only -* D5 -* Wait/DMA Request on Receive/Transmit -* D6 -* Wait/DMA Request Function -* D7 -* Wait/DMA Request Enable -*/ - -/* WR2 */ -/* D7 - D0 -* Interrupt Vector -*/ - -/* WR3 */ -/* D0 -* Rx Enable -* D1 -* Sync Character Load Inhibit -* D2 -* Address Search Mode (SDLC) -* D3 -* Rx CRC Enable -* D4 -* Enter Hunt Mode -* D5 -* Auto Enable -* D7,D6 -* -* 00 - Rx 5 Bits / Character -* 01 - Rx 6 Bits / Character -* 10 - Rx 7 Bits / Character -* 11 - Rx 8 Bits / Character -*/ - -/* WR4 */ -/* D0 -* ParityEnable -* D1 -* Parity Even(0) / Odd(1) -* D3,D2 -* -* 00 - Sync Modes Enable -* 01 - 1 Stop Bit / Character -* 10 - 1.5 Stop Bits / Character -* 11 - 2 Stop Bits / Character -* D5,D4 -* -* 00 - 8-Bit Sync Character -* 01 - 16-Bit Sync Character -* 10 - SDLC Mode -* 11 - External Sync Mode -* D7,D6 -* -* 00 - X1 Clock Mode -* 01 - X16 Clock Mode -* 10 - X32 Clock Mode -* 11 - X64 Clock Mode -*/ - -/* WR5 */ -/* D0 -* Tx CRC Enable -* D1 -* RTS -* D2 -* SDLC-/CRC-16 -* D3 -* Tx Enable -* D4 -* Send Break -* D6,D5 -* -* 00 - Tx 5 Bits / Character -* 01 - Tx 6 Bits / Character -* 10 - Tx 7 Bits / Character -* 11 - Tx 8 Bits / Character -* D7 -* DTR -*/ - -/* WR6 */ -/* D5-D0 -* xN constant -* D7,D6 -* Reserved (not used in asynchronous mode) -*/ - -/* WR7 */ -/* D6-D0 -* Reserved (not used in asynchronous mode) -* D7 -* xN Mode Enable -*/ - -/* WR8 */ -/* D7-D0 -* Transmit Buffer -*/ - -/* WR9 */ -/* D0 -* Vector Includes Status -* D1 -* No Vector -* D2 -* Disable Lower Chain -* D3 -* Master Interrupt Enable -* D4 -* Status High/Low_ -* D5 -* Interrupt Masking Without INTACK_ -* D7-D6 -* -* 00 - No Reset -* 01 - Channel B Reset -* 10 - Channel A Reset -* 11 - Force Hardware Reset -*/ - -/* WR10 */ -/* D0 -* 6 bit / 8 bit SYNC -* D1 -* Loop Mode -* D2 -* Abort/Flag on Underrun -* D3 -* Mark/Flag Idle -* D4 -* Go Active on Poll -* D6-D5 -* -* 00 - NRZ -* 01 - NRZI -* 10 - FM1 (Transition = 1) -* 11 - FM0 (Transition = 0) -* D7 -* CRC Preset '1' or '0' -*/ - -/* WR11 */ -/* D1-D0 -* -* 00 - TRxC Out = XTAL output -* 01 - TRxC Out = Transmit Clock -* 10 - TRxC Out = BRG output -* 11 - TRxC Out = DPLL output -* D2 -* TRxC O/I -* D4-D3 -* -* 00 - Transmit Clock = RTxC pin -* 01 - Transmit Clock = TRxC pin -* 10 - Transmit Clock = BRG output -* 11 - Transmit Clock = DPLL output -* D6-D5 -* -* 00 - Receive Clock = RTxC pin -* 01 - Receive Clock = TRxC pin -* 10 - Receive Clock = BRG output -* 11 - Receive Clock = DPLL output -* D7 -* RTxC XTAL / NO XTAL -*/ - -/* WR12 */ -/* D7-D0 -* Lower Byte of Time Constant -*/ - -/* WR13 */ -/* D7-D0 -* Upper Byte of Time Constant -*/ - -/* WR14 */ -/* D0 -* BRG Enable -* D1 -* BRG Source -* D2 -* DTR / REQUESTt Function -* D3 -* Auto Echo -* D4 -* Local Loopback -* D7-D5 -* -* 000 - Null Command -* 001 - Enter Search Mode -* 010 - Reset Missing Clock -* 011 - Disable DPLL -* 100 - Set Source = BR Generator -* 101 - Set Source = RTxC_ -* 110 - Set FM Mode -* 111 - Set NRZI Mode -*/ - -/* WR15 */ -/* D0 -* SDLC/HDLC Enhancement Enable -* D1 -* Zero Count IE (Interrupt Enable) -* D2 -* 10 * 19-bit Frame Status FIFO Enable -* D3 -* DCD IE -* D4 -* Sync/Hunt IE -* D5 -* CTS IE -* D6 -* Tx Underrun / EOM IE -* D7 -* Break/Abort IE -*/ - - -/* RR0 */ -/* D0 -* Rx Character Availiable -* D1 -* Zero Count -* D2 -* Tx Buffer Empty -* D3 -* DCD -* D4 -* Sync/Hunt -* D5 -* CTS -* D6 -* Tx Underrun / EOM -* D7 -* Break/Abort -*/ - -/* RR1 */ -/* D0 -* All Sent -* D1 -* Residue Code 2 -* D2 -* Residue Code 1 -* D3 -* Residue Code 0 -* D4 -* Parity Error -* D5 -* Rx Overrun Error -* D6 -* CRC / Framing Error -* D7 -* End of Frame (SDLC) -*/ - -/* RR2 */ -/* D7-D0 -* Interrupt Vector -* -* Channel A RR2 = WR2 -* Channel B RR2 = Interrupt Vector Modified* -* -* * -* D3 D2 D1 Status High/Low = 0 -* D4 D5 D6 Status High/Low = 1 -* -* 0 0 0 Ch B Transmit Buffer Empty -* 0 0 1 Ch B External/Status Change -* 0 1 0 Ch B Receive Char. Availiable -* 0 1 1 Ch B Special Receive Condition -* 1 0 0 Ch A Transmit Buffer Empty -* 1 0 1 Ch A External/Status Change -* 1 1 0 Ch A Receive Char. Availiable -* 1 1 1 Ch A Special Receive Condition -*/ - -/* RR3 */ -/* D0 -* Channel B Ext/Status IP (Interrupt Pending) -* D1 -* Channel B Tx IP -* D2 -* Channel B Rx IP -* D3 -* Channel A Ext/Status IP -* D4 -* Channel A Tx IP -* D5 -* Channel A Rx IP -* D7-D6 -* Always 00 -*/ - -/* RR8 */ -/* D7-D0 -* Receive Buffer -*/ - -/* RR10 */ -/* D7-D0 -* Reserved (not used in asynchronous mode) -*/ - -/* RR12 */ -/* D7-D0 -* Lower Byte of Time Constant -*/ - -/* RR13 */ -/* D7-D0 -* Upper Byte of Time Constant -*/ - #endif /* ! _L_SERIAL_H */ diff --git a/arch/e2k/include/asm/Kbuild b/arch/e2k/include/asm/Kbuild index 6196c57..7727e6e 100644 --- a/arch/e2k/include/asm/Kbuild +++ b/arch/e2k/include/asm/Kbuild @@ -4,12 +4,15 @@ generic-y += bugs.h generic-y += div64.h generic-y += errno.h generic-y += emergency-restart.h +generic-y += ioctl.h generic-y += irq_regs.h generic-y += kmap_types.h generic-y += local64.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h -generic-y += preempt.h +generic-y += param.h generic-y += qrwlock.h +generic-y += statfs.h +generic-y += termios.h generic-y += xor.h generic-y += mmiowb.h diff --git a/arch/e2k/include/asm/aau_context.h b/arch/e2k/include/asm/aau_context.h index 42714d0..8bac882 100644 --- a/arch/e2k/include/asm/aau_context.h +++ b/arch/e2k/include/asm/aau_context.h @@ -119,10 +119,10 @@ native_set_all_aaldas(const e2k_aalda_t aaldas_p[]) /* set current array prefetch buffer indices values */ static __always_inline void native_set_aau_aaldis_aaldas( - const struct thread_info *ti, const e2k_aau_t *aau_regs) + const e2k_aalda_t *aaldas, const e2k_aau_t *aau_regs) { native_set_all_aaldis(aau_regs->aaldi); - native_set_all_aaldas(ti->aalda); + native_set_all_aaldas(aaldas); } /* @@ -130,24 +130,24 @@ static __always_inline void native_set_aau_aaldis_aaldas( * and comparison with aasr.iab was taken. */ static inline void -native_get_aau_context_v2(e2k_aau_t *context) +native_get_aau_context_v2(e2k_aau_t *context, e2k_aasr_t aasr) { - NATIVE_GET_AAU_CONTEXT_V2(context); + NATIVE_GET_AAU_CONTEXT_V2(context, aasr); } static inline void -native_get_aau_context_v5(e2k_aau_t *context) +native_get_aau_context_v5(e2k_aau_t *context, e2k_aasr_t aasr) { - NATIVE_GET_AAU_CONTEXT_V5(context); + NATIVE_GET_AAU_CONTEXT_V5(context, aasr); } /* * It's taken that comparison with aasr.iab was taken and assr * will be set later. */ -static __always_inline void -native_set_aau_context(e2k_aau_t *context) +static __always_inline void native_set_aau_context(const e2k_aau_t *context, + const e2k_aalda_t *aalda, e2k_aasr_t aasr) { - NATIVE_SET_AAU_CONTEXT(context); + NATIVE_SET_AAU_CONTEXT(context, aalda, aasr); } #ifdef CONFIG_KVM_GUEST_KERNEL @@ -177,14 +177,14 @@ native_set_aau_context(e2k_aau_t *context) native_get_synchronous_part_v5(aau_context); \ }) -#define GET_AAU_CONTEXT_V2(cntx) native_get_aau_context_v2(cntx) -#define GET_AAU_CONTEXT_V5(cntx) native_get_aau_context_v5(cntx) +#define GET_AAU_CONTEXT_V2(cntx, aasr) native_get_aau_context_v2(cntx, aasr) +#define GET_AAU_CONTEXT_V5(cntx, aasr) native_get_aau_context_v5(cntx, aasr) #define SAVE_AAU_MASK_REGS(aau_context, aasr) \ NATIVE_SAVE_AAU_MASK_REGS(aau_context, aasr) -#define RESTORE_AAU_MASK_REGS(aau_context) \ - NATIVE_RESTORE_AAU_MASK_REGS(aau_context) +#define RESTORE_AAU_MASK_REGS(aau_context, aaldv, aasr) \ + NATIVE_RESTORE_AAU_MASK_REGS(aau_context, aaldv, aasr) #define SAVE_AADS(aau_regs) \ NATIVE_SAVE_AADS(aau_regs) @@ -234,10 +234,10 @@ native_set_aau_context(e2k_aau_t *context) regs = native_read_aafstr_reg_value(); \ }) -static __always_inline void -set_aau_context(e2k_aau_t *context) +static __always_inline void set_aau_context(e2k_aau_t *context, + const e2k_aalda_t *aalda, e2k_aasr_t aasr) { - native_set_aau_context(context); + native_set_aau_context(context, aalda, aasr); } #endif /* CONFIG_KVM_GUEST_KERNEL */ @@ -245,10 +245,8 @@ set_aau_context(e2k_aau_t *context) /* * for code optimization */ -static inline int aau_working(e2k_aau_t *context) +static inline int aau_working(e2k_aasr_t aasr) { - e2k_aasr_t aasr = context->aasr; - return unlikely(AW(aasr) & (AAU_AASR_IAB | AAU_AASR_STB)); } diff --git a/arch/e2k/include/asm/aau_regs_access.h b/arch/e2k/include/asm/aau_regs_access.h index 78e2355..12c6a33 100644 --- a/arch/e2k/include/asm/aau_regs_access.h +++ b/arch/e2k/include/asm/aau_regs_access.h @@ -35,42 +35,49 @@ */ #define PREFIX_SAVE_AAU_MASK_REGS(PV_TYPE, pv_type, aau_context, aasr) \ -({ \ - if (unlikely(AAU_ACTIVE(aasr))) { \ - /* As it turns out AAU can be in ACTIVE state \ - * in interrupt handler (bug 53227 comment 28 \ - * and bug 53227 comment 36). \ - * The hardware stops AAU automatically but \ - * the value to be written should be corrected \ - * to "stopped" so that the "DONE" instruction \ - * works as expected. \ - */ \ - AS(aasr).lds = AASR_STOPPED; \ +do { \ + if (aau_context) { \ + if (unlikely(AAU_STOPPED(aasr))) { \ + pv_type##_read_aaldv_reg(&(aau_context)->aaldv); \ + pv_type##_read_aaldm_reg(&(aau_context)->aaldm); \ + } else { \ + AW((aau_context)->aaldv) = 0; \ + AW((aau_context)->aaldm) = 0; \ + } \ } \ - (aau_context)->aasr = aasr; \ - if (unlikely(AAU_STOPPED(aasr))) { \ - pv_type##_read_aaldv_reg(&(aau_context)->aaldv); \ - pv_type##_read_aaldm_reg(&(aau_context)->aaldm); \ - } else { \ - AW((aau_context)->aaldv) = 0; \ - AW((aau_context)->aaldm) = 0; \ - } \ -}) +} while (0) -#define NATIVE_SAVE_AAU_MASK_REGS(aau_context, aasr) \ +#define NATIVE_SAVE_AAU_MASK_REGS(aau_context, aasr) \ PREFIX_SAVE_AAU_MASK_REGS(NATIVE, native, aau_context, aasr) -#define PREFIX_RESTORE_AAU_MASK_REGS(PV_TYPE, pv_type, aau_context) \ +static inline e2k_aasr_t aasr_parse(e2k_aasr_t aasr) +{ + if (unlikely(AAU_ACTIVE(aasr))) { + /* As it turns out AAU can be in ACTIVE state + * in interrupt handler (bug 53227 comment 28 + * and bug 53227 comment 36). + * The hardware stops AAU automatically but + * the value to be written should be corrected + * to "stopped" so that the "DONE" instruction + * works as expected. + */ + aasr.lds = AASR_STOPPED; + } + + return aasr; +} + +#define PREFIX_RESTORE_AAU_MASK_REGS(PV_TYPE, pv_type, aaldm, aaldv, aasr) \ ({ \ pv_type##_write_aafstr_reg_value(0); \ - pv_type##_write_aaldm_reg(&(aau_context)->aaldm); \ - pv_type##_write_aaldv_reg(&(aau_context)->aaldv); \ + pv_type##_write_aaldm_reg(aaldm); \ + pv_type##_write_aaldv_reg(aaldv); \ /* aasr can be in 'ACTIVE' state, so we set it last */ \ - pv_type##_write_aasr_reg((aau_context)->aasr); \ + pv_type##_write_aasr_reg(aasr); \ }) -#define NATIVE_RESTORE_AAU_MASK_REGS(aau_context) \ - PREFIX_RESTORE_AAU_MASK_REGS(NATIVE, native, aau_context) +#define NATIVE_RESTORE_AAU_MASK_REGS(aaldm, aaldv, aasr) \ + PREFIX_RESTORE_AAU_MASK_REGS(NATIVE, native, aaldm, aaldv, aasr) #define PREFIX_SAVE_AADS(PV_TYPE, pv_type, aau_regs) \ ({ \ @@ -491,74 +498,68 @@ * It's taken that aasr was get earlier(from get_aau_context caller) * and comparison with aasr.iab was taken. */ -#define PREFIX_GET_AAU_CONTEXT(PV_TYPE, pv_type, ISET, iset, aau_context) \ +#define PREFIX_GET_AAU_CONTEXT(PV_TYPE, pv_type, ISET, iset, aau_context, aasr) \ ({ \ - /* get registers, which describe arrays in APB operations */ \ - e2k_aasr_t aasr = (aau_context)->aasr; \ - \ /* get descriptors & auxiliary registers */ \ - if (AS(aasr).iab) \ - PV_TYPE##_GET_ARRAY_DESCRIPTORS_##ISET(aau_context); \ + if (aasr.iab) \ + PV_TYPE##_GET_ARRAY_DESCRIPTORS_##ISET(aau_context); \ \ /* get synchronous part of APB */ \ - if (AS(aasr).stb) \ + if (aasr.stb) \ PV_TYPE##_GET_SYNCHRONOUS_PART_##ISET(aau_context); \ }) -#define PREFIX_GET_AAU_CONTEXT_V2(PV_TYPE, pv_type, aau_context) \ - PREFIX_GET_AAU_CONTEXT(PV_TYPE, pv_type, V2, v2, aau_context) -#define PREFIX_GET_AAU_CONTEXT_V5(PV_TYPE, pv_type, aau_context) \ - PREFIX_GET_AAU_CONTEXT(PV_TYPE, pv_type, V5, v5, aau_context) -#define NATIVE_GET_AAU_CONTEXT_V2(aau_context) \ - PREFIX_GET_AAU_CONTEXT_V2(NATIVE, native, aau_context) -#define NATIVE_GET_AAU_CONTEXT_V5(aau_context) \ - PREFIX_GET_AAU_CONTEXT_V5(NATIVE, native, aau_context) -#define NATIVE_GET_AAU_CONTEXT(aau_context) \ -({ \ +#define PREFIX_GET_AAU_CONTEXT_V2(PV_TYPE, pv_type, aau_context, aasr) \ + PREFIX_GET_AAU_CONTEXT(PV_TYPE, pv_type, V2, v2, aau_context, aasr) +#define PREFIX_GET_AAU_CONTEXT_V5(PV_TYPE, pv_type, aau_context, aasr) \ + PREFIX_GET_AAU_CONTEXT(PV_TYPE, pv_type, V5, v5, aau_context, aasr) +#define NATIVE_GET_AAU_CONTEXT_V2(aau_context, aasr) \ + PREFIX_GET_AAU_CONTEXT_V2(NATIVE, native, aau_context, aasr) +#define NATIVE_GET_AAU_CONTEXT_V5(aau_context, aasr) \ + PREFIX_GET_AAU_CONTEXT_V5(NATIVE, native, aau_context, aasr) +#define NATIVE_GET_AAU_CONTEXT(aau_context, aasr) \ +do { \ if (IS_AAU_ISET_V5()) { \ - NATIVE_GET_AAU_CONTEXT_V5(aau_context); \ + NATIVE_GET_AAU_CONTEXT_V5(aau_context, aasr); \ } else if (IS_AAU_ISET_V2()) { \ - NATIVE_GET_AAU_CONTEXT_V2(aau_context); \ + NATIVE_GET_AAU_CONTEXT_V2(aau_context, aasr); \ } else if (IS_AAU_ISET_GENERIC()) { \ - machine.get_aau_context(aau_context); \ + machine.get_aau_context(aau_context, aasr); \ } else { \ BUILD_BUG_ON(true); \ } \ -}) +} while (0) -/* - * It's taken that comparison with aasr.iab was taken and assr - * will be set later. - */ -#define PREFIX_SET_AAU_CONTEXT(PV_TYPE, pv_type, aau_context) \ +#define PREFIX_SET_AAU_CONTEXT(PV_TYPE, pv_type, aau_context, aalda, aasr) \ do { \ const e2k_aau_t *const aau = (aau_context); \ - /* retrieve common APB status register */\ - e2k_aasr_t aasr = aau->aasr; \ \ /* prefetch data to restore */ \ - if (AS(aasr).stb) \ + if (aasr.stb) \ prefetch_nospec_range(aau->aastis, sizeof(aau->aastis) + \ sizeof(aau->aasti_tags)); \ - if (AS(aasr).iab) \ + if (aasr.iab) \ prefetch_nospec_range(aau->aainds, sizeof(aau->aainds) + \ sizeof(aau->aaind_tags) + sizeof(aau->aaincrs) + \ sizeof(aau->aaincr_tags) + sizeof(aau->aads)); \ - if (AAU_STOPPED(aasr)) \ + if (AAU_STOPPED(aasr)) { \ prefetch_nospec_range(aau->aaldi, sizeof(aau->aaldi)); \ + if (!cpu_has(CPU_FEAT_ISET_V6)) \ + prefetch_nospec_range(aalda, sizeof(e2k_aalda_t) * AALDAS_REGS_NUM); \ + } \ \ /* Make sure prefetches are issued */ \ barrier(); \ \ /* set synchronous part of APB */ \ - if (AS(aasr).stb) \ + if (aasr.stb) \ pv_type##_set_synchronous_part(aau); \ \ /* set descriptors & auxiliary registers */ \ - if (AS(aasr).iab) \ + if (aasr.iab) \ pv_type##_set_array_descriptors(aau); \ } while (0) -#define NATIVE_SET_AAU_CONTEXT(aau_context) \ - PREFIX_SET_AAU_CONTEXT(NATIVE, native, aau_context) +#define NATIVE_SET_AAU_CONTEXT(aau_context, aalda, aasr) \ + PREFIX_SET_AAU_CONTEXT(NATIVE, native, (aau_context), (aalda), (aasr)) #define PREFIX_SAVE_AALDAS(PV_TYPE, pv_type, aaldas_p) \ ({ \ @@ -638,7 +639,7 @@ static inline void read_aaldm_reg(e2k_aaldm_t *aaldm) { native_read_aaldm_reg(aaldm); } -static inline void write_aaldm_reg(e2k_aaldm_t *aaldm) +static inline void write_aaldm_reg(e2k_aaldm_t aaldm) { native_write_aaldm_reg(aaldm); } @@ -646,7 +647,7 @@ static inline void read_aaldv_reg(e2k_aaldv_t *aaldv) { native_read_aaldv_reg(aaldv); } -static inline void write_aaldv_reg(e2k_aaldv_t *aaldv) +static inline void write_aaldv_reg(e2k_aaldv_t aaldv) { native_write_aaldv_reg(aaldv); } @@ -662,24 +663,4 @@ static inline void write_aaldv_reg(e2k_aaldv_t *aaldv) #endif /* CONFIG_KVM_GUEST_KERNEL */ -#define SWITCH_GUEST_AAU_AASR(aasr, aau_context, do_switch) \ -({ \ - if (do_switch) { \ - e2k_aasr_t aasr_worst_case; \ - AW(aasr_worst_case) = 0; \ - AS(aasr_worst_case).stb = 1; \ - AS(aasr_worst_case).iab = 1; \ - AS(aasr_worst_case).lds = AASR_STOPPED; \ - (aau_context)->guest_aasr = *(aasr); \ - *(aasr) = aasr_worst_case; \ - } \ -}) - -#define RESTORE_GUEST_AAU_AASR(aau_context, do_restore) \ -({ \ - if (do_restore) { \ - (aau_context)->aasr = (aau_context)->guest_aasr; \ - } \ -}) - #endif /* _E2K_AAU_REGS_ACCESS_H_ */ diff --git a/arch/e2k/include/asm/aau_regs_types.h b/arch/e2k/include/asm/aau_regs_types.h index f536117..74dd0ea 100644 --- a/arch/e2k/include/asm/aau_regs_types.h +++ b/arch/e2k/include/asm/aau_regs_types.h @@ -48,22 +48,25 @@ enum { }; #define AAU_AASR_STB 0x20 #define AAU_AASR_IAB 0x40 -typedef struct e2k_aasr_fields { - u32 reserved : 5; /* [4:0] */ - u32 stb : 1; /* [5:5] */ - u32 iab : 1; /* [6:6] */ - u32 lds : 3; /* [9:7] */ -} e2k_aasr_fields_t; typedef union e2k_aasr { /* aadj quad-word */ - e2k_aasr_fields_t fields; + struct { + u32 reserved : 5; /* [4:0] */ + u32 stb : 1; /* [5:5] */ + u32 iab : 1; /* [6:6] */ + u32 lds : 3; /* [9:7] */ + }; u32 word; } e2k_aasr_t; +#define E2K_FULL_AASR ((e2k_aasr_t) { .stb = 1, .iab = 1, .lds = AASR_STOPPED }) + /* Check up AAU state */ -#define AAU_NULL(aasr) (AS(aasr).lds == AASR_NULL) -#define AAU_READY(aasr) (AS(aasr).lds == AASR_READY) -#define AAU_ACTIVE(aasr) (AS(aasr).lds == AASR_ACTIVE) -#define AAU_STOPPED(aasr) (AS(aasr).lds == AASR_STOPPED) +#define AAU_NULL(aasr) (aasr.lds == AASR_NULL) +#define AAU_READY(aasr) (aasr.lds == AASR_READY) +#define AAU_ACTIVE(aasr) (aasr.lds == AASR_ACTIVE) +#define AAU_STOPPED(aasr) (aasr.lds == AASR_STOPPED) + +#define aau_has_state(aasr) (!AAU_NULL(aasr) || aasr.iab || aasr.stb) typedef u32 e2k_aafstr_t; @@ -150,13 +153,7 @@ typedef union e2k_aalda_struct { #define AALDIS_REGS_NUM 64 #define AALDAS_REGS_NUM 64 -/* - * For virtualization, aasr might be switched to worst-case scenario (lds = AAU_STOPPED, - * iab = 1, stb = 1). In that case, real aasr will be saved to guest_aasr - */ typedef struct e2k_aau_context { - e2k_aasr_t aasr; - e2k_aasr_t guest_aasr; e2k_aafstr_t aafstr; e2k_aaldm_t aaldm; e2k_aaldv_t aaldv; diff --git a/arch/e2k/include/asm/atomic_api.h b/arch/e2k/include/asm/atomic_api.h index 02b6f02..5f621dd 100644 --- a/arch/e2k/include/asm/atomic_api.h +++ b/arch/e2k/include/asm/atomic_api.h @@ -27,9 +27,9 @@ # else # ifndef __ASSEMBLY__ # include -register unsigned long long __cpu_reg DO_ASM_GET_GREG_MEMONIC(SMP_CPU_ID_GREG); +register unsigned long long __cpu_preempt_reg DO_ASM_GET_GREG_MEMONIC(SMP_CPU_ID_GREG); # endif -# define NATIVE_HWBUG_AFTER_LD_ACQ_CPU __cpu_reg +# define NATIVE_HWBUG_AFTER_LD_ACQ_CPU ((unsigned int) __cpu_preempt_reg) # endif #elif defined(E2K_P2V) diff --git a/arch/e2k/include/asm/barrier.h b/arch/e2k/include/asm/barrier.h index 8dee3f3..38025ba 100644 --- a/arch/e2k/include/asm/barrier.h +++ b/arch/e2k/include/asm/barrier.h @@ -4,7 +4,6 @@ #include #include -#include #include #if CONFIG_CPU_ISET >= 6 diff --git a/arch/e2k/include/asm/compiler.h b/arch/e2k/include/asm/compiler.h index b89aea8..10c3487 100644 --- a/arch/e2k/include/asm/compiler.h +++ b/arch/e2k/include/asm/compiler.h @@ -26,7 +26,10 @@ * The same goes for preemption-disabled sections: these clobbers * will forbid compiler to move per-cpu area address calculation out * from them. Since disabling interrupts also disables preemption, - * we also need these clobbers when writing PSR/UPSR. */ + * we also need these clobbers when writing PSR/UPSR. + * + * And of course operations on preempt_count must not be moved + * out of/into preemption disabled sections. */ #define PREEMPTION_CLOBBERS __PREEMPTION_CLOBBERS(SMP_CPU_ID_GREG, MY_CPU_OFFSET_GREG) #ifdef CONFIG_DEBUG_LCC_VOLATILE_ATOMIC diff --git a/arch/e2k/include/asm/copy-hw-stacks.h b/arch/e2k/include/asm/copy-hw-stacks.h index ee45fca..8557fa0 100644 --- a/arch/e2k/include/asm/copy-hw-stacks.h +++ b/arch/e2k/include/asm/copy-hw-stacks.h @@ -280,12 +280,9 @@ static __always_inline s64 get_ps_copy_size(u64 cur_window_q, s64 u_pshtp_size) return u_pshtp_size - (E2K_MAXSR - cur_window_q) * EXT_4_NR_SZ; } -#ifdef CONFIG_CPU_HAS_FILL_INSTRUCTION -# define E2K_CF_MAX_FILL (E2K_CF_MAX_FILL_FILLC_q * 0x10) -#else extern int cf_max_fill_return; -# define E2K_CF_MAX_FILL cf_max_fill_return -#endif +#define E2K_CF_MAX_FILL (cpu_has(CPU_FEAT_FILLC) ? \ + (E2K_CF_MAX_FILL_FILLC_q * 0x10) : cf_max_fill_return) static __always_inline s64 get_pcs_copy_size(s64 u_pcshtp_size) { diff --git a/arch/e2k/include/asm/cpu_features.h b/arch/e2k/include/asm/cpu_features.h new file mode 100644 index 0000000..79addd8 --- /dev/null +++ b/arch/e2k/include/asm/cpu_features.h @@ -0,0 +1,64 @@ +#ifndef _E2K_ASM_CPU_FEATURES_H +#define _E2K_ASM_CPU_FEATURES_H + +#ifndef __ASSEMBLY__ +enum { + /* Hardware bugs */ + CPU_HWBUG_LARGE_PAGES, + CPU_HWBUG_LAPIC_TIMER, + CPU_HWBUG_PIO_READS, + CPU_HWBUG_ATOMIC, + CPU_HWBUG_CLW, + CPU_HWBUG_PAGE_A, + CPU_HWBUG_SPURIOUS_EXC_ILL_INSTR_ADDR, + CPU_HWBUG_UNALIGNED_LOADS, + CPU_HWBUG_CANNOT_DO_DMA_IN_NEIGHBOUR_NODE, + CPU_HWBUG_DMA_AT_APIC_ADDR, + CPU_HWBUG_KERNEL_DATA_MONITOR, + CPU_HWBUG_WRITE_MEMORY_BARRIER, + CPU_HWBUG_BAD_RESET, + CPU_HWBUG_BREAKPOINT_INSTR, + CPU_HWBUG_E8C_WATCHDOG, + CPU_HWBUG_IOMMU, + CPU_HWBUG_WC_DAM, + CPU_HWBUG_TRAP_CELLAR_S_F, + CPU_HWBUG_SS, + CPU_HWBUG_AAU_AALDV, + CPU_HWBUG_LEVEL_EOI, + CPU_HWBUG_FALSE_SS, + CPU_HWBUG_SPURIOUS_EXC_DATA_DEBUG, + CPU_HWBUG_TLB_FLUSH_L1D, + CPU_HWBUG_GUEST_ASYNC_PM, + CPU_HWBUG_E16C_SLEEP, + CPU_HWBUG_L1I_STOPS_WORKING, + CPU_HWBUG_CLW_STALE_L1_ENTRY, + CPU_HWBUG_PIPELINE_FREEZE_MONITORS, + CPU_HWBUG_C3_WAIT_MA_C, + CPU_HWBUG_VIRT_SCLKM3_INTC, + CPU_HWBUG_VIRT_PUSD_PSL, + CPU_HWBUG_USD_ALIGNMENT, + CPU_HWBUG_VIRT_PSIZE_INTERCEPTION, + CPU_NO_HWBUG_SOFT_WAIT, + CPU_HWBUG_SOFT_WAIT_E8C2, + CPU_HWBUG_C3, + + /* Features, not bugs */ + CPU_FEAT_WC_PCI_PREFETCH, + CPU_FEAT_FLUSH_DC_IC, + CPU_FEAT_EPIC, + CPU_FEAT_TRAP_V5, + CPU_FEAT_TRAP_V6, + CPU_FEAT_QPREG, + CPU_FEAT_HW_PREFETCHER, + CPU_FEAT_SEPARATE_TLU_CACHE, + CPU_FEAT_FILLR, + CPU_FEAT_FILLC, + CPU_FEAT_ISET_V3, + CPU_FEAT_ISET_V5, + CPU_FEAT_ISET_V6, + + NR_CPU_FEATURES +}; +#endif + +#endif diff --git a/arch/e2k/include/asm/cpu_regs_types.h b/arch/e2k/include/asm/cpu_regs_types.h index cf797e2..a2ad020 100644 --- a/arch/e2k/include/asm/cpu_regs_types.h +++ b/arch/e2k/include/asm/cpu_regs_types.h @@ -4,7 +4,7 @@ #ifdef __KERNEL__ -#include +#include #ifndef __ASSEMBLY__ @@ -619,47 +619,65 @@ typedef e2k_rwap_struct_t psp_struct_t; * describes the full procedure chain stack memory as well as the current * pointer to the top of a procedure chain stack memory part. */ +typedef union { + struct { + u64 base : E2K_VA_SIZE; + u64 : 58 - E2K_VA_SIZE; + u64 p : 1; + u64 rw : 2; + u64 : 3; + }; + e2k_rwap_lo_fields_t fields; + u64 word; +} e2k_pcsp_lo_t; +#define _PCSP_lo_rw rw +#define E2K_PCSR_RW_PROTECTIONS E2_RWAR_RW_ENABLE; +#define PCSP_lo_base base +#define PCSP_lo_half word - /* - * Structure of lower word - * access PCSP.lo.PCSP_lo_xxx or PCSP -> lo.PCSP_lo_xxx - * or PCSP_lo.PCSP_lo_xxx or PCSP_lo -> PCSP_lo_xxx - */ -typedef e2k_rwap_lo_struct_t e2k_pcsp_lo_t; -#define _PCSP_lo_rw E2K_RWAP_lo_rw /* [60:59] - read/write flags */ - /* should be "RW" */ -#define E2K_PCSR_RW_PROTECTIONS E2_RWAR_RW_ENABLE; -#define PCSP_lo_base E2K_RWAP_lo_base /* [47: 0] - base address */ -#define PCSP_lo_half E2K_RWAP_lo_half /* [63: 0] - entire lower */ - /* double-word of register */ - /* - * Structure of high word - * access PCSP.hi.PCSP_hi_xxx or PCSP -> hi.PCSP_hi_xxx - * or PCSP_hi.PCSP_hi_xxx or PCSP_hi -> PCSP_hi_xxx - */ -typedef e2k_rwap_hi_struct_t e2k_pcsp_hi_t; -#define PCSP_hi_size E2K_RPSP_hi_size /* [63:32] - size */ -#define PCSP_hi_ind E2K_RPSP_hi_ind /* [31: 0] - index for SPILL */ - /* and FILL */ -#define PCSP_hi_half E2K_RPSP_hi_half /* [63: 0] - entire high */ +typedef union { + struct { + u64 ind : 32; + u64 size : 32; + }; + e2k_rpsp_hi_fields_t fields; + u64 word; +} e2k_pcsp_hi_t; +#define PCSP_hi_size size +#define PCSP_hi_ind ind +#define PCSP_hi_half word /* * Structure of quad-word register * access PCSP.PCSP_xxx or PCSP -> PCSP_xxx */ -typedef e2k_rwap_struct_t pcsp_struct_t; -#define _PCSP_rw E2K_RWAP_rw /* [60:59] - read/write flags */ - /* should be "RW" */ -#define PCSP_base E2K_RWAP_base /* [47: 0] - base address */ -#define PCSP_size E2K_RPSP_size /* [63:32] - size */ -#define PCSP_ind E2K_RPSP_ind /* [31: 0] - index for SPILL */ - /* and FILL */ -#define PCSP_lo_reg E2K_RWAP_lo_reg /* [63: 0] - entire lower */ - /* double-word of register */ -#define PCSP_hi_reg E2K_RPSP_hi_reg /* [63: 0] - entire high */ - /* double-word of register */ -#define PCSP_lo_struct E2K_RWAP_lo_struct /* low register structure */ -#define PCSP_hi_struct E2K_RPSP_hi_struct /* high register structure */ +typedef struct { + union { + struct { + u64 base : E2K_VA_SIZE; + u64 : 58 - E2K_VA_SIZE; + u64 p : 1; + u64 rw : 2; + u64 : 3; + }; + e2k_pcsp_lo_t lo; + }; + union { + struct { + u64 ind : 32; + u64 size : 32; + }; + e2k_pcsp_hi_t hi; + }; +} pcsp_struct_t; +#define PCSP_rw rw +#define PCSP_base base +#define PCSP_size size +#define PCSP_ind ind +#define PCSP_lo_reg lo.word +#define PCSP_hi_reg hi.word +#define PCSP_lo_struct lo +#define PCSP_hi_struct hi #endif /* !(__ASSEMBLY__) */ #define E2K_ALIGN_PCSTACK 12 /* Procedure chain stack */ @@ -2398,33 +2416,19 @@ typedef union { u32 btf : 1; u32 gm : 1; }; - struct { - u32 v0 : 1; - u32 t0 : 1; - u32 v1 : 1; - u32 t1 : 1; - u32 v2 : 1; - u32 t2 : 1; - u32 v3 : 1; - u32 t3 : 1; - u32 bt : 1; - u32 stop : 1; - u32 btf : 1; - u32 gm : 1; - } fields; u32 word; } e2k_dibcr_t; #define DIBCR_reg word #define E2K_DIBCR_MASK(cp_num) (0x3ULL << ((cp_num) * 2)) -typedef union { +typedef union e2k_dimtp { struct { struct { - u64 base : E2K_VA_SIZE; - u64 __pad1 : 59 - E2K_VA_SIZE; - u64 rw : 2; - u64 __pad2 : 3; + u64 base : E2K_VA_SIZE; + u64 : 59 - E2K_VA_SIZE; + u64 rw : 2; + u64 : 3; }; struct { u64 ind : 32; diff --git a/arch/e2k/include/asm/e12c.h b/arch/e2k/include/asm/e12c.h index d16f7e1..24f3385 100644 --- a/arch/e2k/include/asm/e12c.h +++ b/arch/e2k/include/asm/e12c.h @@ -19,9 +19,6 @@ extern void setup_APIC_vector_handler(int vector, void (*handler)(struct pt_regs *), bool system, char *name); #endif -#define E12C_CPU_VENDOR ES2_CPU_VENDOR -#define E12C_CPU_FAMILY E16C_CPU_FAMILY - #define E12C_NR_NODE_CPUS 12 #define E12C_MAX_NR_NODE_CPUS 16 diff --git a/arch/e2k/include/asm/e16c.h b/arch/e2k/include/asm/e16c.h index a83362f..57041e8 100644 --- a/arch/e2k/include/asm/e16c.h +++ b/arch/e2k/include/asm/e16c.h @@ -19,9 +19,6 @@ extern void setup_APIC_vector_handler(int vector, void (*handler)(struct pt_regs *), bool system, char *name); #endif -#define E16C_CPU_VENDOR ES2_CPU_VENDOR -#define E16C_CPU_FAMILY 6 - #define E16C_NR_NODE_CPUS 16 #define E16C_MAX_NR_NODE_CPUS 16 diff --git a/arch/e2k/include/asm/e1cp.h b/arch/e2k/include/asm/e1cp.h index 5c4204d..02189e1 100644 --- a/arch/e2k/include/asm/e1cp.h +++ b/arch/e2k/include/asm/e1cp.h @@ -13,9 +13,6 @@ extern void boot_e1cp_setup_arch(void); extern void e1cp_setup_machine(void); #endif -#define E1CP_CPU_VENDOR ES2_CPU_VENDOR -#define E1CP_CPU_FAMILY ES2_CPU_FAMILY - #define E1CP_NR_NODE_CPUS 1 #define E1CP_MAX_NR_NODE_CPUS E1CP_NR_NODE_CPUS diff --git a/arch/e2k/include/asm/e2c3.h b/arch/e2k/include/asm/e2c3.h index d0b1dd1..63da1bc 100644 --- a/arch/e2k/include/asm/e2c3.h +++ b/arch/e2k/include/asm/e2c3.h @@ -19,9 +19,6 @@ extern void setup_APIC_vector_handler(int vector, void (*handler)(struct pt_regs *), bool system, char *name); #endif -#define E2C3_CPU_VENDOR ES2_CPU_VENDOR -#define E2C3_CPU_FAMILY E16C_CPU_FAMILY - #define E2C3_NR_NODE_CPUS 2 #define E2C3_MAX_NR_NODE_CPUS 16 diff --git a/arch/e2k/include/asm/e2k.h b/arch/e2k/include/asm/e2k.h index 9a7308b..ef02fc7 100644 --- a/arch/e2k/include/asm/e2k.h +++ b/arch/e2k/include/asm/e2k.h @@ -419,4 +419,6 @@ static inline void set_mach_type_id(void) extern unsigned long machine_serial_num; +#define ELBRUS_CPU_VENDOR "Elbrus-MCST" + #endif /* _ASM_E2K_H_ */ diff --git a/arch/e2k/include/asm/e2k_api.h b/arch/e2k/include/asm/e2k_api.h index cebc5c9..fbf6bcd 100644 --- a/arch/e2k/include/asm/e2k_api.h +++ b/arch/e2k/include/asm/e2k_api.h @@ -2,7 +2,11 @@ #define _E2K_API_H_ #include +#include +#include +#include /* For instr_cs1_t */ #include + #include @@ -4602,76 +4606,6 @@ do { \ __res; \ }) -#if !defined CONFIG_E2K_MACHINE || \ - defined CONFIG_E2K_ES2_DSP || defined CONFIG_E2K_ES2_RU || \ - (defined CONFIG_E2K_E2S && defined CONFIG_NUMA) -# define WORKAROUND_WAIT_HWBUG(num) (((num) & (_st_c | _all_c | _sas)) ? \ - ((num) | _ma_c) : (num)) -#else -# define WORKAROUND_WAIT_HWBUG(num) num -#endif - -#define __E2K_WAIT(_num) \ -do { \ - int unused, num = WORKAROUND_WAIT_HWBUG(_num); \ - instr_cs1_t cs1 = { \ - .opc = CS1_OPC_WAIT, \ - .param = num \ - }; \ - \ - /* Use "asm volatile" around tricky barriers such as _ma_c, _fl_c, etc */ \ - if ((_num) & ~(_st_c | _ld_c | _sas | _sal | _las | _lal | _mt)) \ - asm volatile ("" ::: "memory"); \ - \ - /* CPU_NO_HWBUG_SOFT_WAIT: use faster workaround for "lal" barriers */ \ - if ((_num) == (_ld_c | _lal) || (_num) == (_ld_c | _lal | _mt)) { \ - _Pragma("no_asm_inline") \ - asm NOT_VOLATILE (ALTERNATIVE( \ - /* Default version - add nop 5 */ \ - ".word 0x00008281\n" \ - ".word %[cs1]\n", \ - /* CPU_NO_HWBUG_SOFT_WAIT version */ \ - ".word 0x00008001\n" \ - ".word %[cs1]\n", \ - %[facility]) \ - : "=r" (unused) \ - : [cs1] "i" (cs1.word), \ - [facility] "i" (CPU_NO_HWBUG_SOFT_WAIT) \ - : "memory"); \ - } else { \ - instr_cs1_t cs1_no_soft_barriers = { \ - .opc = CS1_OPC_WAIT, \ - .param = num & ~(_lal | _las | _sal | _sas) \ - }; \ - /* #79245 - use .word to encode relaxed barriers */ \ - _Pragma("no_asm_inline") \ - asm NOT_VOLATILE (ALTERNATIVE( \ - /* Default version */ \ - ".word 0x00008001\n" \ - ".word %[cs1_no_soft_barriers]\n", \ - /* CPU_NO_HWBUG_SOFT_WAIT version - use soft barriers */ \ - ".word 0x00008001\n" \ - ".word %[cs1]\n", \ - %[facility]) \ - : "=r" (unused) \ - : [cs1] "i" (cs1.word), \ - [cs1_no_soft_barriers] "i" (cs1_no_soft_barriers.word), \ - [facility] "i" (CPU_NO_HWBUG_SOFT_WAIT) \ - : "memory"); \ - } \ - \ - /* Use "asm volatile" around tricky barriers such as _ma_c */ \ - if ((_num) & ~(_st_c | _ld_c | _sas | _sal | _las | _lal | _mt)) \ - asm volatile ("" ::: "memory"); \ -} while (0) - -#define E2K_WAIT(num) \ -do { \ - __E2K_WAIT(num); \ - if (num & (_st_c | _ld_c | _all_c | _ma_c)) \ - NATIVE_HWBUG_AFTER_LD_ACQ(); \ -} while (0) - #define _mem_mod 0x2000 /* watch for modification */ #define _int 0x1000 /* stop the conveyor untill interrupt */ #define _mt 0x800 @@ -4688,6 +4622,92 @@ do { \ #define _all_e 0x2 /* stop until prev. operations issue all exceptions */ #define _all_c 0x1 /* stop until prev. operations complete */ +#if !defined CONFIG_E2K_MACHINE || \ + defined CONFIG_E2K_ES2_DSP || defined CONFIG_E2K_ES2_RU || \ + (defined CONFIG_E2K_E2S && defined CONFIG_NUMA) +# define WORKAROUND_WAIT_HWBUG(num) (((num) & (_st_c | _all_c | _sas)) ? \ + ((num) | _ma_c) : (num)) +#else +# define WORKAROUND_WAIT_HWBUG(num) num +#endif + +#ifndef __ASSEMBLY__ +/* We use a static inline function instead of a macro + * because otherwise the preprocessed files size will + * increase tenfold making compile times much worse. */ +__attribute__((__always_inline__)) +static inline void __E2K_WAIT(int _num) +{ + int unused, num = WORKAROUND_WAIT_HWBUG(_num); + instr_cs1_t cs1 = { + .opc = CS1_OPC_WAIT, + .param = num + }; + + /* Use "asm volatile" around tricky barriers such as _ma_c, _fl_c, etc */ + if (_num & ~(_st_c | _ld_c | _sas | _sal | _las | _lal | _mt)) + asm volatile ("" ::: "memory"); + + /* Header dependency hell, cannot use here: + * cpu_has(CPU_HWBUG_SOFT_WAIT_E8C2) + * so just check straight for E8C2 */ + if (IS_ENABLED(CONFIG_CPU_E8C2) && (num & (_sas | _sal))) + asm ("{nop}" ::: "memory"); + + /* CPU_NO_HWBUG_SOFT_WAIT: use faster workaround for "lal" barriers */ + if (_num == (_ld_c | _lal) || _num == (_ld_c | _lal | _mt)) { +#pragma no_asm_inline + asm NOT_VOLATILE (ALTERNATIVE( + /* Default version - add "nop 5" after and a separate + * wide instruction before the barrier. */ + "{nop}" + ".word 0x00008281\n" + ".word %[cs1]\n", + /* CPU_NO_HWBUG_SOFT_WAIT version */ + ".word 0x00008011\n" + ".word %[cs1]\n" + ".word 0x0\n" + ".word 0x0\n", + %[facility]) + : "=r" (unused) + : [cs1] "i" (cs1.word), + [facility] "i" (CPU_NO_HWBUG_SOFT_WAIT) + : "memory"); + } else { + instr_cs1_t cs1_no_soft_barriers = { + .opc = CS1_OPC_WAIT, + .param = num & ~(_lal | _las | _sal | _sas) + }; + /* #79245 - use .word to encode relaxed barriers */ +#pragma no_asm_inline + asm NOT_VOLATILE (ALTERNATIVE( + /* Default version */ + ".word 0x00008001\n" + ".word %[cs1_no_soft_barriers]\n", + /* CPU_NO_HWBUG_SOFT_WAIT version - use soft barriers */ + ".word 0x00008001\n" + ".word %[cs1]\n", + %[facility]) + : "=r" (unused) + : [cs1] "i" (cs1.word), + [cs1_no_soft_barriers] "i" (cs1_no_soft_barriers.word), + [facility] "i" (CPU_NO_HWBUG_SOFT_WAIT) + : "memory"); + } + + /* Use "asm volatile" around tricky barriers such as _ma_c, _fl_c, etc */ + if (_num & ~(_st_c | _ld_c | _sas | _sal | _las | _lal | _mt)) + asm volatile ("" ::: "memory"); +} +#endif + +#define E2K_WAIT(num) \ +do { \ + __E2K_WAIT(num); \ + if (num & (_st_c | _ld_c | _all_c | _ma_c)) \ + NATIVE_HWBUG_AFTER_LD_ACQ(); \ +} while (0) + /* * IMPORTANT NOTE!!! * Do not add 'sas' and 'sal' here, as they are modifiers @@ -5060,15 +5080,19 @@ static inline void E2K_SET_USER_STACK(int x) #ifdef CONFIG_SMP # define SMP_ONLY(...) __VA_ARGS__ +# define NOT_SMP_ONLY(...) #else # define SMP_ONLY(...) +# define NOT_SMP_ONLY(...) __VA_ARGS__ #endif -#ifdef CONFIG_CPU_HAS_FILL_INSTRUCTION -# define NATIVE_FILL_HARDWARE_STACKS() \ - asm volatile ("{fillc; fillr}" ::: "memory") -#else -# define NATIVE_FILL_HARDWARE_STACKS() \ +#define NATIVE_FILL_HARDWARE_STACKS__HW() \ +do { \ + /* "{fillc; fillr}" */ \ + _Pragma("no_asm_inline") \ + asm volatile (".word 0x00008001; .word 0x7000000c" ::: "memory"); \ +} while (0) +#define NATIVE_FILL_HARDWARE_STACKS__SW() \ do { \ asm volatile ( \ "{\n" \ @@ -5106,8 +5130,14 @@ do { \ offsetof(struct task_struct, thread_info)),) \ [task_ti_offset] "i" (offsetof(struct task_struct, thread_info)) \ : "ctpr1", "ctpr3", "memory"); \ + /* If CPU supports only FILLC but not FILLR, then we use the return \ + * trick above to fill RF and FILLC instruction to fill CF. */ \ + if (cpu_has(CPU_FEAT_FILLC)) { \ + /* "{fillc}" */ \ + _Pragma("no_asm_inline") \ + asm volatile (".word 0x00008001; .word 0x70000008" ::: "memory"); \ + } \ } while (0) -#endif #ifndef __ASSEMBLY__ @@ -5354,10 +5384,18 @@ do { \ __E2K_JUMP_FUNC_WITH_ARGUMENTS_8(FUNC_TO_NAME(func), \ arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +#ifdef CONFIG_CPU_HWBUG_IBRANCH +# define WORKAROUND_IBRANCH_HWBUG "{nop} {nop} \n" +#else +# define WORKAROUND_IBRANCH_HWBUG +#endif + #define E2K_GOTO_ARG0(func) \ do { \ _Pragma("no_asm_inline") \ - asm volatile ("ibranch " #func "\n" :: ); \ + asm volatile ("{ibranch " #func "}\n" \ + WORKAROUND_IBRANCH_HWBUG \ + :: ); \ } while (0) #define E2K_GOTO_ARG1(label, arg1) \ do { \ @@ -5367,6 +5405,7 @@ _Pragma("no_asm_inline") \ "addd \t 0, %0, %%dr0\n" \ "ibranch \t" #label "\n" \ "}\n" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u64_t) (arg1)) \ ); \ @@ -5380,6 +5419,7 @@ _Pragma("no_asm_inline") \ "addd \t 0, %1, %%dr1\n" \ "ibranch \t" #label "\n" \ "}\n" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u64_t) (arg1)), \ "ri" ((__e2k_u64_t) (arg2)) \ @@ -5395,6 +5435,7 @@ _Pragma("no_asm_inline") \ "addd \t 0, %2, %%dr2\n" \ "ibranch \t" #label "\n" \ "}\n" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u64_t) (arg1)), \ "ri" ((__e2k_u64_t) (arg2)), \ @@ -5412,6 +5453,7 @@ _Pragma("no_asm_inline") \ "addd \t 0, %3, %%dr3\n" \ "ibranch \t" #label "\n" \ "}\n" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u64_t) (arg1)), \ "ri" ((__e2k_u64_t) (arg2)), \ @@ -5419,10 +5461,9 @@ _Pragma("no_asm_inline") \ "ri" ((__e2k_u64_t) (arg4)) \ ); \ } while (false) -#define E2K_GOTO_AND_RETURN_ARG6(label, \ - arg1, arg2, arg3, arg4, arg5, arg6) \ +#define E2K_GOTO_ARG7(label, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ do { \ -_Pragma("no_asm_inline") \ + _Pragma("no_asm_inline") \ asm volatile ("\n" \ "{\n" \ "addd \t 0, %0, %%dr0\n" \ @@ -5433,8 +5474,8 @@ _Pragma("no_asm_inline") \ "addd \t 0, %5, %%dr5\n" \ "}\n" \ "{\n" \ - "rrd \t %%nip, %%dr6\n" \ - "ibranch \t" #label \ + "addd \t 0, %6, %%dr6\n" \ + "ibranch \t" #label "\n" \ "}\n" \ : \ : "ri" ((__e2k_u64_t) (arg1)), \ @@ -5442,7 +5483,107 @@ _Pragma("no_asm_inline") \ "ri" ((__e2k_u64_t) (arg3)), \ "ri" ((__e2k_u64_t) (arg4)), \ "ri" ((__e2k_u64_t) (arg5)), \ - "ri" ((__e2k_u64_t) (arg6)) \ + "ri" ((__e2k_u64_t) (arg6)), \ + "ri" ((__e2k_u64_t) (arg7)) \ + : "r0", "r1", "r2", "r3", "r4", "r5", "r6" \ + ); \ +} while (false) +#define E2K_SCALL_ARG7(trap_num, ret, sys_num, arg1, arg2, arg3, \ + arg4, arg5, arg6) \ +do { \ + _Pragma("no_asm_inline") \ + asm volatile ("\n" \ + "{\n" \ + "addd \t 0, %[_sys_num], %%db[0]\n" \ + "addd \t 0, %[_arg1], %%db[1]\n" \ + "addd \t 0, %[_arg2], %%db[2]\n" \ + "addd \t 0, %[_arg3], %%db[3]\n" \ + "addd \t 0, %[_arg4], %%db[4]\n" \ + "addd \t 0, %[_arg5], %%db[5]\n" \ + "}\n" \ + "{\n" \ + "addd \t 0, %[_arg6], %%db[6]\n" \ + "sdisp \t %%ctpr1, 0x"#trap_num"\n" \ + "}\n" \ + "{\n" \ + "call %%ctpr1, wbs = %#\n" \ + "}\n" \ + "{\n" \ + "addd,0,sm 0x0, %%db[0], %[_ret]\n" \ + "}\n" \ + : [_ret] "=r" (ret) \ + : [_sys_num] "ri" ((__e2k_u64_t) (sys_num)), \ + [_arg1] "ri" ((__e2k_u64_t) (arg1)), \ + [_arg2] "ri" ((__e2k_u64_t) (arg2)), \ + [_arg3] "ri" ((__e2k_u64_t) (arg3)), \ + [_arg4] "ri" ((__e2k_u64_t) (arg4)), \ + [_arg5] "ri" ((__e2k_u64_t) (arg5)), \ + [_arg6] "ri" ((__e2k_u64_t) (arg6)) \ + : "b[0]", "b[1]", "b[2]", "b[3]", "b[4]", "b[5]", \ + "b[6]", "ctpr1" \ + ); \ +} while (false) +#define E2K_GOTO_AND_RETURN_ARG6(label, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ +do { \ + _Pragma("no_asm_inline") \ + asm volatile ("\n" \ + "{\n" \ + "addd \t 0, %1, %%dr1\n" \ + "addd \t 0, %2, %%dr2\n" \ + "addd \t 0, %3, %%dr3\n" \ + "addd \t 0, %4, %%dr4\n" \ + "addd \t 0, %5, %%dr5\n" \ + "addd \t 0, %6, %%dr6\n" \ + "}\n" \ + "{\n" \ + "addd \t 0, %0, %%dr0\n" \ + "ibranch \t" #label "\n" \ + "}\n" \ + WORKAROUND_IBRANCH_HWBUG \ + : \ + : "i" ((__e2k_u64_t) (arg1)), \ + "ri" ((__e2k_u64_t) (arg2)), \ + "ri" ((__e2k_u64_t) (arg3)), \ + "ri" ((__e2k_u64_t) (arg4)), \ + "ri" ((__e2k_u64_t) (arg5)), \ + "ri" ((__e2k_u64_t) (arg6)), \ + "ri" ((__e2k_u64_t) (arg7)) \ + ); \ +} while (false) +#define E2K_SCALL_ARG7(trap_num, ret, sys_num, arg1, arg2, arg3, \ + arg4, arg5, arg6) \ +do { \ + _Pragma("no_asm_inline") \ + asm volatile ("\n" \ + "{\n" \ + "addd \t 0, %[_sys_num], %%db[0]\n" \ + "addd \t 0, %[_arg1], %%db[1]\n" \ + "addd \t 0, %[_arg2], %%db[2]\n" \ + "addd \t 0, %[_arg3], %%db[3]\n" \ + "addd \t 0, %[_arg4], %%db[4]\n" \ + "addd \t 0, %[_arg5], %%db[5]\n" \ + "}\n" \ + "{\n" \ + "addd \t 0, %[_arg6], %%db[6]\n" \ + "sdisp \t %%ctpr1, 0x"#trap_num"\n" \ + "}\n" \ + "{\n" \ + "call %%ctpr1, wbs = %#\n" \ + "}\n" \ + "{\n" \ + "addd,0,sm 0x0, %%db[0], %[_ret]\n" \ + "}\n" \ + : [_ret] "=r" (ret) \ + : [_sys_num] "ri" ((__e2k_u64_t) (sys_num)), \ + [_arg1] "ri" ((__e2k_u64_t) (arg1)), \ + [_arg2] "ri" ((__e2k_u64_t) (arg2)), \ + [_arg3] "ri" ((__e2k_u64_t) (arg3)), \ + [_arg4] "ri" ((__e2k_u64_t) (arg4)), \ + [_arg5] "ri" ((__e2k_u64_t) (arg5)), \ + [_arg6] "ri" ((__e2k_u64_t) (arg6)) \ + : "b[0]", "b[1]", "b[2]", "b[3]", "b[4]", "b[5]", \ + "b[6]", "ctpr1" \ ); \ } while (false) #define E2K_COND_GOTO(label, cond, pred_no) \ @@ -5453,6 +5594,7 @@ _Pragma("no_asm_inline") \ "\n{" \ "\nibranch \t" #label " ? ~%%pred" #pred_no \ "\n}" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u32_t) (cond)) \ : "pred" #pred_no \ @@ -5467,6 +5609,7 @@ _Pragma("no_asm_inline") \ "\naddd \t 0, %1, %%dr0 ? ~%%pred" #pred_no \ "\nibranch \t" #label " ? ~%%pred" #pred_no \ "\n}" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u32_t) (cond)), \ "ri" ((__e2k_u64_t) (arg1)) \ @@ -5483,6 +5626,7 @@ _Pragma("no_asm_inline") \ "\naddd \t 0, %2, %%dr1 ? ~%%pred" #pred_no \ "\nibranch \t" #label " ? ~%%pred" #pred_no \ "\n}" \ + WORKAROUND_IBRANCH_HWBUG \ : \ : "ri" ((__e2k_u32_t) (cond)), \ "ri" ((__e2k_u64_t) (arg1)), \ @@ -6875,6 +7019,62 @@ do { \ "{call %%ctpr2, wbs=%#}\n" \ ::: "call"); \ } while (0) + +/* + * Arithmetic operations that are atomic with regard to interrupts. + * I.e. an interrupt can arrive only before or after the operation. + */ +#define E2K_INSFD_ATOMIC(src1, src2, src3_dst) \ +do { \ + _Pragma("no_asm_inline") \ + asm ("insfd %[new_value], %[insf_params], %[reg], %[reg]" \ + : [reg] "+r" (src3_dst) \ + : [insf_params] "i" (src2), \ + [new_value] "ir" (src1)); \ +} while (0) + +#define E2K_ADDD_ATOMIC(src1_dst, src2) \ +do { \ + _Pragma("no_asm_inline") \ + asm ("addd %[reg], %[val], %[reg]" \ + : [reg] "+r" (src1_dst) \ + : [val] "ir" (src2)); \ +} while (0) + +#define E2K_SUBD_ATOMIC(src1_dst, src2) \ +do { \ + _Pragma("no_asm_inline") \ + asm ("subd %[reg], %[val], %[reg]" \ + : [reg] "+r" (src1_dst) \ + : [val] "ir" (src2)); \ +} while (0) + +#define E2K_SUBD_ATOMIC__SHRD32(src1_dst, src2, _old) \ +do { \ + asm ("{subd %[reg], %[val], %[reg]\n" \ + " shrd %[reg], 32, %[old]}" \ + : [reg] "+r" (src1_dst), \ + [old] "=r" (_old) \ + : [val] "i" (src2)); \ +} while (0) + #endif /* __ASSEMBLY__ */ +#define DECOMPRESSOR_READ_CORE_MODE() \ +({ \ + e2k_core_mode_t __core_mode; \ + register u64 __value asm("b[0]"); \ + \ + /* Cannot use "rrd %core_mode" here since the file is compiled \ + * for generic architecture so use hard-coded read */ \ + _Pragma("no_asm_inline") \ + asm (".word 0x04100011\n" \ + ".word 0x3f04c000\n" \ + ".word 0x01c00000\n" \ + ".word 0x00000000\n" \ + : "=r" (__value) ::); \ + __core_mode.word = __value; \ + __core_mode; \ +}) + #endif /* _E2K_API_H_ */ diff --git a/arch/e2k/include/asm/e2k_debug.h b/arch/e2k/include/asm/e2k_debug.h index a9383d4..01e00bf 100644 --- a/arch/e2k/include/asm/e2k_debug.h +++ b/arch/e2k/include/asm/e2k_debug.h @@ -82,8 +82,8 @@ typedef int (*parse_chain_fn_t)(e2k_mem_crs_t *crs, int flags, void *arg); #define PCS_USER 0x1 #define PCS_OPEN_IRQS 0x2 -extern notrace int parse_chain_stack(int flags, struct task_struct *p, - parse_chain_fn_t func, void *arg); +extern notrace long parse_chain_stack(int flags, struct task_struct *p, + parse_chain_fn_t func, void *arg); extern void *kernel_symtab; @@ -198,8 +198,6 @@ extern void print_chain_stack(struct stack_regs *regs, int show_reg_window); extern void copy_stack_regs(struct task_struct *task, const struct pt_regs *limit_regs, struct stack_regs *regs); -extern int parse_chain_stack(int flags, struct task_struct *p, - parse_chain_fn_t func, void *arg); extern struct stack_regs stack_regs_cache[NR_CPUS]; extern int debug_userstack; @@ -607,7 +605,7 @@ static inline int set_hardware_data_breakpoint(u64 addr, u64 size, e2k_dibcr_t dibcr; dibcr = READ_DIBCR_REG(); - AS(dibcr).stop = 1; + dibcr.stop = 1; WRITE_DIBCR_REG(dibcr); } @@ -746,17 +744,16 @@ print_aau_regs(char *str, e2k_aau_t *context, struct pt_regs *regs, "ctpr2 = 0x%llx\n" "lsr = 0x%llx\n" "ilcr = 0x%llx\n", - AW(context->aasr), - AAU_NULL(context->aasr) ? "NULL" : - AAU_READY(context->aasr) ? "READY" : - AAU_ACTIVE(context->aasr) ? "ACTIVE" : - AAU_STOPPED(context->aasr) ? "STOPPED": + AW(regs->aasr), + AAU_NULL(regs->aasr) ? "NULL" : + AAU_READY(regs->aasr) ? "READY" : + AAU_ACTIVE(regs->aasr) ? "ACTIVE" : + AAU_STOPPED(regs->aasr) ? "STOPPED" : "undefined", - AS(context->aasr).iab, - AS(context->aasr).stb, + regs->aasr.iab, regs->aasr.stb, AW(regs->ctpr2), regs->lsr, regs->ilcr); - if (AAU_STOPPED(context->aasr)) { + if (AAU_STOPPED(regs->aasr)) { pr_info("aaldv = 0x%llx\n" "aaldm = 0x%llx\n", AW(context->aaldv), AW(context->aaldm)); @@ -767,7 +764,7 @@ print_aau_regs(char *str, e2k_aau_t *context, struct pt_regs *regs, "AALDM will not be printed\n"); } - if (AS(context->aasr).iab) { + if (regs->aasr.iab) { for (i = 0; i < 32; i++) { pr_info("aad[%d].hi = 0x%llx ", i, AW(context->aads[i]).hi); @@ -794,7 +791,7 @@ print_aau_regs(char *str, e2k_aau_t *context, struct pt_regs *regs, "AAINCR, AAINCR_TAGS\n"); } - if (AS(context->aasr).stb) { + if (regs->aasr.stb) { for (i = 0; i < 16; i++) { pr_info("aasti[%d] = 0x%llx\n", i, (old_iset) ? (u64) (u32) context->aastis[i] : diff --git a/arch/e2k/include/asm/e2k_ptypes.h b/arch/e2k/include/asm/e2k_ptypes.h index be09e23..ca3bafd 100644 --- a/arch/e2k/include/asm/e2k_ptypes.h +++ b/arch/e2k/include/asm/e2k_ptypes.h @@ -172,7 +172,7 @@ typedef union { /* Common array pointer */ long lo; long hi; } word; -} e2k_ptr_t; +} __aligned(16) e2k_ptr_t; #define R_ENABLE 0x1 #define W_ENABLE 0x2 diff --git a/arch/e2k/include/asm/e2s.h b/arch/e2k/include/asm/e2s.h index 7557222..0c105b0 100644 --- a/arch/e2k/include/asm/e2s.h +++ b/arch/e2k/include/asm/e2s.h @@ -20,9 +20,6 @@ extern void setup_APIC_vector_handler(int vector, extern void sic_error_interrupt(struct pt_regs *regs); #endif -#define E2S_CPU_VENDOR ES2_CPU_VENDOR -#define E2S_CPU_FAMILY ES2_CPU_FAMILY - #define E2S_NR_NODE_CPUS 4 #define E2S_MAX_NR_NODE_CPUS E2S_NR_NODE_CPUS diff --git a/arch/e2k/include/asm/e8c.h b/arch/e2k/include/asm/e8c.h index b106ec7..a7b3009 100644 --- a/arch/e2k/include/asm/e8c.h +++ b/arch/e2k/include/asm/e8c.h @@ -20,9 +20,6 @@ extern void setup_APIC_vector_handler(int vector, extern void sic_error_interrupt(struct pt_regs *regs); #endif -#define E8C_CPU_VENDOR ES2_CPU_VENDOR -#define E8C_CPU_FAMILY ES2_CPU_FAMILY - #define E8C_NR_NODE_CPUS 8 #define E8C_MAX_NR_NODE_CPUS 16 diff --git a/arch/e2k/include/asm/e8c2.h b/arch/e2k/include/asm/e8c2.h index 5101212..f141e3b 100644 --- a/arch/e2k/include/asm/e8c2.h +++ b/arch/e2k/include/asm/e8c2.h @@ -20,9 +20,6 @@ extern void setup_APIC_vector_handler(int vector, extern void sic_error_interrupt(struct pt_regs *regs); #endif -#define E8C2_CPU_VENDOR ES2_CPU_VENDOR -#define E8C2_CPU_FAMILY 5 - #define E8C2_NR_NODE_CPUS E8C_NR_NODE_CPUS #define E8C2_MAX_NR_NODE_CPUS E8C_MAX_NR_NODE_CPUS diff --git a/arch/e2k/include/asm/epicdef.h b/arch/e2k/include/asm/epicdef.h index 94673c4..36c5a74 100644 --- a/arch/e2k/include/asm/epicdef.h +++ b/arch/e2k/include/asm/epicdef.h @@ -5,8 +5,8 @@ * Constants for e2k EPICs (CEPIC, IOEPIC) */ -#define IO_EPIC_DEFAULT_PHYS_BASE 0xfec00000 -#define EPIC_DEFAULT_PHYS_BASE 0xfee00000 +#define IO_EPIC_DEFAULT_PHYS_BASE 0xfec00000UL +#define EPIC_DEFAULT_PHYS_BASE 0xfee00000UL #include diff --git a/arch/e2k/include/asm/es2.h b/arch/e2k/include/asm/es2.h index 5da081d..a7cf2b1 100644 --- a/arch/e2k/include/asm/es2.h +++ b/arch/e2k/include/asm/es2.h @@ -22,9 +22,6 @@ extern void setup_APIC_vector_handler(int vector, extern void eldsp_interrupt(struct pt_regs *regs); #endif -#define ES2_CPU_VENDOR "Elbrus-MCST" -#define ES2_CPU_FAMILY 4 - #define ES2_NR_NODE_CPUS 2 #define ES2_MAX_NR_NODE_CPUS 4 diff --git a/arch/e2k/include/asm/fast_syscalls.h b/arch/e2k/include/asm/fast_syscalls.h index b210806..2a66b20 100644 --- a/arch/e2k/include/asm/fast_syscalls.h +++ b/arch/e2k/include/asm/fast_syscalls.h @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include struct fast_syscalls_data { struct timekeeper *tk; @@ -41,6 +44,7 @@ int native_do_fast_clock_gettime(const clockid_t which_clock, int native_fast_sys_clock_gettime(const clockid_t which_clock, struct timespec __user *tp); int native_do_fast_gettimeofday(struct timeval *tv); +int native_do_fast_sys_set_return(u64 ip, int flags); int native_fast_sys_siggetmask(u64 __user *oset, size_t sigsetsize); #ifdef CONFIG_KVM_GUEST_KERNEL @@ -58,22 +62,103 @@ do_fast_clock_gettime(const clockid_t which_clock, struct timespec *tp) return native_do_fast_clock_gettime(which_clock, tp); } -static inline int -fast_sys_clock_gettime(const clockid_t which_clock, struct timespec __user *tp) -{ - return native_fast_sys_clock_gettime(which_clock, tp); -} - static inline int do_fast_gettimeofday(struct timeval *tv) { return native_do_fast_gettimeofday(tv); } + static inline int -fast_sys_siggetmask(u64 __user *oset, size_t sigsetsize) +do_fast_sys_set_return(u64 ip, int flags) { - return native_fast_sys_siggetmask(oset, sigsetsize); + return native_do_fast_sys_set_return(ip, flags); } + +#ifdef CONFIG_KVM_HOST_MODE +extern long ret_from_fast_sys_call(void); + +static inline long kvm_return_from_fast_syscall(thread_info_t *ti, long arg1) +{ + /* Restore vcpu state reg old value (guest user) */ + HOST_VCPU_STATE_REG_RESTORE(ti); + + /* TODO: Cleanup guest kernel's pgds in shadow page table */ + + /* Get current parameters of top chain stack frame */ + e2k_cr0_lo_t cr0_lo = READ_CR0_LO_REG(); + e2k_cr0_hi_t cr0_hi = READ_CR0_HI_REG(); + e2k_cr1_lo_t cr1_lo = READ_CR1_LO_REG(); + e2k_cr1_hi_t cr1_hi = READ_CR1_HI_REG(); + + /* + * Correct ip in current chain stack frame to return to guest user + * through special trap function ret_from_fast_syscall_trampoline + */ + AS(cr0_lo).pf = -1ULL; + AS(cr0_hi).ip = ((u64)ret_from_fast_sys_call) >> 3; + AS(cr1_lo).psr = AW(E2K_KERNEL_PSR_DISABLED); + AS(cr1_lo).cui = KERNEL_CODES_INDEX; + + WRITE_CR0_LO_REG(cr0_lo); + WRITE_CR0_HI_REG(cr0_hi); + WRITE_CR1_LO_REG(cr1_lo); + WRITE_CR1_HI_REG(cr1_hi); + + return arg1; +} + +static inline long kvm_set_return_user_ip(thread_info_t *gti, u64 ip, int flags) +{ + e2k_pcsp_lo_t pcsp_lo; + e2k_pcsp_hi_t pcsp_hi; + e2k_cr0_hi_t cr0_hi; + e2k_mem_crs_t *frame, *base; + u64 prev_ip; + + E2K_FLUSHC; + + if (unlikely(flags)) + return -EINVAL; + + if (unlikely(ip >= USER_DS.seg)) + return -EFAULT; + + pcsp_hi = READ_PCSP_HI_REG(); /* We don't use %pcsp_hi.size */ + pcsp_lo = READ_PCSP_LO_REG(); + + base = (e2k_mem_crs_t *) GET_PCS_BASE(>i->u_hw_stack); + frame = (e2k_mem_crs_t *) (AS(pcsp_lo).base + AS(pcsp_hi).ind); + + do { + --frame; + + cr0_hi = frame->cr0_hi; + prev_ip = AS(cr0_hi).ip << 3; + } while (unlikely(prev_ip >= GUEST_TASK_SIZE && frame > base)); + + /* No user frames above? */ + if (unlikely(prev_ip >= GUEST_TASK_SIZE)) + return -EPERM; + + /* Modify stack */ + AS(cr0_hi).ip = ip >> 3; + frame->cr0_hi = cr0_hi; + return 0; +} +#endif /* CONFIG_KVM_HOST_MODE */ + +/* trap table entry started by direct branch (it is closer to fast system */ +/* call wirthout switch and use user local data stack */ +#define goto_ttable_entry1_args3(sys_num, arg1, arg2, ret) \ + E2K_GOTO_ARG7(native_ttable_entry1, sys_num, arg1, arg2, 0, 0, 0, 0) +#define goto_ttable_entry1_args4(sys_num, arg1, arg2, arg3, ret) \ + E2K_GOTO_ARG7(native_ttable_entry1, sys_num, arg1, arg2, arg3, 0, 0, 0) + +#define goto_ttable_entry3_args3(sys_num, arg1, arg2, ret) \ + E2K_GOTO_ARG7(native_ttable_entry3, sys_num, arg1, arg2, 0, 0, 0, 0) +#define goto_ttable_entry3_args4(sys_num, arg1, arg2, arg3, ret) \ + E2K_GOTO_ARG7(native_ttable_entry3, sys_num, arg1, arg2, arg3, 0, 0, 0) + #endif /* ! CONFIG_KVM_GUEST_KERNEL */ /* @@ -209,29 +294,18 @@ typedef long (*ttable_entry_args4)(int sys_num, u64 arg1, u64 arg2, u64 arg3); #define ttable_entry3_args4(sys_num, arg1, arg2) \ ((ttable_entry_args4)(get_ttable_entry3))(sys_num, arg1, arg2, arg3) -/* trap table entry started by direct branch (it is closer to fast system */ -/* call wirthout switch and use user local data stack */ -#define goto_ttable_entry_args3(entry_label, sys_num, arg1, arg2) \ - E2K_GOTO_ARG3(entry_label, sys_num, arg1, arg2) -#define goto_ttable_entry_args4(entry_label, sys_num, arg1, arg2, arg3) \ - E2K_GOTO_ARG4(entry_label, sys_num, arg1, arg2, arg3) -#define goto_ttable_entry3_args3(sys_num, arg1, arg2) \ - goto_ttable_entry_args3(ttable_entry3, sys_num, arg1, arg2) -#define goto_ttable_entry3_args4(sys_num, arg1, arg2, arg3) \ - goto_ttable_entry_args4(ttable_entry3, sys_num, arg1, arg2, arg3) - - -#define ttable_entry_clock_gettime(which, time) \ -/* ibranch */ goto_ttable_entry3_args3(__NR_clock_gettime, which, time) +#define ttable_entry_clock_gettime(which, time, ret) \ +/* ibranch */ goto_ttable_entry3_args3(__NR_clock_gettime, which, time, ret) /* call ttable_entry3_args3(__NR_clock_gettime, which, time) */ -#define ttable_entry_gettimeofday(tv, tz) \ -/* ibranch */ goto_ttable_entry3_args3(__NR_gettimeofday, tv, tz) +#define ttable_entry_gettimeofday(tv, tz, ret) \ +/* ibranch */ goto_ttable_entry3_args3(__NR_gettimeofday, tv, tz, ret) /* ttable_entry3_args3(__NR_gettimeofday, tv, tz) */ -#define ttable_entry_sigprocmask(how, nset, oset) \ -/* ibranch */ goto_ttable_entry3_args4(__NR_sigprocmask, how, nset, oset) +#define ttable_entry_sigprocmask(how, nset, oset, ret) \ +/* ibranch */ goto_ttable_entry3_args4(__NR_sigprocmask, how, \ + nset, oset, ret) /* ttable_entry3_args4(__NR_sigprocmask, how, nset, oset) */ -#define ttable_entry_getcpu(cpup, nodep, unused) \ -/* ibranch */ goto_ttable_entry3_args4(__NR_getcpu, cpup, nodep, unused) +#define ttable_entry_getcpu(cpup, nodep, unused, ret) \ +/* ibranch */ goto_ttable_entry3_args4(__NR_getcpu, cpup, nodep, unused, ret) /* ttable_entry3_args4(__NR_getcpu, cpup, nodep, unused) */ static inline int @@ -242,18 +316,13 @@ FAST_SYS_CLOCK_GETTIME(const clockid_t which_clock, struct timespec __user *tp) prefetch_nospec(&fsys_data); -#ifdef CONFIG_KVM_HOST_MODE - if (unlikely(test_ti_status_flag(ti, TS_HOST_AT_VCPU_MODE))) - ttable_entry_clock_gettime((u64) which_clock, (u64) tp); -#endif - tp = (typeof(tp)) ((u64) tp & E2K_VA_MASK); if (unlikely((u64) tp + sizeof(struct timespec) > ti->addr_limit.seg)) return -EFAULT; r = do_fast_clock_gettime(which_clock, tp); if (unlikely(r)) - ttable_entry_clock_gettime((u64) which_clock, (u64) tp); + ttable_entry_clock_gettime(which_clock, tp, r); return r; } @@ -278,9 +347,6 @@ FAST_SYS_SIGGETMASK(u64 __user *oset, size_t sigsetsize) { struct thread_info *const ti = READ_CURRENT_REG(); struct task_struct *task = thread_info_task(ti); -#ifdef CONFIG_KVM_HOST_MODE - bool guest = test_ti_status_flag(ti, TS_HOST_AT_VCPU_MODE); -#endif u64 set; set = task->blocked.sig[0]; @@ -288,11 +354,6 @@ FAST_SYS_SIGGETMASK(u64 __user *oset, size_t sigsetsize) if (unlikely(sigsetsize != 8)) return -EINVAL; -#ifdef CONFIG_KVM_HOST_MODE - if (unlikely(guest)) - ttable_entry_sigprocmask((u64) 0, (u64) NULL, (u64) oset); -#endif - oset = (typeof(oset)) ((u64) oset & E2K_VA_MASK); if (unlikely((u64) oset + sizeof(sigset_t) > ti->addr_limit.seg)) return -EFAULT; @@ -310,9 +371,7 @@ struct getcpu_cache; int fast_sys_getcpu(unsigned __user *cpup, unsigned __user *nodep, struct getcpu_cache __user *unused); int fast_sys_siggetmask(u64 __user *oset, size_t sigsetsize); -struct ucontext; int fast_sys_getcontext(struct ucontext __user *ucp, size_t sigsetsize); -int fast_sys_set_return(u64 ip, int flags); struct compat_timespec; int compat_fast_sys_clock_gettime(const clockid_t which_clock, @@ -321,7 +380,6 @@ struct compat_timeval; int compat_fast_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz); int compat_fast_sys_siggetmask(u32 __user *oset, size_t sigsetsize); -struct ucontext_32; int compat_fast_sys_getcontext(struct ucontext_32 __user *ucp, size_t sigsetsize); int compat_fast_sys_set_return(u32 ip, int flags); @@ -333,5 +391,97 @@ int protected_fast_sys_gettimeofday(u32 tags, int protected_fast_sys_getcpu(u32 tags, u64 arg2, u64 arg3, u64 arg4, u64 arg5); int protected_fast_sys_siggetmask(u32 tags, u64 arg2, u64 arg3, size_t sigsetsize); int protected_fast_sys_getcontext(u32 tags, u64 arg2, u64 arg3, size_t sigsetsize); -#endif /* _ASM_E2K_FAST_SYSCALLS_H */ +/* Inlined handlers for fast syscalls */ + +notrace __interrupt __section(.entry_handlers) +static inline int _fast_sys_gettimeofday(struct timeval __user *__restrict tv, + struct timezone __user *__restrict tz) +{ + struct thread_info *const ti = READ_CURRENT_REG(); + int ret; + + prefetch_nospec(&fsys_data); + + tv = (typeof(tv)) ((u64) tv & E2K_VA_MASK); + tz = (typeof(tz)) ((u64) tz & E2K_VA_MASK); + if (unlikely((u64) tv + sizeof(struct timeval) > ti->addr_limit.seg + || (u64) tz + sizeof(struct timezone) + > ti->addr_limit.seg)) + return -EFAULT; + + if (likely(tv)) { + ret = do_fast_gettimeofday(tv); + if (unlikely(ret)) + ttable_entry_gettimeofday((u64) tv, (u64) tz, ret); + } else { + ret = 0; + } + + if (tz) { + tz->tz_minuteswest = sys_tz.tz_minuteswest; + tz->tz_dsttime = sys_tz.tz_dsttime; + } + + return ret; +} + +notrace __interrupt __section(.entry_handlers) +static inline int _fast_sys_clock_gettime(const clockid_t which_clock, + struct timespec __user *tp) +{ + return FAST_SYS_CLOCK_GETTIME(which_clock, tp); +} + +notrace __interrupt __section(.entry_handlers) +static inline int _fast_sys_siggetmask(u64 __user *oset, size_t sigsetsize) +{ + return FAST_SYS_SIGGETMASK(oset, sigsetsize); +} + +notrace __interrupt __section(.entry_handlers) +static inline int _fast_sys_getcontext(struct ucontext __user *ucp, + size_t sigsetsize) +{ + struct thread_info *const ti = READ_CURRENT_REG(); + struct task_struct *task = thread_info_task(ti); + + register u64 pcsp_lo, pcsp_hi; + register u32 fpcr, fpsr, pfpfr; + u64 set, key; + + BUILD_BUG_ON(sizeof(task->blocked.sig[0]) != 8); + set = task->blocked.sig[0]; + + if (unlikely(sigsetsize != 8)) + return -EINVAL; + + ucp = (typeof(ucp)) ((u64) ucp & E2K_VA_MASK); + if (unlikely((u64) ucp + sizeof(struct ucontext) > ti->addr_limit.seg)) + return -EFAULT; + + key = context_ti_key_fast_syscall(ti); + + E2K_GETCONTEXT(fpcr, fpsr, pfpfr, pcsp_lo, pcsp_hi); + + /* We want stack to point to user frame that called us */ + pcsp_hi -= SZ_OF_CR; + + *((u64 *) &ucp->uc_sigmask) = set; + ucp->uc_mcontext.sbr = key; + ucp->uc_mcontext.pcsp_lo = pcsp_lo; + ucp->uc_mcontext.pcsp_hi = pcsp_hi; + ucp->uc_extra.fpcr = fpcr; + ucp->uc_extra.fpsr = fpsr; + ucp->uc_extra.pfpfr = pfpfr; + + return 0; +} + +notrace __interrupt __section(.entry_handlers) +static inline int fast_sys_set_return(u64 ip, int flags) +{ + return do_fast_sys_set_return(ip, flags); +} + +#endif /* _ASM_E2K_FAST_SYSCALLS_H */ diff --git a/arch/e2k/include/asm/fcntl.h b/arch/e2k/include/asm/fcntl.h deleted file mode 100644 index 46ab12d..0000000 --- a/arch/e2k/include/asm/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/asm/glob_regs.h b/arch/e2k/include/asm/glob_regs.h index 20b95df..8aa511a 100644 --- a/arch/e2k/include/asm/glob_regs.h +++ b/arch/e2k/include/asm/glob_regs.h @@ -9,8 +9,6 @@ #ifdef __KERNEL__ -#include - /* * MAP of global registers using for the user purposes */ diff --git a/arch/e2k/include/asm/ioctl.h b/arch/e2k/include/asm/ioctl.h deleted file mode 100644 index b279fe0..0000000 --- a/arch/e2k/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/asm/ioctls.h b/arch/e2k/include/asm/ioctls.h deleted file mode 100644 index dd12291..0000000 --- a/arch/e2k/include/asm/ioctls.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _E2K_IOCTLS_H_ -#define _E2K_IOCTLS_H_ - -/* - * We are too far from real ioctl handling and it is difficult to predict - * any errors now. So I accept i386(ia64) ioctl's stuff as the basis. - */ - - -#include -#include - -#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ -#define TIOCGDB 0x547F /* enable GDB stub mode on this tty */ - -#endif /* _E2K_IOCTLS_H_ */ diff --git a/arch/e2k/include/asm/ipcbuf.h b/arch/e2k/include/asm/ipcbuf.h deleted file mode 100644 index dc3376b..0000000 --- a/arch/e2k/include/asm/ipcbuf.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _E2K_IPCBUF_H_ -#define _E2K_IPCBUF_H_ - -/* - * The ipc64_perm structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 32-bit seq - * - 2 miscellaneous 64-bit values - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned short seq; - unsigned short __pad1; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _E2K_IPCBUF_H_ */ diff --git a/arch/e2k/include/asm/kdebug.h b/arch/e2k/include/asm/kdebug.h index 5679fca..b90ddc4 100644 --- a/arch/e2k/include/asm/kdebug.h +++ b/arch/e2k/include/asm/kdebug.h @@ -11,12 +11,11 @@ enum die_val { DIE_BREAKPOINT }; -extern void printk_address(unsigned long address, int reliable); +extern void printk_address(unsigned long address, int reliable) __cold; extern void show_trace(struct task_struct *t, struct pt_regs *regs, - unsigned long *sp, unsigned long bp); -extern void __show_regs(struct pt_regs *regs, int all); -extern void show_regs(struct pt_regs *regs); -extern unsigned long oops_begin(void); -extern void oops_end(unsigned long, struct pt_regs *, int signr); + unsigned long *sp, unsigned long bp) __cold; +extern void __show_regs(struct pt_regs *regs, int all) __cold; +extern void show_regs(struct pt_regs *regs) __cold; +extern void die(const char *str, struct pt_regs *regs, long err) __cold; #endif /* _ASM_E2K_KDEBUG_H */ diff --git a/arch/e2k/include/asm/kvm/aau_regs_access.h b/arch/e2k/include/asm/kvm/aau_regs_access.h index 01a3a67..aaa8ba3 100644 --- a/arch/e2k/include/asm/kvm/aau_regs_access.h +++ b/arch/e2k/include/asm/kvm/aau_regs_access.h @@ -192,8 +192,7 @@ }) #define KVM_GET_AAU_AASTI_TAG() \ GUEST_GET_AAU_SREG(aasti_tags) -#define KVM_GET_AAU_AASR() \ - GUEST_GET_AAU_SREG(aasr) +#define KVM_GET_AAU_AASR() GUEST_GET_CPU_SREG(AASR) #define KVM_GET_AAU_AAFSTR() \ GUEST_GET_AAU_SREG(aafstr) #define KVM_GET_AAU_AALDI(AALDI_no, lval, rval) \ @@ -289,8 +288,7 @@ do { \ }) #define KVM_SET_AAU_AASTI_TAG(val) \ GUEST_SET_AAU_SREG(aasti_tags, val) -#define KVM_SET_AAU_AASR(val) \ - GUEST_SET_AAU_SREG(aasr, val) +#define KVM_SET_AAU_AASR(val) GUEST_SET_CPU_SREG(AASR, val) #define KVM_SET_AAU_AAFSTR(val) \ GUEST_SET_AAU_SREG(aafstr, val) #define KVM_SET_AAU_AALDI(AALDI_no, lval, rval) \ @@ -559,9 +557,9 @@ kvm_read_aaldm_reg(e2k_aaldm_t *aaldm) kvm_read_aaldm_reg_value(&aaldm->lo, &aaldm->hi); } static inline void -kvm_write_aaldm_reg(e2k_aaldm_t *aaldm) +kvm_write_aaldm_reg(e2k_aaldm_t aaldm) { - kvm_write_aaldm_reg_value(aaldm->lo, aaldm->hi); + kvm_write_aaldm_reg_value(aaldm.lo, aaldm.hi); } static inline void kvm_read_aaldv_reg_value(u32 *lo_value, u32 *hi_value) @@ -583,9 +581,9 @@ kvm_read_aaldv_reg(e2k_aaldv_t *aaldv) kvm_read_aaldv_reg_value(&aaldv->lo, &aaldv->hi); } static inline void -kvm_write_aaldv_reg(e2k_aaldv_t *aaldv) +kvm_write_aaldv_reg(e2k_aaldv_t aaldv) { - kvm_write_aaldm_reg_value(aaldv->lo, aaldv->hi); + kvm_write_aaldm_reg_value(aaldv.lo, aaldv.hi); } static inline void @@ -647,17 +645,17 @@ static inline void read_aaldm_reg(e2k_aaldm_t *aaldm) { kvm_read_aaldm_reg_value(&aaldm->lo, &aaldm->hi); } -static inline void write_aaldm_reg(e2k_aaldm_t *aaldm) +static inline void write_aaldm_reg(e2k_aaldm_t aaldm) { - kvm_write_aaldm_reg_value(aaldm->lo, aaldm->hi); + kvm_write_aaldm_reg_value(aaldm.lo, aaldm.hi); } static inline void read_aaldv_reg(e2k_aaldv_t *aaldv) { kvm_read_aaldv_reg_value(&aaldv->lo, &aaldv->hi); } -static inline void write_aaldv_reg(e2k_aaldv_t *aaldv) +static inline void write_aaldv_reg(e2k_aaldv_t aaldv) { - kvm_write_aaldm_reg_value(aaldv->lo, aaldv->hi); + kvm_write_aaldm_reg_value(aaldv.lo, aaldv.hi); } #define clear_apb() kvm_clear_apb() diff --git a/arch/e2k/include/asm/kvm/copy-hw-stacks.h b/arch/e2k/include/asm/kvm/copy-hw-stacks.h index 55a35e6..c4ea67c 100644 --- a/arch/e2k/include/asm/kvm/copy-hw-stacks.h +++ b/arch/e2k/include/asm/kvm/copy-hw-stacks.h @@ -398,22 +398,12 @@ pv_vcpu_user_hw_stacks_prepare(struct kvm_vcpu *vcpu, pt_regs_t *regs, "set to 0x%x\n", stacks->pcshtp); } else if (!syscall && pcshtp == 0 && guest_user) { - e2k_pcsp_hi_t k_pcsp_hi; - unsigned long flags; + /* in this case the trampoline frame is added into the guest */ + /* kernel chain stack */ /* set flag for unconditional injection to do not copy */ /* from guest user space */ regs->need_inject = true; - - /* reserve one bottom frames for trampoline */ - /* the guest handler replaces guest user trapped frame */ - raw_all_irq_save(flags); - NATIVE_FLUSHC; - k_pcsp_hi = NATIVE_NV_READ_PCSP_HI_REG(); - BUG_ON(k_pcsp_hi.PCSP_hi_ind); - k_pcsp_hi.PCSP_hi_ind += 1 * SZ_OF_CR; - NATIVE_NV_NOIRQ_WRITE_PCSP_HI_REG(k_pcsp_hi); - raw_all_irq_restore(flags); } /* diff --git a/arch/e2k/include/asm/kvm/gregs.h b/arch/e2k/include/asm/kvm/gregs.h index 4b09c01..942cb5d 100644 --- a/arch/e2k/include/asm/kvm/gregs.h +++ b/arch/e2k/include/asm/kvm/gregs.h @@ -108,6 +108,27 @@ ONLY_RESTORE_KERNEL_GREGS(task__, cpu_id__, cpu_off__); \ }) +#define HOST_VCPU_STATE_REG_SWITCH_TO_GUEST(vcpu) \ +({ \ + machine.save_kernel_gregs(&vcpu->arch.host_ctxt.k_gregs); \ + \ + u64 guest_vs = GET_GUEST_VCPU_STATE_POINTER(vcpu); \ + E2K_SET_DGREG(GUEST_VCPU_STATE_GREG, guest_vs); \ +}) + +#define HOST_VCPU_STATE_REG_RESTORE(host_ti) \ +({ \ + struct kvm_vcpu *vcpu = host_ti->vcpu; \ + \ + struct kernel_gregs h_gregs; \ + machine.save_kernel_gregs(&h_gregs); \ + \ + NATIVE_RESTORE_KERNEL_GREGS(&vcpu->arch.host_ctxt.k_gregs); \ + machine.save_kernel_gregs(&host_ti->k_gregs_light); \ + \ + NATIVE_RESTORE_KERNEL_GREGS(&h_gregs); \ +}) + #define HOST_RESTORE_KERNEL_GREGS_AS_LIGHT(_ti) \ HOST_RESTORE_HOST_GREGS_FROM(&(_ti)->k_gregs_light, false) diff --git a/arch/e2k/include/asm/kvm/guest.h b/arch/e2k/include/asm/kvm/guest.h index d9bfbe0..93093e9 100644 --- a/arch/e2k/include/asm/kvm/guest.h +++ b/arch/e2k/include/asm/kvm/guest.h @@ -66,6 +66,7 @@ typedef struct kvm_cpu_regs { u64 CPU_SBBP[SBBP_ENTRIES_NUM]; e2k_wd_t CPU_WD; /* Window Descriptor Register */ e2k_bgr_t CPU_BGR; /* Base Global Register */ + e2k_aasr_t CPU_AASR; e2k_lsr_t CPU_LSR; /* Loop Status Register */ e2k_lsr_t CPU_LSR1; /* */ e2k_ilcr_t CPU_ILCR; /* Initial Loop Counters Register */ diff --git a/arch/e2k/include/asm/kvm/guest/aau_context.h b/arch/e2k/include/asm/kvm/guest/aau_context.h index ea0e78b..e71f345 100644 --- a/arch/e2k/include/asm/kvm/guest/aau_context.h +++ b/arch/e2k/include/asm/kvm/guest/aau_context.h @@ -29,13 +29,13 @@ } \ }) -#define KVM_RESTORE_AAU_MASK_REGS(aau_context) \ +#define KVM_RESTORE_AAU_MASK_REGS(aaldm, aaldv, aau_context) \ ({ \ if (IS_HV_GM()) { \ E2K_CMD_SEPARATOR; \ - NATIVE_RESTORE_AAU_MASK_REGS(aau_context); \ + NATIVE_RESTORE_AAU_MASK_REGS(aaldm, aaldv, aau_context); \ } else { \ - PREFIX_RESTORE_AAU_MASK_REGS(KVM, kvm, aau_context); \ + PREFIX_RESTORE_AAU_MASK_REGS(KVM, kvm, aaldm, aaldv, aau_context); \ } \ }) @@ -155,30 +155,30 @@ } \ }) -#define KVM_GET_AAU_CONTEXT(context) \ -({ \ +#define KVM_GET_AAU_CONTEXT(context, aasr) \ +do { \ if (IS_HV_GM()) { \ - NATIVE_GET_AAU_CONTEXT(context); \ + NATIVE_GET_AAU_CONTEXT(context, aasr); \ } else { \ - PREFIX_GET_AAU_CONTEXT(KVM, kvm, V5, v5, context); \ + PREFIX_GET_AAU_CONTEXT(KVM, kvm, V5, v5, context, aasr); \ } \ -}) -#define KVM_GET_AAU_CONTEXT_V2(context) \ -({ \ +} while (0) +#define KVM_GET_AAU_CONTEXT_V2(context, aasr) \ +do { \ if (IS_HV_GM()) { \ - NATIVE_GET_AAU_CONTEXT_V2(context); \ + NATIVE_GET_AAU_CONTEXT_V2(context, aasr); \ } else { \ - PREFIX_GET_AAU_CONTEXT(KVM, kvm, V5, v5, context); \ + PREFIX_GET_AAU_CONTEXT(KVM, kvm, V5, v5, context, aasr); \ } \ -}) -#define KVM_GET_AAU_CONTEXT_V5(context) \ -({ \ +} while (0) +#define KVM_GET_AAU_CONTEXT_V5(context, aasr) \ +do { \ if (IS_HV_GM()) { \ - NATIVE_GET_AAU_CONTEXT_V5(context); \ + NATIVE_GET_AAU_CONTEXT_V5(context, aasr); \ } else { \ - PREFIX_GET_AAU_CONTEXT(KVM, kvm, V5, v5, context); \ + PREFIX_GET_AAU_CONTEXT(KVM, kvm, V5, v5, context, aasr); \ } \ -}) +} while (0) static inline void kvm_save_aaldi(u64 *aaldis) @@ -238,24 +238,13 @@ kvm_get_synchronous_part_v5(e2k_aau_t *context) * It's taken that aasr was get earlier(from get_aau_context caller) * and comparison with aasr.iab was taken. */ -static inline void -kvm_get_aau_context(e2k_aau_t *context) +static inline void kvm_get_aau_context(e2k_aau_t *context, e2k_aasr_t aasr) { - KVM_GET_AAU_CONTEXT(context); -} -static inline void -kvm_get_aau_context_v2(e2k_aau_t *context) -{ - KVM_GET_AAU_CONTEXT_V2(context); -} -static inline void -kvm_get_aau_context_v5(e2k_aau_t *context) -{ - KVM_GET_AAU_CONTEXT_V5(context); + KVM_GET_AAU_CONTEXT(context, aasr); } -static __always_inline void -kvm_set_aau_context(e2k_aau_t *context) +static __always_inline void kvm_set_aau_context(e2k_aau_t *context, + const e2k_aalda_t *aalda, e2k_aasr_t aasr) { /* AAU contesxt should restore host */ } @@ -266,8 +255,8 @@ kvm_set_aau_context(e2k_aau_t *context) #define SAVE_AAU_MASK_REGS(aau_context, aasr) \ KVM_SAVE_AAU_MASK_REGS(aau_context, aasr) -#define RESTORE_AAU_MASK_REGS(aau_context) \ - KVM_RESTORE_AAU_MASK_REGS(aau_context) +#define RESTORE_AAU_MASK_REGS(aaldm, aaldv, aau_context) \ + KVM_RESTORE_AAU_MASK_REGS(aaldm, aaldv, aau_context) #define SAVE_AADS(aau_regs) \ KVM_SAVE_AADS(aau_regs) @@ -295,8 +284,8 @@ kvm_set_aau_context(e2k_aau_t *context) #define GET_SYNCHRONOUS_PART_V5(context) \ KVM_GET_SYNCHRONOUS_PART_V5(context) -#define GET_AAU_CONTEXT_V2(context) KVM_GET_AAU_CONTEXT_V2(context) -#define GET_AAU_CONTEXT_V5(context) KVM_GET_AAU_CONTEXT_V5(context) +#define GET_AAU_CONTEXT_V2(context, aasr) KVM_GET_AAU_CONTEXT_V2(context, aasr) +#define GET_AAU_CONTEXT_V5(context, aasr) KVM_GET_AAU_CONTEXT_V5(context, aasr) static inline void save_aaldi(u64 *aaldis) @@ -309,15 +298,15 @@ set_array_descriptors(e2k_aau_t *context) kvm_set_array_descriptors(context); } static inline void -get_aau_context(e2k_aau_t *context) +get_aau_context(e2k_aau_t *context, e2k_aasr_t aasr) { - kvm_get_aau_context(context); + kvm_get_aau_context(context, aasr); } -static __always_inline void -set_aau_context(e2k_aau_t *context) +static __always_inline void set_aau_context(e2k_aau_t *context, + const e2k_aalda_t *aalda, e2k_aasr_t aasr) { - kvm_set_aau_context(context); + kvm_set_aau_context(context, aalda, aasr); } #endif /* CONFIG_KVM_GUEST_KERNEL */ diff --git a/arch/e2k/include/asm/kvm/guest/e2k_virt.h b/arch/e2k/include/asm/kvm/guest/e2k_virt.h index 6eba659..9132e0a 100644 --- a/arch/e2k/include/asm/kvm/guest/e2k_virt.h +++ b/arch/e2k/include/asm/kvm/guest/e2k_virt.h @@ -4,7 +4,6 @@ #include #include -#define E2K_VIRT_CPU_VENDOR "Elbrus-MCST" #define E2K_VIRT_CPU_FAMILY 0xff #define E2K_VIRT_CPU_MODEL IDR_E2K_VIRT_MDL #define E2K_VIRT_CPU_REVISION 16 /* 2016 year */ diff --git a/arch/e2k/include/asm/kvm/guest/fast_syscalls.h b/arch/e2k/include/asm/kvm/guest/fast_syscalls.h index 51638f7..94e371d 100644 --- a/arch/e2k/include/asm/kvm/guest/fast_syscalls.h +++ b/arch/e2k/include/asm/kvm/guest/fast_syscalls.h @@ -11,32 +11,43 @@ int kvm_fast_sys_clock_gettime(const clockid_t which_clock, struct timespec __user *tp); int kvm_do_fast_gettimeofday(struct timeval *tv); int kvm_fast_sys_siggetmask(u64 __user *oset, size_t sigsetsize); +int kvm_do_fast_sys_set_return(u64 ip, int flags); #ifdef CONFIG_KVM_GUEST_KERNEL + +#define __NR_fast_gettimeofday 0 +#define __NR_fast_clock_gettime 1 +#define __NR_fast_getcpu 2 +#define __NR_fast_siggetmask 3 +#define __NR_fast_getcontext 4 +#define __NR_fast_set_return 5 + +#define goto_ttable_entry1_args3(sys_num, arg1, arg2, ret) \ + E2K_SCALL_ARG7(1, ret, sys_num, arg1, arg2, 0, 0, 0, 0) +#define goto_ttable_entry1_args4(sys_num, arg1, arg2, arg3, ret) \ + E2K_SCALL_ARG7(1, ret, sys_num, arg1, arg2, arg3, 0, 0, 0) + +#define goto_ttable_entry3_args3(sys_num, arg1, arg2, ret) \ + E2K_SCALL_ARG7(3, ret, sys_num, arg1, arg2, 0, 0, 0, 0) +#define goto_ttable_entry3_args4(sys_num, arg1, arg2, arg3, ret) \ + E2K_SCALL_ARG7(3, ret, sys_num, arg1, arg2, arg3, 0, 0, 0) + /* it is native guest kernel (not paravirtualized based on pv_ops) */ static inline int do_fast_clock_gettime(const clockid_t which_clock, struct timespec *tp) { return kvm_do_fast_clock_gettime(which_clock, tp); } - -static inline int -fast_sys_clock_gettime(const clockid_t which_clock, struct timespec __user *tp) -{ - return kvm_fast_sys_clock_gettime(which_clock, tp); -} - static inline int do_fast_gettimeofday(struct timeval *tv) { return kvm_do_fast_gettimeofday(tv); } static inline int -fast_sys_siggetmask(u64 __user *oset, size_t sigsetsize) +do_fast_sys_set_return(u64 ip, int flags) { - return kvm_fast_sys_siggetmask(oset, sigsetsize); + return kvm_do_fast_sys_set_return(ip, flags); } #endif /* ! CONFIG_KVM_GUEST_KERNEL */ #endif /* _ASM_E2K_KVM_GUEST_FAST_SYSCALLS_H */ - diff --git a/arch/e2k/include/asm/kvm/guest/mm_hooks.h b/arch/e2k/include/asm/kvm/guest/mm_hooks.h index c3b05c8..b46e1f3 100644 --- a/arch/e2k/include/asm/kvm/guest/mm_hooks.h +++ b/arch/e2k/include/asm/kvm/guest/mm_hooks.h @@ -3,15 +3,15 @@ #ifdef __KERNEL__ -extern void kvm_get_mm_notifier_locked(struct mm_struct *mm); +extern int kvm_get_mm_notifier_locked(struct mm_struct *mm); #ifdef CONFIG_KVM_GUEST_KERNEL /* it is pure guest kernel (not paravirtualized based on pv_ops) */ -static inline void +static inline int get_mm_notifier_locked(struct mm_struct *mm) { /* create mm notifier to trace some events over mm */ - kvm_get_mm_notifier_locked(mm); + return kvm_get_mm_notifier_locked(mm); } #endif /* CONFIG_KVM_GUEST_KERNEL */ diff --git a/arch/e2k/include/asm/kvm/guest/mmu_context.h b/arch/e2k/include/asm/kvm/guest/mmu_context.h index cef5f42..b2fabbf 100644 --- a/arch/e2k/include/asm/kvm/guest/mmu_context.h +++ b/arch/e2k/include/asm/kvm/guest/mmu_context.h @@ -7,7 +7,8 @@ extern void kvm_activate_mm(struct mm_struct *active_mm, struct mm_struct *mm); -extern void kvm_get_mm_notifier_locked(struct mm_struct *mm); +extern int kvm_get_mm_notifier(struct mm_struct *mm); +extern int kvm_get_mm_notifier_locked(struct mm_struct *mm); #ifdef CONFIG_KVM_GUEST_KERNEL /* it is pure guest kernel (not paravirtualized based on pv_ops) */ diff --git a/arch/e2k/include/asm/kvm/guest/process.h b/arch/e2k/include/asm/kvm/guest/process.h index e669bea..ef4ca2d 100644 --- a/arch/e2k/include/asm/kvm/guest/process.h +++ b/arch/e2k/include/asm/kvm/guest/process.h @@ -113,19 +113,18 @@ kvm_preserve_user_hw_stacks_to_copy(e2k_stacks_t *u_stacks, static __always_inline void kvm_jump_to_ttable_entry(struct pt_regs *regs, enum restore_caller from) { - if (from & FROM_SYSCALL_N_PROT) { + if (from & (FROM_SYSCALL_N_PROT | FROM_SIGRETURN | FROM_RET_FROM_FORK)) { switch (regs->kernel_entry) { case 1: case 3: case 4: KVM_WRITE_UPSR_REG(E2K_KERNEL_UPSR_ENABLED); - regs->stack_regs_saved = true; - __E2K_JUMP_WITH_ARGUMENTS_8(handle_sys_call, - regs->sys_func, - regs->args[1], regs->args[2], - regs->args[3], regs->args[4], - regs->args[5], regs->args[6], - regs); + /* + * Unconditional return to host with guest's return value, + * because of only host can recover initial state of stacks + * and some other registers state to restart system call + */ + E2K_SYSCALL_RETURN(regs->sys_rval); default: BUG(); } diff --git a/arch/e2k/include/asm/kvm/guest/switch.h b/arch/e2k/include/asm/kvm/guest/switch.h index 852c3ca..6f6d29e 100644 --- a/arch/e2k/include/asm/kvm/guest/switch.h +++ b/arch/e2k/include/asm/kvm/guest/switch.h @@ -81,6 +81,11 @@ static inline bool kvm_guest_syscall_enter(struct pt_regs *regs) return false; /* it is not nested guest system call */ } +static inline void kvm_pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs) +{ + /* Do nothing in guest mode */ +} + #ifdef CONFIG_KVM_GUEST_KERNEL /* it is pure guest kernel (not paravrtualized) */ @@ -148,6 +153,11 @@ static inline bool guest_syscall_enter(struct pt_regs *regs, return kvm_guest_syscall_enter(regs); } +static inline void pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs) +{ + kvm_pv_vcpu_syscall_intc(ti, regs); +} + static inline void guest_exit_intc(struct pt_regs *regs, bool intc_emul_flag) { } static inline void guest_syscall_exit_trap(struct pt_regs *regs, diff --git a/arch/e2k/include/asm/kvm/guest/tlbflush.h b/arch/e2k/include/asm/kvm/guest/tlbflush.h index 29ebc44..b8bb453 100644 --- a/arch/e2k/include/asm/kvm/guest/tlbflush.h +++ b/arch/e2k/include/asm/kvm/guest/tlbflush.h @@ -17,145 +17,85 @@ extern void kvm_pv_flush_tlb_all(void); extern void kvm_pv_flush_tlb_mm(struct mm_struct *mm); extern void kvm_pv_flush_tlb_page(struct mm_struct *mm, e2k_addr_t addr); -extern void kvm_pv_flush_tlb_range(struct mm_struct *mm, e2k_addr_t start, - e2k_addr_t end); extern void kvm_pv_flush_tlb_kernel_range(e2k_addr_t start, e2k_addr_t end); extern void kvm_pv_flush_pmd_tlb_range(struct mm_struct *mm, e2k_addr_t start, e2k_addr_t end); extern void kvm_pv_flush_tlb_range_and_pgtables(struct mm_struct *mm, - e2k_addr_t start, - e2k_addr_t end); -#ifndef CONFIG_SMP -static inline void -kvm_flush_tlb_all(void) + e2k_addr_t start, e2k_addr_t end); + +static inline void kvm_flush_tlb_all(void) { if (IS_HV_GM()) - __flush_tlb_all(); + native_flush_tlb_all(); else kvm_pv_flush_tlb_all(); } -static inline void -kvm_flush_tlb_mm(struct mm_struct *mm) + +static inline void kvm_flush_tlb_mm(struct mm_struct *mm) { if (IS_HV_GM()) - __flush_tlb_mm(mm); + native_flush_tlb_mm(mm); else kvm_pv_flush_tlb_mm(mm); } -static inline void -kvm_flush_tlb_page(struct vm_area_struct *vma, e2k_addr_t addr) + +static inline void kvm_flush_tlb_page(struct mm_struct *mm, e2k_addr_t addr) { if (IS_HV_GM()) - __flush_tlb_page(vma->vm_mm, addr); + native_flush_tlb_page(mm, addr); else - kvm_pv_flush_tlb_page(vma->vm_mm, addr); + kvm_pv_flush_tlb_page(mm, addr); } -static inline void -kvm_flush_tlb_range(struct mm_struct *mm, e2k_addr_t start, e2k_addr_t end) + +static inline void kvm_flush_tlb_range(struct mm_struct *mm, + e2k_addr_t start, e2k_addr_t end) { if (IS_HV_GM()) - __flush_tlb_range(mm, start, end); - else - kvm_pv_flush_tlb_range(mm, start, end); -} -static inline void -kvm_flush_tlb_kernel_range(e2k_addr_t start, e2k_addr_t end) -{ - if (IS_HV_GM()) - __flush_tlb_all(); - else - kvm_pv_flush_tlb_kernel_range(start, end); -} -static inline void -kvm_flush_pmd_tlb_range(struct mm_struct *mm, e2k_addr_t start, - e2k_addr_t end) -{ - if (IS_HV_GM()) - __flush_pmd_tlb_range(mm, start, end); - else - kvm_pv_flush_pmd_tlb_range(mm, start, end); -} -static inline void -kvm_flush_tlb_range_and_pgtables(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end) -{ - if (IS_HV_GM()) - __flush_tlb_range_and_pgtables(mm, start, end); + native_flush_tlb_range(mm, start, end); else kvm_pv_flush_tlb_range_and_pgtables(mm, start, end); } -#else /* CONFIG_SMP */ -extern void kvm_pv_smp_flush_tlb_mm(struct mm_struct *const mm); -extern void kvm_pv_smp_flush_tlb_all(void); -extern void kvm_pv_smp_flush_tlb_page(struct vm_area_struct *const vma, - const e2k_addr_t addr); -extern void kvm_pv_smp_flush_tlb_range(struct mm_struct *const mm, - const e2k_addr_t start, const e2k_addr_t end); -extern void kvm_pv_smp_flush_pmd_tlb_range(struct mm_struct *const mm, - const e2k_addr_t start, const e2k_addr_t end); -extern void kvm_pv_smp_flush_tlb_range_and_pgtables(struct mm_struct *const mm, - const e2k_addr_t start, const e2k_addr_t end); -extern void kvm_pv_smp_flush_tlb_kernel_range(e2k_addr_t start, e2k_addr_t end); -static inline void -kvm_flush_tlb_all(void) +static inline void kvm_flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long stride, u32 levels_mask) { if (IS_HV_GM()) - native_smp_flush_tlb_all(); + native_flush_tlb_mm_range(mm, start, end, stride, levels_mask); else - kvm_pv_smp_flush_tlb_all(); + kvm_pv_flush_tlb_range_and_pgtables(mm, start, end); } -static inline void -kvm_flush_tlb_mm(struct mm_struct *mm) + +static inline void kvm_flush_tlb_kernel_range(e2k_addr_t start, e2k_addr_t end) { if (IS_HV_GM()) - native_smp_flush_tlb_mm(mm); + native_flush_tlb_kernel_range(start, end); else - kvm_pv_smp_flush_tlb_mm(mm); + kvm_pv_flush_tlb_kernel_range(start, end); } -static inline void -kvm_flush_tlb_page(struct vm_area_struct *vma, e2k_addr_t addr) + +static inline void kvm_flush_pmd_tlb_range(struct mm_struct *mm, + e2k_addr_t start, e2k_addr_t end) { if (IS_HV_GM()) - native_smp_flush_tlb_page(vma, addr); + native_flush_pmd_tlb_range(mm, start, end); else - kvm_pv_smp_flush_tlb_page(vma, addr); + kvm_pv_flush_pmd_tlb_range(mm, start, end); } -static inline void -kvm_flush_tlb_range(struct mm_struct *mm, e2k_addr_t start, e2k_addr_t end) -{ - if (IS_HV_GM()) - native_smp_flush_tlb_range(mm, start, end); - else - kvm_pv_smp_flush_tlb_range(mm, start, end); -} -static inline void -kvm_flush_tlb_kernel_range(e2k_addr_t start, e2k_addr_t end) -{ - if (IS_HV_GM()) - native_smp_flush_tlb_all(); - else - kvm_pv_smp_flush_tlb_kernel_range(start, end); -} -static inline void -kvm_flush_pmd_tlb_range(struct mm_struct *mm, e2k_addr_t start, - e2k_addr_t end) -{ - if (IS_HV_GM()) - native_smp_flush_pmd_tlb_range(mm, start, end); - else - kvm_pv_smp_flush_pmd_tlb_range(mm, start, end); -} -static inline void -kvm_flush_tlb_range_and_pgtables(struct mm_struct *mm, + +static inline void kvm_flush_tlb_range_and_pgtables(struct mm_struct *mm, e2k_addr_t start, e2k_addr_t end) { if (IS_HV_GM()) - native_smp_flush_tlb_range_and_pgtables(mm, start, end); + native_flush_tlb_range_and_pgtables(mm, start, end); else - kvm_pv_smp_flush_tlb_range_and_pgtables(mm, start, end); + kvm_pv_flush_tlb_range_and_pgtables(mm, start, end); +} + +static inline void kvm_flush_tlb_page_and_pgtables(struct mm_struct *mm, + unsigned long uaddr) +{ + kvm_flush_tlb_range_and_pgtables(mm, uaddr, uaddr + 1); } -#endif /* CONFIG_SMP */ /* it is native KVM guest kernel (not paravirtualized) */ /* guest kernel does not support other virtual machines and guests */ diff --git a/arch/e2k/include/asm/kvm/guest/trap_table.h b/arch/e2k/include/asm/kvm/guest/trap_table.h index bc13495..2fa61dc 100644 --- a/arch/e2k/include/asm/kvm/guest/trap_table.h +++ b/arch/e2k/include/asm/kvm/guest/trap_table.h @@ -164,10 +164,19 @@ kvm_do_aau_page_fault(struct pt_regs *const regs, e2k_addr_t address, ttable_entry; \ }) -#define FILL_HARDWARE_STACKS() \ +#define FILL_HARDWARE_STACKS__HW() \ do { \ if (IS_HV_GM()) { \ - NATIVE_FILL_HARDWARE_STACKS(); \ + NATIVE_FILL_HARDWARE_STACKS__HW(); \ + } else { \ + KVM_FILL_HARDWARE_STACKS(); \ + } \ +} while (false) + +#define FILL_HARDWARE_STACKS__SW() \ +do { \ + if (IS_HV_GM()) { \ + NATIVE_FILL_HARDWARE_STACKS__SW(); \ } else { \ KVM_FILL_HARDWARE_STACKS(); \ } \ diff --git a/arch/e2k/include/asm/kvm/guest/traps.h b/arch/e2k/include/asm/kvm/guest/traps.h index 403a147..160671d 100644 --- a/arch/e2k/include/asm/kvm/guest/traps.h +++ b/arch/e2k/include/asm/kvm/guest/traps.h @@ -40,6 +40,8 @@ extern int kvm_host_apply_psp_delta_to_signal_stack(unsigned long base, extern int kvm_host_apply_pcsp_delta_to_signal_stack(unsigned long base, unsigned long size, unsigned long start, unsigned long end, unsigned long delta); +extern int kvm_host_apply_usd_delta_to_signal_stack(unsigned long top, + unsigned long delta, bool incr); static inline unsigned long kvm_mmio_page_fault(struct pt_regs *regs, trap_cellar_t *tcellar) @@ -108,6 +110,16 @@ static inline int host_apply_pcsp_delta_to_signal_stack(unsigned long base, start, end, delta); } +static inline int host_apply_usd_delta_to_signal_stack(unsigned long top, + unsigned long delta, bool incr) +{ + if (IS_HV_GM()) { + return native_host_apply_usd_delta_to_signal_stack(top, delta, + incr); + } + return kvm_host_apply_usd_delta_to_signal_stack(top, delta, incr); +} + static inline void handle_interrupt(struct pt_regs *regs) { diff --git a/arch/e2k/include/asm/kvm/gva_cache.h b/arch/e2k/include/asm/kvm/gva_cache.h new file mode 100644 index 0000000..dbd9123 --- /dev/null +++ b/arch/e2k/include/asm/kvm/gva_cache.h @@ -0,0 +1,180 @@ +#ifndef GVA_CACHE_E2K_H +#define GVA_CACHE_E2K_H + + +#include + +#include +#include + +/* Format of address record in gva cache */ +typedef union { + struct { + u64 addr : 64 - PAGE_SHIFT; + u64 flags : PAGE_SHIFT; + } fields; + u64 word; +} cache_addr_t; + +#define ADDR_VALID_MASK (1 << 0) + +#define GVA_ADDR gva.fields.addr +#define GVA_FLAGS gva.fields.flags +#define GVA_WHOLE gva.word + +/* Cache "cell" with gva -> gpa,hva translation */ +typedef struct gva_cache_cell { + cache_addr_t gva; + gfn_t gfn; + u32 pte_access; + u32 level; + u64 replace_data; +} gva_cache_cell_t; + +/* gva -> gpa cache size */ +#define KVM_GVA_CACHE_SZ PAGE_SIZE +/* 2 ^ KVM_GVA_CACHE_BUCKET_BITS buckets in cache */ +#define KVM_GVA_CACHE_BUCKET_BITS 5 +#define KVM_GVA_CACHE_BUCKETS (1 << KVM_GVA_CACHE_BUCKET_BITS) +#define KVM_GVA_CACHE_BUCKET_SZ \ + (KVM_GVA_CACHE_SZ / KVM_GVA_CACHE_BUCKETS) +#define KVM_GVA_CACHE_BUCKET_LEN \ + (KVM_GVA_CACHE_BUCKET_SZ / sizeof(gva_cache_cell_t)) +#define KVM_GVA_CACHE_LEN \ + (KVM_GVA_CACHE_SZ / sizeof(gva_cache_cell_t)) + +typedef enum REPLACE_POLICY { + LRU = 0, + RAND = 1 +} replace_policy_t; + +/* + * gva cache stores translations from gva to gpa and hva to avoid + * guest page table and kvm memory slots lookup. + */ +typedef struct gva_cache { + spinlock_t bucket_locks[KVM_GVA_CACHE_BUCKETS]; + gva_cache_cell_t *data; + replace_policy_t replace_policy; +} gva_cache_t; + +typedef struct gva_translation { + gva_t gva; + gpa_t gpa; + u32 pte_access; + u32 level; +} gva_translation_t; + +typedef struct gva_cache_query { + gva_t gva; + u32 access; +} gva_cache_query_t; + + +typedef gpa_t (*gva_tranlslator_t)(struct kvm_vcpu *, gva_t, + u32, struct kvm_arch_exception*); + +gpa_t gva_cache_translate(gva_cache_t *cache, gva_t gva, u32 access, + struct kvm_vcpu *vcpu, kvm_arch_exception_t *exc, + gva_tranlslator_t gva_translate); +void gva_cache_fetch_addr(gva_cache_t *cache, gva_t gva, gpa_t gpa, + u32 access); +void gva_cache_flush_addr(gva_cache_t *cache, gva_t gva); +gva_cache_t *gva_cache_init(void); +void gva_cache_erase(gva_cache_t *cache); + + +#ifdef CONFIG_KVM_GVA_CACHE_STAT + +int gva_cache_stat_dev_init(void); + +/* Statistics of access to gva->gpa cache */ +typedef struct gva_caches_stat { + u64 accesses; + u64 hits; + u64 misses; + + u64 sum_hit_time; + u64 sum_miss_pen; + + u64 conflict_misses; + u64 cold_misses; + + u64 flushes; + u64 fetches; +} gva_caches_stat_t; + +extern gva_caches_stat_t caches_stat; + +#define gva_cache_stat_lookup_start(start) \ +({ \ + caches_stat.accesses++; \ + start = ktime_get_ns(); \ +}) + +#define gva_cache_stat_lookup_hit_end(start, stop) \ +({ \ + stop = ktime_get_ns(); \ + caches_stat.hits++; \ + caches_stat.sum_hit_time += (stop - start); \ +}) + +#define gva_cache_stat_lookup_miss_start(start) \ +({ \ + caches_stat.misses++; \ + start = ktime_get_ns(); \ +}) + +#define gva_cache_stat_lookup_miss_stop(start, stop) \ +({ \ + stop = ktime_get_ns(); \ + caches_stat.sum_miss_pen += (stop - start); \ +}) + +#define gva_cache_stat_lookup_miss_stop(start, stop) \ +({ \ + stop = ktime_get_ns(); \ + caches_stat.sum_miss_pen += (stop - start); \ +}) + +#define gva_cache_stat_lookup_miss_conflict(is_conflict) \ +({ \ + if (is_conflict) \ + caches_stat.conflict_misses++; \ + else \ + caches_stat.cold_misses++; \ +}) + +#define gva_cache_stat_replace_conflict(is_conflict, conflict) \ +({ \ + if (is_conflict) \ + *is_conflict = conflict; \ +}) + +#define gva_cache_stat_fetch() \ +({ \ + caches_stat.accesses++; \ + caches_stat.fetches++; \ +}) + +#define gva_cache_stat_flush() \ +({ \ + caches_stat.accesses++; \ + caches_stat.flushes++; \ +}) + +#else /* CONFIG_KVM_GVA_CACHE_STAT */ + +#define gva_cache_stat_lookup_start(start) +#define gva_cache_stat_lookup_hit_end(start, stop) +#define gva_cache_stat_lookup_miss_start(start) +#define gva_cache_stat_lookup_miss_stop(start, stop) +#define gva_cache_stat_lookup_miss_stop(start, stop) +#define gva_cache_stat_lookup_miss_conflict(is_conflict) +#define gva_cache_stat_replace_conflict(is_conflict, conflict) +#define gva_cache_stat_fetch() +#define gva_cache_stat_flush() + +#endif /* CONFIG_KVM_GVA_CACHE_STAT */ + +#endif /* GVA_CACHE_H */ diff --git a/arch/e2k/include/asm/kvm/hypercall.h b/arch/e2k/include/asm/kvm/hypercall.h index 5475f86..3ca7c02 100644 --- a/arch/e2k/include/asm/kvm/hypercall.h +++ b/arch/e2k/include/asm/kvm/hypercall.h @@ -246,6 +246,10 @@ static inline unsigned long generic_hypercall6(unsigned long nr, #define KVM_HCALL_SWITCH_TO_EXPANDED_PROC_STACK 31 /* notify host kernel aboout switch to updated procedure chain stack on guest */ #define KVM_HCALL_SWITCH_TO_EXPANDED_CHAIN_STACK 32 +/* return back to guest user from fast syscall handler */ +#define KVM_HCALL_RETURN_FROM_FAST_SYSCALL 33 +/* change return ip in user stack */ +#define KVM_HCALL_SET_RETURN_USER_IP 34 typedef struct kvm_hw_stacks_flush { unsigned long psp_lo; @@ -472,6 +476,19 @@ HYPERVISOR_switch_to_expanded_guest_chain_stack(long delta_size, delta_size, delta_offset, (unsigned long)decr_gk_pcs); } +static inline unsigned long +HYPERVISOR_return_from_fast_syscall(long ret_val) +{ + return light_hypercall1(KVM_HCALL_RETURN_FROM_FAST_SYSCALL, ret_val); +} + +static inline unsigned long +HYPERVISOR_set_return_user_ip(u64 gti, u64 ip, int flags) +{ + return light_hypercall3(KVM_HCALL_SET_RETURN_USER_IP, gti, + ip, flags); +} + /* * KVM hypervisor (host) <-> guest generic hypercalls list */ @@ -487,6 +504,9 @@ HYPERVISOR_switch_to_expanded_guest_chain_stack(long delta_size, #define KVM_HCALL_COMPLETE_LONG_JUMP 12 /* long jump completion */ #define KVM_HCALL_LAUNCH_SIG_HANDLER 14 /* launch guest user signal */ /* handler */ +#define KVM_HCALL_APPLY_USD_BOUNDS 15 /* update user data */ + /* stack pointers after stack */ + /* bounds handling */ #define KVM_HCALL_SWITCH_TO_VIRT_MODE 16 /* switch from physical to */ /* virtual addresses mode */ /* (enable paging, TLB, TLU) */ @@ -895,6 +915,14 @@ HYPERVISOR_apply_pcsp_bounds(unsigned long base, unsigned long size, return generic_hypercall5(KVM_HCALL_APPLY_PCSP_BOUNDS, base, size, start, end, delta); } + +static inline unsigned long +HYPERVISOR_apply_usd_bounds(unsigned long top, unsigned long delta, bool incr) +{ + return generic_hypercall3(KVM_HCALL_APPLY_USD_BOUNDS, + top, delta, incr); +} + static inline unsigned long HYPERVISOR_correct_trap_return_ip(unsigned long return_ip) { diff --git a/arch/e2k/include/asm/kvm/mm.h b/arch/e2k/include/asm/kvm/mm.h index 29a004d..5d4eb24 100644 --- a/arch/e2k/include/asm/kvm/mm.h +++ b/arch/e2k/include/asm/kvm/mm.h @@ -7,6 +7,7 @@ #include #include +#include #define GMMID_MAX_LIMIT (GPID_MAX_LIMIT) #define RESERVED_GMMIDS 1 /* 0 is reserved for init_mm */ @@ -52,6 +53,7 @@ typedef struct gmm_struct { /* the guest mm */ cpumask_t cpu_vm_mask; /* mask of CPUs where the mm is */ /* in use or was some early */ + gva_cache_t *gva_cache; /* gva -> gpa,hva cache */ } gmm_struct_t; /* same as accessor for struct mm_struct's cpu_vm_mask but for guest mm */ diff --git a/arch/e2k/include/asm/kvm/mm_hooks.h b/arch/e2k/include/asm/kvm/mm_hooks.h index a834039..1cdb9cc 100644 --- a/arch/e2k/include/asm/kvm/mm_hooks.h +++ b/arch/e2k/include/asm/kvm/mm_hooks.h @@ -15,10 +15,11 @@ #if !defined(CONFIG_PARAVIRT_GUEST) && !defined(CONFIG_KVM_GUEST_KERNEL) /* it is native kernel without any virtualization */ /* it is native host kernel with virtualization support */ -static inline void +static inline int get_mm_notifier_locked(struct mm_struct *mm) { /* Do not need mmu notifier in native mode */ + return 0; } #elif defined(CONFIG_PARAVIRT_GUEST) /* it is paravirtualized host and guest kernel */ diff --git a/arch/e2k/include/asm/kvm/mmu_exc.h b/arch/e2k/include/asm/kvm/mmu_exc.h new file mode 100644 index 0000000..8f9380d --- /dev/null +++ b/arch/e2k/include/asm/kvm/mmu_exc.h @@ -0,0 +1,20 @@ +#ifndef MMU_GVA_TRANSLATION_H +#define MMU_GVA_TRANSLATION_H + +#include + +#undef E2K_INVALID_PAGE +#define E2K_INVALID_PAGE (~(hpa_t)0) + +#define UNMAPPED_GVA (~(gpa_t)0) +#define arch_is_error_gpa(gpa) ((gpa_t)(gpa) == UNMAPPED_GVA) + + +typedef struct kvm_arch_exception { + bool error_code_valid; /* PFERR_* flags is valid */ + u32 error_code; /* PFERR_* flags */ + u64 address; /* page fault gpa */ + u64 ip; /* IP to inject trap */ +} kvm_arch_exception_t; + +#endif /* MMU_GVA_TRANSLATION_H */ diff --git a/arch/e2k/include/asm/kvm/mmu_pte.h b/arch/e2k/include/asm/kvm/mmu_pte.h new file mode 100644 index 0000000..90dbfe7 --- /dev/null +++ b/arch/e2k/include/asm/kvm/mmu_pte.h @@ -0,0 +1,58 @@ +#ifndef MMU_PTE_H +#define MMU_PTE_H + +/* uwx (u - user mode, w - writable, x executable) */ +#define ACC_EXEC_MASK 0x1 +#define ACC_WRITE_MASK 0x2 +#define ACC_USER_MASK 0x4 +#define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK) +/* page tables directories always privileged & not executable */ +#define ACC_PT_DIR (ACC_WRITE_MASK) + +#define PFERR_PRESENT_BIT 0 +#define PFERR_WRITE_BIT 1 +#define PFERR_USER_BIT 2 +#define PFERR_RSVD_BIT 3 +#define PFERR_FETCH_BIT 4 +#define PFERR_NOT_PRESENT_BIT 5 +#define PFERR_PT_FAULT_BIT 6 +#define PFERR_INSTR_FAULT_BIT 7 +#define PFERR_INSTR_PROT_BIT 8 +#define PFERR_FORCED_BIT 9 +#define PFERR_WAIT_LOCK_BIT 10 +#define PFERR_GPTE_CHANGED_BIT 11 +#define PFERR_MMIO_BIT 12 +#define PFERR_ONLY_VALID_BIT 13 +#define PFERR_READ_PROT_BIT 14 +#define PFERR_IS_UNMAPPED_BIT 15 +#define PFERR_FAPB_BIT 16 + +#define PFERR_ACCESS_SIZE_BIT 24 + +#define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT) +#define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT) +#define PFERR_USER_MASK (1U << PFERR_USER_BIT) +#define PFERR_RSVD_MASK (1U << PFERR_RSVD_BIT) +#define PFERR_FETCH_MASK (1U << PFERR_FETCH_BIT) +#define PFERR_NOT_PRESENT_MASK (1U << PFERR_NOT_PRESENT_BIT) +#define PFERR_PT_FAULT_MASK (1U << PFERR_PT_FAULT_BIT) +#define PFERR_INSTR_FAULT_MASK (1U << PFERR_INSTR_FAULT_BIT) +#define PFERR_INSTR_PROT_MASK (1U << PFERR_INSTR_PROT_BIT) +#define PFERR_FORCED_MASK (1U << PFERR_FORCED_BIT) +#define PFERR_WAIT_LOCK_MASK (1U << PFERR_WAIT_LOCK_BIT) +#define PFERR_GPTE_CHANGED_MASK (1U << PFERR_GPTE_CHANGED_BIT) +#define PFERR_MMIO_MASK (1U << PFERR_MMIO_BIT) +#define PFERR_ONLY_VALID_MASK (1U << PFERR_ONLY_VALID_BIT) +#define PFERR_READ_PROT_MASK (1U << PFERR_READ_PROT_BIT) +#define PFERR_IS_UNMAPPED_MASK (1U << PFERR_IS_UNMAPPED_BIT) +#define PFERR_FAPB_MASK (1U << PFERR_FAPB_BIT) + +#define PFERR_ACCESS_SIZE_MASK (~0U << PFERR_ACCESS_SIZE_BIT) + +#define PFRES_GET_ACCESS_SIZE(pfres) \ + (((pfres) & PFERR_ACCESS_SIZE_MASK) >> PFERR_ACCESS_SIZE_BIT) +#define PFRES_SET_ACCESS_SIZE(pfres, size) \ + (((pfres) & ~PFERR_ACCESS_SIZE_MASK) | \ + ((size) << PFERR_ACCESS_SIZE_BIT)) + +#endif /* MMU_PTE_H */ diff --git a/arch/e2k/include/asm/kvm/mmu_regs_access.h b/arch/e2k/include/asm/kvm/mmu_regs_access.h index f4f5678..a302727 100644 --- a/arch/e2k/include/asm/kvm/mmu_regs_access.h +++ b/arch/e2k/include/asm/kvm/mmu_regs_access.h @@ -177,7 +177,7 @@ static inline void BOOT_KVM_WRITE_MMU_PID_REG(mmu_reg_t reg_val) /* all hardware MMU registers, but it is not so now, */ /* for example PT roots and context registers are controled */ /* by hypervisor as for paravirtualized kernels */ - NATIVE_FLUSH_TLB_ALL(_flush_op_tlb_all); + NATIVE_FLUSH_TLB_ALL(flush_op_tlb_all); } } static inline unsigned long BOOT_KVM_READ_MMU_PID_REG(void) @@ -246,11 +246,11 @@ static inline void KVM_FLUSH_TLB_ENTRY(flush_op_t flush_op, flush_addr_t flush_addr) { if (unlikely(flush_addr_get_pid(flush_addr) == E2K_KERNEL_CONTEXT)) { - pr_warn("%s(): CPU #%d try to flush %s addr 0x%lx pid 0x%03lx\n", + pr_warn("%s(): CPU #%d try to flush %s addr 0x%llx pid 0x%03llx\n", __func__, smp_processor_id(), - (flush_op_get_type(flush_op) == flush_op_tlb_page_sys) ? + (flush_op_get_type(flush_op) == FLUSH_TLB_PAGE_OP) ? "TLB page" : "???", - flush_addr_get_va(flush_addr), + FLUSH_VADDR_TO_VA(flush_addr), flush_addr_get_pid(flush_addr)); } } diff --git a/arch/e2k/include/asm/kvm/pv-emul.h b/arch/e2k/include/asm/kvm/pv-emul.h index 81479d0..c1d1f73 100644 --- a/arch/e2k/include/asm/kvm/pv-emul.h +++ b/arch/e2k/include/asm/kvm/pv-emul.h @@ -127,7 +127,6 @@ extern void insert_pv_vcpu_sigreturn(struct kvm_vcpu *vcpu, extern void kvm_emulate_pv_vcpu_intc(struct thread_info *ti, pt_regs_t *regs, trap_pt_regs_t *trap); extern void return_from_pv_vcpu_intc(struct thread_info *ti, pt_regs_t *regs); -extern bool pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs); static inline bool kvm_vcpu_in_hypercall(struct kvm_vcpu *vcpu) { diff --git a/arch/e2k/include/asm/kvm/switch.h b/arch/e2k/include/asm/kvm/switch.h index b416e9f..ce2e495 100644 --- a/arch/e2k/include/asm/kvm/switch.h +++ b/arch/e2k/include/asm/kvm/switch.h @@ -99,6 +99,12 @@ native_guest_syscall_enter(struct pt_regs *regs) return false; /* it is not guest system call */ } +static inline void +native_pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs) +{ + /* Nothing to do in native mode */ +} + #ifdef CONFIG_VIRTUALIZATION /* @@ -278,106 +284,6 @@ static inline void kvm_switch_to_host_mmu_pid(struct kvm_vcpu *vcpu, raw_all_irq_restore(flags); } -static inline void kvm_switch_debug_regs(struct kvm_sw_cpu_context *sw_ctxt, - int is_active) -{ - u64 b_dimar0, b_dimar1, b_ddmar0, b_ddmar1, b_dibar0, b_dibar1, - b_dibar2, b_dibar3, b_ddbar0, b_ddbar1, b_ddbar2, b_ddbar3, - a_dimar0, a_dimar1, a_ddmar0, a_ddmar1, a_dibar0, a_dibar1, - a_dibar2, a_dibar3, a_ddbar0, a_ddbar1, a_ddbar2, a_ddbar3; - e2k_dimcr_t b_dimcr, a_dimcr; - e2k_ddmcr_t b_ddmcr, a_ddmcr; - e2k_dibcr_t b_dibcr, a_dibcr; - e2k_dibsr_t b_dibsr, a_dibsr; - e2k_ddbcr_t b_ddbcr, a_ddbcr; - e2k_ddbsr_t b_ddbsr, a_ddbsr; - - b_dibcr = sw_ctxt->dibcr; - b_ddbcr = sw_ctxt->ddbcr; - b_dibsr = sw_ctxt->dibsr; - b_ddbsr = sw_ctxt->ddbsr; - b_dimcr = sw_ctxt->dimcr; - b_ddmcr = sw_ctxt->ddmcr; - b_dibar0 = sw_ctxt->dibar0; - b_dibar1 = sw_ctxt->dibar1; - b_dibar2 = sw_ctxt->dibar2; - b_dibar3 = sw_ctxt->dibar3; - b_ddbar0 = sw_ctxt->ddbar0; - b_ddbar1 = sw_ctxt->ddbar1; - b_ddbar2 = sw_ctxt->ddbar2; - b_ddbar3 = sw_ctxt->ddbar3; - b_dimar0 = sw_ctxt->dimar0; - b_dimar1 = sw_ctxt->dimar1; - b_ddmar0 = sw_ctxt->ddmar0; - b_ddmar1 = sw_ctxt->ddmar1; - - a_dibcr = NATIVE_READ_DIBCR_REG(); - a_ddbcr = NATIVE_READ_DDBCR_REG(); - a_dibsr = NATIVE_READ_DIBSR_REG(); - a_ddbsr = NATIVE_READ_DDBSR_REG(); - a_dimcr = NATIVE_READ_DIMCR_REG(); - a_ddmcr = NATIVE_READ_DDMCR_REG(); - a_dibar0 = NATIVE_READ_DIBAR0_REG_VALUE(); - a_dibar1 = NATIVE_READ_DIBAR1_REG_VALUE(); - a_dibar2 = NATIVE_READ_DIBAR2_REG_VALUE(); - a_dibar3 = NATIVE_READ_DIBAR3_REG_VALUE(); - a_ddbar0 = NATIVE_READ_DDBAR0_REG_VALUE(); - a_ddbar1 = NATIVE_READ_DDBAR1_REG_VALUE(); - a_ddbar2 = NATIVE_READ_DDBAR2_REG_VALUE(); - a_ddbar3 = NATIVE_READ_DDBAR3_REG_VALUE(); - a_ddmar0 = NATIVE_READ_DDMAR0_REG_VALUE(); - a_ddmar1 = NATIVE_READ_DDMAR1_REG_VALUE(); - a_dimar0 = NATIVE_READ_DIMAR0_REG_VALUE(); - a_dimar1 = NATIVE_READ_DIMAR1_REG_VALUE(); - - if (is_active) { - /* These two must be written first to disable monitoring */ - NATIVE_WRITE_DIBCR_REG(b_dibcr); - NATIVE_WRITE_DDBCR_REG(b_ddbcr); - } - NATIVE_WRITE_DIBAR0_REG_VALUE(b_dibar0); - NATIVE_WRITE_DIBAR1_REG_VALUE(b_dibar1); - NATIVE_WRITE_DIBAR2_REG_VALUE(b_dibar2); - NATIVE_WRITE_DIBAR3_REG_VALUE(b_dibar3); - NATIVE_WRITE_DDBAR0_REG_VALUE(b_ddbar0); - NATIVE_WRITE_DDBAR1_REG_VALUE(b_ddbar1); - NATIVE_WRITE_DDBAR2_REG_VALUE(b_ddbar2); - NATIVE_WRITE_DDBAR3_REG_VALUE(b_ddbar3); - NATIVE_WRITE_DDMAR0_REG_VALUE(b_ddmar0); - NATIVE_WRITE_DDMAR1_REG_VALUE(b_ddmar1); - NATIVE_WRITE_DIMAR0_REG_VALUE(b_dimar0); - NATIVE_WRITE_DIMAR1_REG_VALUE(b_dimar1); - NATIVE_WRITE_DIBSR_REG(b_dibsr); - NATIVE_WRITE_DDBSR_REG(b_ddbsr); - NATIVE_WRITE_DIMCR_REG(b_dimcr); - NATIVE_WRITE_DDMCR_REG(b_ddmcr); - if (!is_active) { - /* These two must be written last to enable monitoring */ - NATIVE_WRITE_DIBCR_REG(b_dibcr); - NATIVE_WRITE_DDBCR_REG(b_ddbcr); - } - - sw_ctxt->dibcr = a_dibcr; - sw_ctxt->ddbcr = a_ddbcr; - sw_ctxt->dibsr = a_dibsr; - sw_ctxt->ddbsr = a_ddbsr; - sw_ctxt->dimcr = a_dimcr; - sw_ctxt->ddmcr = a_ddmcr; - sw_ctxt->dibar0 = a_dibar0; - sw_ctxt->dibar1 = a_dibar1; - sw_ctxt->dibar2 = a_dibar2; - sw_ctxt->dibar3 = a_dibar3; - sw_ctxt->ddbar0 = a_ddbar0; - sw_ctxt->ddbar1 = a_ddbar1; - sw_ctxt->ddbar2 = a_ddbar2; - sw_ctxt->ddbar3 = a_ddbar3; - sw_ctxt->ddmar0 = a_ddmar0; - sw_ctxt->ddmar1 = a_ddmar1; - sw_ctxt->dimar0 = a_dimar0; - sw_ctxt->dimar1 = a_dimar1; - -} - #ifdef CONFIG_CLW_ENABLE static inline void kvm_switch_clw_regs(struct kvm_sw_cpu_context *sw_ctxt, bool guest_enter) { @@ -421,6 +327,8 @@ switch_ctxt_trap_enable_mask(struct kvm_sw_cpu_context *sw_ctxt) sw_ctxt->osem = osem; } +extern void kvm_switch_debug_regs(struct kvm_sw_cpu_context *sw_ctxt, int is_active); + static inline void host_guest_enter(struct thread_info *ti, struct kvm_vcpu_arch *vcpu, unsigned flags) { @@ -444,6 +352,10 @@ static inline void host_guest_enter(struct thread_info *ti, } } + /* This makes a call so switch it before AAU */ + if (flags & DEBUG_REGS_SWITCH) + kvm_switch_debug_regs(sw_ctxt, true); + if (flags & FROM_HYPERCALL_SWITCH) { /* * Hypercalls - both hardware and software virtualization @@ -470,7 +382,8 @@ static inline void host_guest_enter(struct thread_info *ti, */ #ifdef CONFIG_USE_AAU if (!(flags & DONT_AAU_CONTEXT_SWITCH)) - machine.calculate_aau_aaldis_aaldas(NULL, ti, &sw_ctxt->aau_context); + machine.calculate_aau_aaldis_aaldas(NULL, ti->aalda, + &sw_ctxt->aau_context); #endif if (machine.flushts) @@ -501,7 +414,7 @@ static inline void host_guest_enter(struct thread_info *ti, * before restoring %aasr, so we must restore all AAU registers. */ native_clear_apb(); - native_set_aau_context(&sw_ctxt->aau_context); + native_set_aau_context(&sw_ctxt->aau_context, ti->aalda, E2K_FULL_AASR); /* * It's important to restore AAD after all return operations. @@ -519,9 +432,6 @@ static inline void host_guest_enter(struct thread_info *ti, kvm_switch_mmu_regs(sw_ctxt, false); } - if (flags & DEBUG_REGS_SWITCH) - kvm_switch_debug_regs(sw_ctxt, true); - KVM_BUG_ON(vcpu->is_hv && !NATIVE_READ_MMU_US_CL_D()); /* Switch data stack after all function calls */ @@ -617,19 +527,16 @@ static inline void host_guest_exit(struct thread_info *ti, */ #ifdef CONFIG_USE_AAU if (!(flags & DONT_AAU_CONTEXT_SWITCH)) { - e2k_aasr_t aasr; - /* * We cannot rely on %aasr value since interception could have * happened in guest user before "bap" or in guest trap handler * before restoring %aasr, so we must save all AAU registers. * Several macroses use %aasr to determine, which registers to - * save/restore, so pass worst-case %aasr to them in - * sw_ctxt->aau_context, and save the actual guest value to - * sw_ctxt->aasr + * save/restore, so pass worst-case %aasr to them directly + * while saving the actual guest value to sw_ctxt->aasr */ - aasr = native_read_aasr_reg(); - SWITCH_GUEST_AAU_AASR(&aasr, &sw_ctxt->aau_context, 1); + sw_ctxt->aasr = aasr_parse(native_read_aasr_reg()); + /* * This is placed before saving intc cellar since it is done * with 'mmurr' instruction which requires AAU to be stopped. @@ -637,7 +544,7 @@ static inline void host_guest_exit(struct thread_info *ti, * Do this before saving %sbbp as it uses 'alc' * and thus zeroes %aaldm. */ - NATIVE_SAVE_AAU_MASK_REGS(&sw_ctxt->aau_context, aasr); + NATIVE_SAVE_AAU_MASK_REGS(&sw_ctxt->aau_context, E2K_FULL_AASR); /* It's important to save AAD before all call operations. */ NATIVE_SAVE_AADS(&sw_ctxt->aau_context); @@ -650,7 +557,7 @@ static inline void host_guest_exit(struct thread_info *ti, /* Since iset v6 %aaldi must be saved too */ NATIVE_SAVE_AALDIS(sw_ctxt->aau_context.aaldi); - machine.get_aau_context(&sw_ctxt->aau_context); + machine.get_aau_context(&sw_ctxt->aau_context, E2K_FULL_AASR); native_clear_apb(); } @@ -687,6 +594,7 @@ static inline void host_guest_exit(struct thread_info *ti, kvm_switch_mmu_regs(sw_ctxt, false); } + /* This makes a call so switch it after AAU */ if (flags & DEBUG_REGS_SWITCH) kvm_switch_debug_regs(sw_ctxt, false); } @@ -1183,18 +1091,32 @@ host_trap_guest_exit(struct thread_info *ti, struct pt_regs *regs, host_switch_trap_enable_mask(ti, regs, false); } +static inline void __guest_exit(struct thread_info *ti, + struct kvm_vcpu_arch *vcpu, unsigned flags); /* * The function should return bool 'is the system call from guest?' */ static inline bool host_guest_syscall_enter(struct pt_regs *regs, bool ts_host_at_vcpu_mode) { + struct kvm_vcpu *vcpu; + if (likely(!ts_host_at_vcpu_mode)) return false; /* it is not guest system call */ clear_ts_flag(TS_HOST_AT_VCPU_MODE); - return pv_vcpu_syscall_intc(current_thread_info(), regs); + + vcpu = current_thread_info()->vcpu; + __guest_exit(current_thread_info(), &vcpu->arch, 0); + /* return to hypervisor MMU context to emulate intercept */ + kvm_switch_to_host_mmu_pid(vcpu, current->mm); + kvm_set_intc_emul_flag(regs); + + return true; } + +extern void host_pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs); + #endif /* CONFIG_VIRTUALIZATION */ #if defined(CONFIG_PARAVIRT_GUEST) @@ -1278,6 +1200,10 @@ static inline bool guest_syscall_enter(struct pt_regs *regs, { return native_guest_syscall_enter(regs); } +static inline void pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs) +{ + native_pv_vcpu_syscall_intc(ti, regs); +} static inline void guest_exit_intc(struct pt_regs *regs, bool intc_emul_flag) { } static inline void guest_syscall_exit_trap(struct pt_regs *regs, @@ -1365,6 +1291,11 @@ static inline bool guest_syscall_enter(struct pt_regs *regs, return host_guest_syscall_enter(regs, ts_host_at_vcpu_mode); } +static inline void pv_vcpu_syscall_intc(thread_info_t *ti, pt_regs_t *regs) +{ + host_pv_vcpu_syscall_intc(ti, regs); +} + static inline void guest_exit_intc(struct pt_regs *regs, bool intc_emul_flag) { if (unlikely(intc_emul_flag)) { diff --git a/arch/e2k/include/asm/kvm/tlbflush.h b/arch/e2k/include/asm/kvm/tlbflush.h index 8b7372f..622789c 100644 --- a/arch/e2k/include/asm/kvm/tlbflush.h +++ b/arch/e2k/include/asm/kvm/tlbflush.h @@ -18,31 +18,10 @@ * - flush_tlb_mm(mm) flushes the specified mm context TLB's * - flush_tlb_page(vma, vmaddr) flushes one page * - flush_tlb_range(mm, start, end) flushes a range of pages - * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables */ -extern void mmu_pv_flush_tlb_address(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - e2k_addr_t addr); -extern void mmu_pv_flush_tlb_address_pgtables(struct kvm_vcpu *vcpu, - gmm_struct_t *gmm, - e2k_addr_t addr); -extern void mmu_pv_flush_tlb_page(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - e2k_addr_t addr); -extern void mmu_pv_flush_tlb_mm(struct kvm_vcpu *vcpu, gmm_struct_t *gmm); extern void mmu_pv_flush_tlb_range(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, const e2k_addr_t start, const e2k_addr_t end); -extern void mmu_pv_flush_pmd_tlb_range(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - unsigned long start, unsigned long end); -extern void mmu_pv_flush_tlb_kernel_range(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - const e2k_addr_t start, const e2k_addr_t end); -extern void mmu_pv_flush_tlb_pgtables(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - e2k_addr_t start, e2k_addr_t end); -extern void mmu_pv_flush_tlb_range_and_pgtables(struct kvm_vcpu *vcpu, - gmm_struct_t *gmm, - e2k_addr_t start, e2k_addr_t end); -extern void mmu_pv_flush_tlb_page_and_pgtables(struct kvm_vcpu *vcpu, - gmm_struct_t *gmm, - unsigned long address); extern void mmu_pv_flush_cpu_root_pt_mm(struct kvm_vcpu *vcpu, gmm_struct_t *gmm); extern void mmu_pv_flush_cpu_root_pt(struct kvm_vcpu *vcpu); @@ -51,56 +30,28 @@ extern long kvm_pv_sync_and_flush_tlb(struct kvm_vcpu *vcpu, extern long kvm_pv_sync_addr_range(struct kvm_vcpu *vcpu, gva_t start_gva, gva_t end_gva); -extern void mmu_pv_smp_flush_tlb_mm(struct kvm_vcpu *vcpu, gmm_struct_t *gmm); -extern void mmu_pv_smp_flush_tlb_page(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - e2k_addr_t addr); -extern void mmu_pv_smp_flush_tlb_range(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - e2k_addr_t start, e2k_addr_t end); -extern void mmu_pv_smp_flush_pmd_tlb_range(struct kvm_vcpu *vcpu, gmm_struct_t *gmm, - e2k_addr_t start, e2k_addr_t end); -extern void mmu_pv_smp_flush_tlb_kernel_range(struct kvm_vcpu *vcpu, - gmm_struct_t *gmm, - e2k_addr_t start, e2k_addr_t end); -extern void mmu_pv_smp_flush_tlb_range_and_pgtables(struct kvm_vcpu *vcpu, - gmm_struct_t *gmm, - e2k_addr_t start, e2k_addr_t end); - extern void host_flush_shadow_pt_tlb_range(struct kvm_vcpu *vcpu, gva_t start, gva_t end, pgprot_t spte, int level); extern void host_flush_shadow_pt_level_tlb(struct kvm *kvm, gmm_struct_t *gmm, gva_t gva, int level, pgprot_t new_spte, pgprot_t old_spte); -#ifndef CONFIG_SMP -#define host_flush_tlb_mm(vcpu, gmm) \ - mmu_pv_flush_tlb_mm(vcpu, gmm) -#define host_flush_tlb_page(vcpu, gmm, addr) \ - mmu_pv_flush_tlb_page(vcpu, gmm, addr) -#define host_flush_tlb_range(vcpu, gmm, start, end) \ - mmu_pv_flush_tlb_range(vcpu, gmm, start, end) -#define host_flush_pmd_tlb_range(vcpu, gmm, start, end) \ - mmu_pv_flush_pmd_tlb_range(vcpu, gmm, start, end) -#define host_flush_tlb_mm_range(vcpu, gmm, start, end) \ - mmu_pv_flush_tlb_range(vcpu, gmm, start, end) -#define host_flush_tlb_kernel_range(vcpu, gmm, start, end) \ - mmu_pv_flush_tlb_kernel_range(vcpu, gmm, start, end) -#define host_flush_tlb_range_and_pgtables(vcpu, gmm, start, end) \ - mmu_pv_flush_tlb_range_and_pgtables(vcpu, gmm, start, end) -#else /* CONFIG_SMP */ -#define host_flush_tlb_mm(vcpu, gmm) \ - mmu_pv_smp_flush_tlb_mm(vcpu, gmm) -#define host_flush_tlb_page(vcpu, gmm, addr) \ - mmu_pv_smp_flush_tlb_page(vcpu, gmm, addr) -#define host_flush_tlb_range(vcpu, gmm, start, end) \ - mmu_pv_smp_flush_tlb_range(vcpu, gmm, start, end) -#define host_flush_pmd_tlb_range(vcpu, gmm, start, end) \ - mmu_pv_smp_flush_pmd_tlb_range(vcpu, gmm, start, end) -#define host_flush_tlb_kernel_range(vcpu, gmm, start, end) \ - mmu_pv_smp_flush_tlb_kernel_range(vcpu, gmm, start, end) -#define host_flush_tlb_mm_range(vcpu, gmm, start, end) \ - mmu_pv_smp_flush_tlb_range(vcpu, gmm, start, end) -#define host_flush_tlb_range_and_pgtables(vcpu, gmm, start, end) \ - mmu_pv_smp_flush_tlb_range_and_pgtables(vcpu, gmm, start, end) -#endif /* !CONFIG_SMP */ +/* + * Shadow PT TLB flushing (same as flush_tlb_*() but for gmm) + * Real switching to a new gmm context (PID) will be a little later + * while return from hypercall to the guest mode (host_guest_enter()), + * and it is then that the PID will become active, but now it is still passive. + */ + +extern void host_flush_tlb_mm(gmm_struct_t *gmm); +extern void host_flush_tlb_page(gmm_struct_t *gmm, unsigned long addr); +extern void host_flush_tlb_range(gmm_struct_t *gmm, + unsigned long start, unsigned long end); +extern void host_flush_tlb_kernel_range(gmm_struct_t *gmm, + unsigned long start, unsigned long end); +extern void host_flush_tlb_range_and_pgtables(gmm_struct_t *gmm, + unsigned long start, unsigned long end); +extern void host_flush_pmd_tlb_range(gmm_struct_t *gmm, + unsigned long start, unsigned long end); #endif /* _E2K_KVM_TLBFLUSH_H */ diff --git a/arch/e2k/include/asm/kvm/trace_kvm.h b/arch/e2k/include/asm/kvm/trace_kvm.h index 1f116ca..c923c5a 100644 --- a/arch/e2k/include/asm/kvm/trace_kvm.h +++ b/arch/e2k/include/asm/kvm/trace_kvm.h @@ -796,9 +796,10 @@ TRACE_EVENT( TRACE_EVENT( intc_aau, - TP_PROTO(const e2k_aau_t *aau_ctxt, u64 lsr, u64 lsr1, u64 ilcr, u64 ilcr1), + TP_PROTO(const e2k_aau_t *aau_ctxt, e2k_aasr_t aasr, + u64 lsr, u64 lsr1, u64 ilcr, u64 ilcr1), - TP_ARGS(aau_ctxt, lsr, lsr1, ilcr, ilcr1), + TP_ARGS(aau_ctxt, aasr, lsr, lsr1, ilcr, ilcr1), TP_STRUCT__entry( __field( u32, aasr ) @@ -829,7 +830,7 @@ TRACE_EVENT( TP_fast_assign( int i; - __entry->aasr = AW(aau_ctxt->guest_aasr); + __entry->aasr = AW(aasr); __entry->lsr = lsr; __entry->lsr1 = lsr1; __entry->ilcr = ilcr; diff --git a/arch/e2k/include/asm/kvm/trace_kvm_hv.h b/arch/e2k/include/asm/kvm/trace_kvm_hv.h index 63d422c..ae1d7e5 100644 --- a/arch/e2k/include/asm/kvm/trace_kvm_hv.h +++ b/arch/e2k/include/asm/kvm/trace_kvm_hv.h @@ -295,6 +295,13 @@ TRACE_EVENT( __field( u64, pcsp_hi ) __field( u64, pshtp ) __field( unsigned int, pcshtp ) + /* Backup stacks */ + __dynamic_array(u64, frames, hw_ctxt->bu_pcsp_hi.ind / SZ_OF_CR) + __field(size_t, frames_len) + __field( u64, bu_psp_lo ) + __field( u64, bu_psp_hi ) + __field( u64, bu_pcsp_lo ) + __field( u64, bu_pcsp_hi ) /* CRs */ __field( u64, cr0_lo ) __field( u64, cr0_hi ) @@ -303,6 +310,15 @@ TRACE_EVENT( ), TP_fast_assign( + u64 *frames = __get_dynamic_array(frames); + e2k_mem_crs_t *chain_stack = (e2k_mem_crs_t *) hw_ctxt->bu_pcsp_lo.base; + size_t len = hw_ctxt->bu_pcsp_hi.ind / SZ_OF_CR; + unsigned long i; + + __entry->frames_len = len; + for (i = 0; i < len; i++) + frames[i] = chain_stack[i].cr0_hi.ip << 3; + __entry->sbr = AW(sw_ctxt->sbr); __entry->usd_lo = AW(sw_ctxt->usd_lo); __entry->usd_hi = AW(sw_ctxt->usd_hi); @@ -316,17 +332,28 @@ TRACE_EVENT( __entry->cr0_hi = AW(crs->cr0_hi); __entry->cr1_lo = AW(crs->cr1_lo); __entry->cr1_hi = AW(crs->cr1_hi); + __entry->bu_psp_lo = AW(hw_ctxt->bu_psp_lo); + __entry->bu_psp_hi = AW(hw_ctxt->bu_psp_hi); + __entry->bu_pcsp_lo = AW(hw_ctxt->bu_pcsp_lo); + __entry->bu_pcsp_hi = AW(hw_ctxt->bu_pcsp_hi); ), TP_printk("sbr 0x%llx, usd_lo 0x%llx, usd_hi 0x%llx\n" - "sh_psp_lo 0x%llx, sh_psp_hi 0x%llx, sh_pcsp_lo 0x%llx, sh_pcsp_hi 0x%llx\n" - "sh_pshtp 0x%llx, sh_pcshtp 0x%x\n" + "sh_psp_lo 0x%llx, sh_psp_hi 0x%llx, sh_pshtp 0x%llx\n" + "sh_pcsp_lo 0x%llx, sh_pcsp_hi 0x%llx, sh_pcshtp 0x%x\n" "cr0_lo 0x%llx, cr0_hi 0x%llx, cr1_lo 0x%llx, cr1_hi 0x%llx\n" + "bu_psp_lo 0x%llx, bu_psp_hi 0x%llx\n" + "bu_pcsp_lo 0x%llx, bu_pcsp_hi 0x%llx\n" + "backup chain stack IPs: %s\n" , __entry->sbr, __entry->usd_lo, __entry->usd_hi, - __entry->psp_lo, __entry->psp_hi, __entry->pcsp_lo, __entry->pcsp_hi, - __entry->pshtp, __entry->pcshtp, - __entry->cr0_lo, __entry->cr0_hi, __entry->cr1_lo, __entry->cr1_hi) + __entry->psp_lo, __entry->psp_hi, __entry->pshtp, + __entry->pcsp_lo, __entry->pcsp_hi, __entry->pcshtp, + __entry->cr0_lo, __entry->cr0_hi, __entry->cr1_lo, __entry->cr1_hi, + __entry->bu_psp_lo, __entry->bu_psp_hi, + __entry->bu_pcsp_lo, __entry->bu_pcsp_hi, + __print_array(__get_dynamic_array(frames), + __entry->frames_len, sizeof(u64))) ); @@ -544,6 +571,7 @@ TRACE_EVENT( __entry->us_cl_m0, __entry->us_cl_m1, __entry->us_cl_m2, __entry->us_cl_m3) ); + #endif /* _TRACE_KVM_HV_H */ /* This part must be outside protection */ diff --git a/arch/e2k/include/asm/kvm/trap_table.S.h b/arch/e2k/include/asm/kvm/trap_table.S.h index caa3b89..1ccd5e4 100644 --- a/arch/e2k/include/asm/kvm/trap_table.S.h +++ b/arch/e2k/include/asm/kvm/trap_table.S.h @@ -123,7 +123,7 @@ shld %dr0, 32, %dr0 ? \ptmp0; } { - SMP_ONLY(shld,1 GCPUID, 3, GCPUOFFSET ? \ptmp0) + SMP_ONLY(shld,1 GCPUID_PREEMPT, 3, GCPUOFFSET ? \ptmp0) puttagd %dr3, 0, %dr3 ? \ptmp0; puttagd %dr4, 0, %dr4 ? \ptmp0; ord %dr0, \entry_num, %dr0 ? \ptmp0; @@ -141,6 +141,9 @@ puttagd %dr7, 0, %dr7 ? \ptmp0; ibranch goto_guest_kernel_ttable_C ? \ptmp0; } +#ifdef CONFIG_CPU_HWBUG_IBRANCH + {nop} {nop} +#endif .endm /* GOTO_GUEST_KERNEL_TTABLE */ # ifdef CONFIG_PARAVIRT_GUEST diff --git a/arch/e2k/include/asm/kvm_host.h b/arch/e2k/include/asm/kvm_host.h index 67277de..1356db0 100644 --- a/arch/e2k/include/asm/kvm_host.h +++ b/arch/e2k/include/asm/kvm_host.h @@ -106,12 +106,6 @@ kvm_is_hw_pv_vm_available(void) /* memory slots that does not exposed to userspace */ #define KVM_PRIVATE_MEM_SLOTS 4 -#undef E2K_INVALID_PAGE -#define E2K_INVALID_PAGE (~(hpa_t)0) - -#define UNMAPPED_GVA (~(gpa_t)0) -#define arch_is_error_gpa(gpa) ((gpa_t)(gpa) == UNMAPPED_GVA) - /* * See include/linux/kvm_host.h * For the normal pfn, the highest 12 bits should be zero, @@ -711,6 +705,7 @@ typedef struct kvm_sw_cpu_context { mmu_reg_t trap_count; bool no_switch_pt; /* do not switch PT registers */ + /* Monitors and breakpoints */ e2k_dibcr_t dibcr; e2k_ddbcr_t ddbcr; e2k_dibsr_t dibsr; @@ -729,9 +724,11 @@ typedef struct kvm_sw_cpu_context { u64 ddbar1; u64 ddbar2; u64 ddbar3; + e2k_dimtp_t dimtp; #ifdef CONFIG_USE_AAU e2k_aau_t aau_context; + e2k_aasr_t aasr; #endif u64 cs_lo; @@ -911,6 +908,8 @@ typedef struct kvm_host_context { unsigned osem; /* OSEM register state */ /* the host kernel's signal/trap stack of contexts */ kvm_signal_context_t signal; + /* kgregs of host kernel */ + struct kernel_gregs k_gregs; } kvm_host_context_t; #ifdef CONFIG_KVM_ASYNC_PF diff --git a/arch/e2k/include/asm/machdep.h b/arch/e2k/include/asm/machdep.h index 346dea5..f05a120 100644 --- a/arch/e2k/include/asm/machdep.h +++ b/arch/e2k/include/asm/machdep.h @@ -6,65 +6,13 @@ #include -#include #include +#include +#include #include -#include #ifdef __KERNEL__ -enum { - /* Hardware bugs */ - CPU_HWBUG_LARGE_PAGES, - CPU_HWBUG_LAPIC_TIMER, - CPU_HWBUG_PIO_READS, - CPU_HWBUG_ATOMIC, - CPU_HWBUG_CLW, - CPU_HWBUG_PAGE_A, - CPU_HWBUG_SPURIOUS_EXC_ILL_INSTR_ADDR, - CPU_HWBUG_UNALIGNED_LOADS, - CPU_HWBUG_CANNOT_DO_DMA_IN_NEIGHBOUR_NODE, - CPU_HWBUG_DMA_AT_APIC_ADDR, - CPU_HWBUG_KERNEL_DATA_MONITOR, - CPU_HWBUG_WRITE_MEMORY_BARRIER, - CPU_HWBUG_BAD_RESET, - CPU_HWBUG_BREAKPOINT_INSTR, - CPU_HWBUG_E8C_WATCHDOG, - CPU_HWBUG_IOMMU, - CPU_HWBUG_WC_DAM, - CPU_HWBUG_TRAP_CELLAR_S_F, - CPU_HWBUG_SS, - CPU_HWBUG_AAU_AALDV, - CPU_HWBUG_LEVEL_EOI, - CPU_HWBUG_FALSE_SS, - CPU_HWBUG_SPURIOUS_EXC_DATA_DEBUG, - CPU_HWBUG_TLB_FLUSH_L1D, - CPU_HWBUG_GUEST_ASYNC_PM, - CPU_HWBUG_E16C_SLEEP, - CPU_HWBUG_L1I_STOPS_WORKING, - CPU_HWBUG_CLW_STALE_L1_ENTRY, - CPU_HWBUG_PIPELINE_FREEZE_MONITORS, - CPU_HWBUG_C3_WAIT_MA_C, - CPU_HWBUG_VIRT_SCLKM3_INTC, - CPU_HWBUG_VIRT_PUSD_PSL, - CPU_HWBUG_USD_ALIGNMENT, - CPU_HWBUG_VIRT_PSIZE_INTERCEPTION, - CPU_NO_HWBUG_SOFT_WAIT, - - /* Features, not bugs */ - CPU_FEAT_WC_PCI_PREFETCH, - CPU_FEAT_FLUSH_DC_IC, - CPU_FEAT_EPIC, - CPU_FEAT_TRAP_V5, - CPU_FEAT_TRAP_V6, - CPU_FEAT_QPREG, - CPU_FEAT_ISET_V3, - CPU_FEAT_ISET_V5, - CPU_FEAT_ISET_V6, - - NR_CPU_FEATURES -}; - struct cpuinfo_e2k; struct pt_regs; struct seq_file; @@ -72,9 +20,10 @@ struct global_regs; struct kernel_gregs; struct local_gregs; struct e2k_aau_context; +struct e2k_mlt; struct kvm_vcpu_arch; -struct e2k_dimtp; struct thread_info; +union e2k_dimtp; #include /* virtualization support */ @@ -139,17 +88,17 @@ typedef struct machdep { void (*restore_gregs_on_mask)(struct global_regs *, bool dirty_bgr, unsigned long not_restore_gregs_mask); - void (*save_dimtp)(e2k_dimtp_t *); - void (*restore_dimtp)(const e2k_dimtp_t *); + void (*save_dimtp)(union e2k_dimtp *); + void (*restore_dimtp)(const union e2k_dimtp *); void (*save_kvm_context)(struct kvm_vcpu_arch *); void (*restore_kvm_context)(const struct kvm_vcpu_arch *); void (*calculate_aau_aaldis_aaldas)(const struct pt_regs *regs, - struct thread_info *ti, struct e2k_aau_context *context); + e2k_aalda_t *aaldas, struct e2k_aau_context *context); void (*do_aau_fault)(int aa_field, struct pt_regs *regs); void (*save_aaldi)(u64 *aaldis); - void (*get_aau_context)(struct e2k_aau_context *); + void (*get_aau_context)(struct e2k_aau_context *, e2k_aasr_t); unsigned long (*rrd)(int reg); void (*rwd)(int reg, unsigned long value); @@ -161,7 +110,7 @@ typedef struct machdep { #ifdef CONFIG_MLT_STORAGE void (*invalidate_MLT)(void); - void (*get_and_invalidate_MLT_context)(e2k_mlt_t *mlt_state); + void (*get_and_invalidate_MLT_context)(struct e2k_mlt *mlt_state); #endif void (*flushts)(void); @@ -196,7 +145,7 @@ typedef struct machdep { * being executed on. */ typedef void (*cpuhas_initcall_t)(int cpu, int revision, int iset_ver, - int guest_cpu, struct machdep *machine); + int guest_cpu, bool is_hardware_guest, struct machdep *machine); extern cpuhas_initcall_t __cpuhas_initcalls[], __cpuhas_initcalls_end[]; /* @@ -217,7 +166,7 @@ extern cpuhas_initcall_t __cpuhas_initcalls[], __cpuhas_initcalls_end[]; __init \ static void feat##_initializer(const int cpu, const int revision, \ const int iset_ver, const int guest_cpu, \ - struct machdep *const machine) { \ + bool is_hardware_guest, struct machdep *const machine) { \ bool is_static = (_is_static); \ if (is_static && (static_cond) || !is_static && (dynamic_cond)) \ set_bit(feat, (machine)->cpu_features); \ @@ -465,13 +414,17 @@ CPUHAS(CPU_HWBUG_CLW_STALE_L1_ENTRY, cpu == IDR_E2S_MDL || cpu == IDR_E8C_MDL || cpu == IDR_E8C2_MDL || cpu == IDR_E16C_MDL && revision == 0); /* #125405 - CPU pipeline freeze feature conflicts with performance monitoring. - * Workaround - disable pipeline freeze when monitoring is enabled. */ + * Workaround - disable pipeline freeze when monitoring is enabled. + * + * Note (#132311): disable workaround on e16c.rev0/e2c3.rev0 since it conflicts + * with #134929 workaround. */ CPUHAS(CPU_HWBUG_PIPELINE_FREEZE_MONITORS, - IS_ENABLED(CONFIG_E2K_MACHINE), - IS_ENABLED(CONFIG_CPU_E8C2) || IS_ENABLED(CONFIG_CPU_E16C) || - IS_ENABLED(CONFIG_CPU_E2C3) || IS_ENABLED(CONFIG_CPU_E12C), - cpu == IDR_E8C2_MDL || cpu == IDR_E16C_MDL || - cpu == IDR_E2C3_MDL || cpu == IDR_E12C_MDL); + IS_ENABLED(CONFIG_E2K_MACHINE) && !IS_ENABLED(CONFIG_CPU_E16C) && + !IS_ENABLED(CONFIG_CPU_E2C3), + IS_ENABLED(CONFIG_CPU_E8C2) || IS_ENABLED(CONFIG_CPU_E12C), + cpu == IDR_E8C2_MDL || cpu == IDR_E12C_MDL || + cpu == IDR_E16C_MDL && revision > 0 || + cpu == IDR_E2C3_MDL && revision > 0); /* #126587 - "wait ma_c=1" does not wait for all L2$ writebacks to complete * when disabling CPU core with "wait trap=1" algorithm. * Workaround - manually insert 66 NOPs before "wait trap=1" */ @@ -518,12 +471,31 @@ CPUHAS(CPU_HWBUG_VIRT_PSIZE_INTERCEPTION, cpu == IDR_E2C3_MDL && revision == 0); /* #130066, #134351 - L1/L2 do not respect "lal"/"las"/"sas"/"st_rel" barriers. - * Workaround - do not use "las"/"sas"/"st_rel", and add 5 nops after "lal". */ + * Workaround - do not use "las"/"sas"/"st_rel", and add 5 nops after "lal". + * #133605 - "lal"/"las"/"sas"/"sal" barriers do not work in certain conditions. + * Workaround - add {nop} before them. + * + * Note that #133605 workaround is split into two parts: + * CPU_NO_HWBUG_SOFT_WAIT - for e16c/e2c3 + * CPU_HWBUG_SOFT_WAIT_E8C2 - for e8c2 + * This is done because it is very convenient to merge #130066, #134351 + * and #133605 bugs workarounds together for e16c/e2c3. */ CPUHAS(CPU_NO_HWBUG_SOFT_WAIT, !IS_ENABLED(CONFIG_CPU_E16C) && !IS_ENABLED(CONFIG_CPU_E2C3), true, !(cpu == IDR_E16C_MDL && revision == 0 || cpu == IDR_E2C3_MDL && revision == 0)); +CPUHAS(CPU_HWBUG_SOFT_WAIT_E8C2, + IS_ENABLED(CONFIG_E2K_MACHINE), + IS_ENABLED(CONFIG_CPU_E8C2), + cpu == IDR_E8C2_MDL); + +/* #132693 - C3 idle state does not work. + * Workaround - do not use it. */ +CPUHAS(CPU_HWBUG_C3, + !IS_ENABLED(CONFIG_CPU_E16C), + false, + cpu == IDR_E16C_MDL && revision == 0); /* * Not bugs but features go here @@ -568,6 +540,56 @@ CPUHAS(CPU_FEAT_QPREG, CONFIG_CPU_ISET != 0, CONFIG_CPU_ISET >= 5, iset_ver >= E2K_ISET_V5); +/* Hardware prefetcher that resides in L2 and works on phys. addresses */ +CPUHAS(CPU_FEAT_HW_PREFETCHER, + IS_ENABLED(CONFIG_E2K_MACHINE), + !IS_ENABLED(CONFIG_CPU_ES2) && !IS_ENABLED(CONFIG_CPU_E2S) && + !IS_ENABLED(CONFIG_CPU_E8C) && !IS_ENABLED(CONFIG_CPU_E1CP) && + !IS_ENABLED(CONFIG_CPU_E8C2) && !IS_ENABLED(CONFIG_CPU_E16C) && + !IS_ENABLED(CONFIG_CPU_E2C3), + cpu != IDR_ES2_DSP_MDL && cpu != IDR_ES2_RU_MDL && + cpu != IDR_E2S_MDL && cpu != IDR_E8C_MDL && + cpu != IDR_E1CP_MDL && cpu != IDR_E8C2_MDL && + cpu != IDR_E16C_MDL && cpu != IDR_E2C3_MDL); +/* When flushing high order page table entries we must also flush + * all links below it. E.g. when flushing PMD also flush PMD->PTE + * link (i.e. DTLB entry for address 0xff8000000000|(address >> 9)). + * + * Otherwise the following can happen: + * 1) High-order page is allocated. + * 2) Someone accesses the PMD->PTE link (e.g. half-spec. load) and + * creates invalid entry in DTLB. + * 3) High-order page is split into 4 Kb pages. + * 4) Someone accesses the PMD->PTE link address (e.g. DTLB entry + * probe) and reads the invalid entry created earlier. + * + * Since v6 we have separate TLBs for intermediate page table levels + * (TLU_CACHE.PWC) and for last level and invalid records (TLB). + * So the invalid entry created in 2) would go into TLB while access + * in 4) will search TLU_CACHE.PWC rendering this flush unneeded. */ +CPUHAS(CPU_FEAT_SEPARATE_TLU_CACHE, + CONFIG_CPU_ISET != 0, + CONFIG_CPU_ISET >= 6, + iset_ver >= E2K_ISET_V6); +/* Set if FILLR instruction is supported. + * + * #135233 - FILLR does not work in hardware guests. + * Workaround - do not use it in hardware guests. */ +CPUHAS(CPU_FEAT_FILLR, + !IS_ENABLED(CONFIG_CPU_E16C) && !IS_ENABLED(CONFIG_CPU_E12C) && + !IS_ENABLED(CONFIG_CPU_E2C3), + CONFIG_CPU_ISET >= 6, + iset_ver >= E2K_ISET_V6 && + !((cpu == IDR_E16C_MDL || cpu == IDR_E12C_MDL || + cpu == IDR_E2C3_MDL) && is_hardware_guest)); +/* Set if FILLC instruction is supported. + * + * #135233 - software emulation of FILLC does not work in hardware guests. + * Workaround - use FILLC in hardware guests. */ +CPUHAS(CPU_FEAT_FILLC, + CONFIG_CPU_ISET != 0, + CONFIG_CPU_ISET >= 6, + iset_ver >= E2K_ISET_V6); /* Optimized version of machine.iset check */ CPUHAS(CPU_FEAT_ISET_V3, CONFIG_CPU_ISET != 0, @@ -599,10 +621,12 @@ static inline unsigned long test_feature_dynamic(struct machdep *machine, int fe test_feature(machine_p, feature) #define boot_cpu_has(feature) boot_machine_has(&boot_machine, feature) -#ifndef E2K_P2V +#ifdef CONFIG_BOOT_E2K # define cpu_has(feature) test_feature(&machine, feature) -#else +#elif defined(E2K_P2V) # define cpu_has(feature) boot_cpu_has(feature) +#else +# define cpu_has(feature) test_feature(&machine, feature) #endif /* Normally cpu_has() is passed symbolic name of feature (e.g. CPU_FEAT_*), @@ -670,25 +694,25 @@ extern void restore_gregs_on_mask_v2(struct global_regs *, bool dirty_bgr, unsigned long mask_not_restore); extern void restore_gregs_on_mask_v5(struct global_regs *, bool dirty_bgr, unsigned long mask_not_restore); -extern void save_dimtp_v6(e2k_dimtp_t *); -extern void restore_dimtp_v6(const e2k_dimtp_t *); +extern void save_dimtp_v6(union e2k_dimtp *); +extern void restore_dimtp_v6(const union e2k_dimtp *); extern void save_kvm_context_v6(struct kvm_vcpu_arch *); extern void restore_kvm_context_v6(const struct kvm_vcpu_arch *); extern void qpswitchd_sm(int); extern void calculate_aau_aaldis_aaldas_v2(const struct pt_regs *regs, - struct thread_info *ti, struct e2k_aau_context *context); + e2k_aalda_t *aaldas, struct e2k_aau_context *context); extern void calculate_aau_aaldis_aaldas_v5(const struct pt_regs *regs, - struct thread_info *ti, struct e2k_aau_context *context); + e2k_aalda_t *aaldas, struct e2k_aau_context *context); extern void calculate_aau_aaldis_aaldas_v6(const struct pt_regs *regs, - struct thread_info *ti, struct e2k_aau_context *context); + e2k_aalda_t *aaldas, struct e2k_aau_context *context); extern void do_aau_fault_v2(int aa_field, struct pt_regs *regs); extern void do_aau_fault_v5(int aa_field, struct pt_regs *regs); extern void do_aau_fault_v6(int aa_field, struct pt_regs *regs); extern void save_aaldi_v2(u64 *aaldis); extern void save_aaldi_v5(u64 *aaldis); -extern void get_aau_context_v2(struct e2k_aau_context *); -extern void get_aau_context_v5(struct e2k_aau_context *); +extern void get_aau_context_v2(struct e2k_aau_context *, e2k_aasr_t); +extern void get_aau_context_v5(struct e2k_aau_context *, e2k_aasr_t); extern void flushts_v3(void); @@ -723,9 +747,9 @@ void native_set_cu_hw1_v5(u64); void invalidate_MLT_v2(void); void invalidate_MLT_v3(void); -void get_and_invalidate_MLT_context_v2(e2k_mlt_t *mlt_state); -void get_and_invalidate_MLT_context_v3(e2k_mlt_t *mlt_state); -void get_and_invalidate_MLT_context_v6(e2k_mlt_t *mlt_state); +void get_and_invalidate_MLT_context_v2(struct e2k_mlt *mlt_state); +void get_and_invalidate_MLT_context_v3(struct e2k_mlt *mlt_state); +void get_and_invalidate_MLT_context_v6(struct e2k_mlt *mlt_state); #ifdef CONFIG_SMP void native_clock_off_v3(void); diff --git a/arch/e2k/include/asm/mas.h b/arch/e2k/include/asm/mas.h index 2481fbb..f3eaec9 100644 --- a/arch/e2k/include/asm/mas.h +++ b/arch/e2k/include/asm/mas.h @@ -1,7 +1,7 @@ #ifndef _E2K_MAS_H_ #define _E2K_MAS_H_ -#include +#include #include diff --git a/arch/e2k/include/asm/mm_hooks.h b/arch/e2k/include/asm/mm_hooks.h index d07df7b..a22b81d 100644 --- a/arch/e2k/include/asm/mm_hooks.h +++ b/arch/e2k/include/asm/mm_hooks.h @@ -8,6 +8,9 @@ #include +extern int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); +extern void arch_exit_mmap(struct mm_struct *mm); + static inline void arch_unmap(struct mm_struct *mm, unsigned long start, unsigned long end) { @@ -16,7 +19,12 @@ static inline void arch_unmap(struct mm_struct *mm, static inline void arch_bprm_mm_init(struct mm_struct *mm, struct vm_area_struct *vma) { - get_mm_notifier_locked(mm); +} + +static inline int arch_bprm_mm_init_locked(struct mm_struct *mm, + struct vm_area_struct *vma) +{ + return get_mm_notifier_locked(mm); } static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, diff --git a/arch/e2k/include/asm/mman.h b/arch/e2k/include/asm/mman.h index 7937a46..1b3fd29 100644 --- a/arch/e2k/include/asm/mman.h +++ b/arch/e2k/include/asm/mman.h @@ -80,7 +80,7 @@ static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags) page_prot = vm_flags & VM_CUI; if (vm_flags & VM_PRIVILEGED) - _PAGE_SET_PRIV(page_prot); + page_prot = _PAGE_SET_PRIV(page_prot); return __pgprot(page_prot); } @@ -121,7 +121,7 @@ enum exec_mmu_ret { }; extern enum exec_mmu_ret execute_mmu_operations(trap_cellar_t *tcellar, trap_cellar_t *next_tcellar, struct pt_regs *regs, - int rg, int zeroing, e2k_addr_t *addr, + int zeroing, e2k_addr_t *addr, bool (*is_spill_fill_recovery)(tc_cond_t cond, e2k_addr_t address, bool s_f, struct pt_regs *regs), diff --git a/arch/e2k/include/asm/mmu-regs-types-v2.h b/arch/e2k/include/asm/mmu-regs-types-v2.h index 6bfbda1..0e05302 100644 --- a/arch/e2k/include/asm/mmu-regs-types-v2.h +++ b/arch/e2k/include/asm/mmu-regs-types-v2.h @@ -7,6 +7,11 @@ #ifndef _ASM_E2K_MMU_REGS_TYPES_V2_H #define _ASM_E2K_MMU_REGS_TYPES_V2_H +/* Avoid header dependency loop of probe_entry_t and DTLB_ENTRY_PH_BOUND_V2 */ +#ifndef _E2K_TLB_REGS_TYPES_H_ +# error Do not include directly, use instead +#endif + /* * This file contains the functions and defines necessary to modify and * use the E2K ISET V2-V5 page tables. diff --git a/arch/e2k/include/asm/mmu-regs-types-v6.h b/arch/e2k/include/asm/mmu-regs-types-v6.h index 8dda520..2e2db39 100644 --- a/arch/e2k/include/asm/mmu-regs-types-v6.h +++ b/arch/e2k/include/asm/mmu-regs-types-v6.h @@ -7,6 +7,11 @@ #ifndef _ASM_E2K_MMU_REGS_TYPES_V6_H #define _ASM_E2K_MMU_REGS_TYPES_V6_H +/* Avoid header dependency loop of probe_entry_t and DTLB_ENTRY_PH_BOUND_V6 */ +#ifndef _E2K_TLB_REGS_TYPES_H_ +# error Do not include directly, use instead +#endif + /* * This file contains the functions and defines necessary to modify and * use the E2K ISET V2-V5 page tables. diff --git a/arch/e2k/include/asm/mmu_context.h b/arch/e2k/include/asm/mmu_context.h index bb45a57..aaf2a1b 100644 --- a/arch/e2k/include/asm/mmu_context.h +++ b/arch/e2k/include/asm/mmu_context.h @@ -58,9 +58,6 @@ extern unsigned long mmu_last_context; #define my_cpu_last_context1(num_cpu) mmu_last_context #endif /* CONFIG_SMP */ -extern int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); -extern void arch_exit_mmap(struct mm_struct *mm); - static inline void reload_context_mask(unsigned long mask) { diff --git a/arch/e2k/include/asm/mmu_regs.h b/arch/e2k/include/asm/mmu_regs.h index cb51ad3..6056235 100644 --- a/arch/e2k/include/asm/mmu_regs.h +++ b/arch/e2k/include/asm/mmu_regs.h @@ -448,30 +448,34 @@ read_MMU_US_CL_D(void) static inline void ____flush_TLB_page(flush_op_t flush_op, flush_addr_t flush_addr) { - unsigned long flags; - bool fl_c_needed = cpu_has(CPU_HWBUG_TLB_FLUSH_L1D); DebugTLB("Flush TLB page : op 0x%lx extended virtual addr 0x%lx\n", - flush_op_val(flush_op), flush_addr_val(flush_addr)); + flush_op, flush_addr); - raw_all_irq_save(flags); - FLUSH_TLB_ENTRY(flush_op_val(flush_op), flush_addr_val(flush_addr)); - if (fl_c_needed) + FLUSH_TLB_ENTRY(flush_op, flush_addr); + if (cpu_has(CPU_HWBUG_TLB_FLUSH_L1D)) __E2K_WAIT(_fl_c); - raw_all_irq_restore(flags); } #define flush_TLB_page_begin() #define flush_TLB_page_end() \ do { \ - __E2K_WAIT(_fl_c | _ma_c); \ + __E2K_WAIT(_fl_c); \ } while (0) +static inline void __flush_TLB_page_tlu_cache(unsigned long virt_addr, + unsigned long context, u64 type) +{ + u64 va_tag = (virt_addr >> (9 * type + 12)); + ____flush_TLB_page(FLUSH_TLB_PAGE_TLU_CACHE_OP, + (va_tag << 21) | (context << 50) | type); +} + + static inline void __flush_TLB_page(e2k_addr_t virt_addr, unsigned long context) { - ____flush_TLB_page(flush_op_tlb_page_sys, - flush_addr_make_sys(virt_addr, context)); + ____flush_TLB_page(FLUSH_TLB_PAGE_OP, flush_addr_make_sys(virt_addr, context)); } static inline void @@ -499,8 +503,7 @@ flush_TLB_kernel_page(e2k_addr_t virt_addr) static inline void __flush_TLB_ss_page(e2k_addr_t virt_addr, unsigned long context) { - ____flush_TLB_page(flush_op_tlb_page_sys, - flush_addr_make_ss(virt_addr, context)); + ____flush_TLB_page(FLUSH_TLB_PAGE_OP, flush_addr_make_ss(virt_addr, context)); } static inline void @@ -628,8 +631,8 @@ static inline void __flush_ICACHE_line(flush_op_t flush_op, flush_addr_t flush_addr) { DebugMR("Flush ICACHE line : op 0x%lx extended virtual addr 0x%lx\n", - flush_op_val(flush_op), flush_addr_val(flush_addr)); - FLUSH_ICACHE_LINE(flush_op_val(flush_op), flush_addr_val(flush_addr)); + flush_op, flush_addr); + FLUSH_ICACHE_LINE(flush_op, flush_addr); } #define flush_ICACHE_line_begin() @@ -641,8 +644,7 @@ do { \ static inline void __flush_ICACHE_line_user(e2k_addr_t virt_addr) { - __flush_ICACHE_line(flush_op_icache_line_user, - flush_addr_make_user(virt_addr)); + __flush_ICACHE_line(FLUSH_ICACHE_LINE_USER_OP, flush_addr_make_user(virt_addr)); } static inline void @@ -656,8 +658,7 @@ flush_ICACHE_line_user(e2k_addr_t virt_addr) static inline void __flush_ICACHE_line_sys(e2k_addr_t virt_addr, unsigned long context) { - __flush_ICACHE_line(flush_op_icache_line_sys, - flush_addr_make_sys(virt_addr, context)); + __flush_ICACHE_line(FLUSH_ICACHE_LINE_SYS_OP, flush_addr_make_sys(virt_addr, context)); } static inline void @@ -691,9 +692,9 @@ boot_native_invalidate_CACHE_L12(void) raw_all_irq_save(flags); E2K_WAIT_MA; if (invalidate_supported) - NATIVE_FLUSH_CACHE_L12(_flush_op_invalidate_cache_L12); + NATIVE_FLUSH_CACHE_L12(flush_op_invalidate_cache_L12); else - NATIVE_FLUSH_CACHE_L12(_flush_op_write_back_cache_L12); + NATIVE_FLUSH_CACHE_L12(flush_op_write_back_cache_L12); E2K_WAIT_FLUSH; raw_all_irq_restore(flags); } @@ -708,7 +709,7 @@ static inline void native_raw_write_back_CACHE_L12(void) { __E2K_WAIT(_ma_c); - NATIVE_FLUSH_CACHE_L12(_flush_op_write_back_cache_L12); + NATIVE_FLUSH_CACHE_L12(flush_op_write_back_cache_L12); __E2K_WAIT(_fl_c | _ma_c); } @@ -716,8 +717,8 @@ static inline void write_back_CACHE_L12(void) { DebugMR("Flush : Write back all CACHEs (op 0x%lx)\n", - _flush_op_write_back_cache_L12); - FLUSH_CACHE_L12(_flush_op_write_back_cache_L12); + flush_op_write_back_cache_L12); + FLUSH_CACHE_L12(flush_op_write_back_cache_L12); } /* @@ -728,15 +729,15 @@ static inline void native_raw_flush_TLB_all(void) { __E2K_WAIT(_st_c); - NATIVE_FLUSH_TLB_ALL(_flush_op_tlb_all); + NATIVE_FLUSH_TLB_ALL(flush_op_tlb_all); __E2K_WAIT(_fl_c | _ma_c); } static inline void flush_TLB_all(void) { - DebugMR("Flush all TLBs (op 0x%lx)\n", _flush_op_tlb_all); - FLUSH_TLB_ALL(_flush_op_tlb_all); + DebugMR("Flush all TLBs (op 0x%lx)\n", flush_op_tlb_all); + FLUSH_TLB_ALL(flush_op_tlb_all); } /* @@ -745,8 +746,8 @@ flush_TLB_all(void) static inline void flush_ICACHE_all(void) { - DebugMR("Flush all ICACHE op 0x%lx\n", _flush_op_icache_all); - FLUSH_ICACHE_ALL(_flush_op_icache_all); + DebugMR("Flush all ICACHE op 0x%lx\n", flush_op_icache_all); + FLUSH_ICACHE_ALL(flush_op_icache_all); } /* diff --git a/arch/e2k/include/asm/mmu_regs_types.h b/arch/e2k/include/asm/mmu_regs_types.h index 85e1ca7..aae6749 100644 --- a/arch/e2k/include/asm/mmu_regs_types.h +++ b/arch/e2k/include/asm/mmu_regs_types.h @@ -536,33 +536,15 @@ typedef dcache_addr_t dcache_l2_addr_t; typedef e2k_addr_t flush_op_t; #endif /* ! __ASSEMBLY__ */ -#define flush_op_val(flush_op) (flush_op) +#define FLUSH_OP_TYPE ULL(7) /* type of operation */ +#define FLUSH_ICACHE_LINE_USER_OP ULL(0) +#define FLUSH_TLB_PAGE_OP ULL(1) +#define FLUSH_ICACHE_LINE_SYS_OP ULL(2) +#define FLUSH_TLB_PAGE_TLU_CACHE_OP ULL(3) -#define __flush_op(flush_op_val) (flush_op_val) - -#define _FLUSH_OP_TYPE 0x0000000000000007 /* type of */ - /* operation */ -#define _FLUSH_ICACHE_LINE_USER_OP 0x0000000000000000 -#define _FLUSH_TLB_PAGE_SYS_OP 0x0000000000000001 -#define _FLUSH_ICACHE_LINE_SYS_OP 0x0000000000000002 - -#define flush_op_get_type(flush_op) \ - (flush_op_val(flush_op) & _FLUSH_OP_TYPE) +#define flush_op_get_type(flush_op) ((flush_op) & FLUSH_OP_TYPE) #define flush_op_set_type(flush_op, type) \ - (__flush_op((flush_op_val(flush_op) & ~_FLUSH_OP_TYPE) | \ - ((type) & _FLUSH_OP_TYPE))) -#define flush_op_set_icache_line_user(flush_op) \ - flush_op_set_type(flush_op, _FLUSH_ICACHE_LINE_USER_OP) -#define flush_op_set_icache_line_sys(flush_op) \ - flush_op_set_type(flush_op, _FLUSH_ICACHE_LINE_SYS_OP) -#define flush_op_set_tlb_page_sys(flush_op) \ - flush_op_set_type(flush_op, _FLUSH_TLB_PAGE_SYS_OP) -#define _flush_op_icache_line_user ((long)_FLUSH_ICACHE_LINE_USER_OP) -#define _flush_op_icache_line_sys ((long)_FLUSH_ICACHE_LINE_SYS_OP) -#define _flush_op_tlb_page_sys ((long)_FLUSH_TLB_PAGE_SYS_OP) -#define flush_op_icache_line_user __flush_op(_flush_op_icache_line_user) -#define flush_op_icache_line_sys __flush_op(_flush_op_icache_line_sys) -#define flush_op_tlb_page_sys __flush_op(_flush_op_tlb_page_sys) + (((flush_op) & ~FLUSH_OP_TYPE) | ((type) & FLUSH_OP_TYPE)) /* ICACHE/DTLB/ITLB line flush extended virtual address structure */ @@ -570,60 +552,30 @@ typedef e2k_addr_t flush_op_t; typedef e2k_addr_t flush_addr_t; #endif /* ! __ASSEMBLY__ */ -#define flush_addr_val(flush_addr) (flush_addr) +#define FLUSH_ADDR_CONTEXT_SHIFT ULL(50) /* [61:50] */ +#define FLUSH_ADDR_VA ULL(0x0000ffffffffffff) /* virtual address */ +#define FLUSH_ADDR_CONTEXT ULL(0x3ffc000000000000) /* context # */ +#define FLUSH_ADDR_ROOT ULL(0x4000000000000000) /* should be 0 */ +#define FLUSH_ADDR_PHYS ULL(0x8000000000000000) /* should be 0 */ -#define __flush_addr(flush_addr_val) (flush_addr_val) - -#define _FLUSH_ADDR_CONTEXT_SHIFT 50 /* [61:50] */ - -#define _FLUSH_ADDR_VA 0x0000ffffffffffff /* virtual address */ - /* [47: 0] */ -#define _FLUSH_ADDR_CONTEXT 0x3ffc000000000000 /* context # */ -#define _FLUSH_ADDR_ROOT 0x4000000000000000 /* should be 0 */ -#define _FLUSH_ADDR_PHYS 0x8000000000000000 /* should be 0 */ - -#define FLUSH_VADDR_TO_VA(virt_addr) ((virt_addr) & _FLUSH_ADDR_VA) - -#define _FLUSH_ADDR_KERNEL(virt_addr) (FLUSH_VADDR_TO_VA(virt_addr) | \ - ((long)E2K_KERNEL_CONTEXT << _FLUSH_ADDR_CONTEXT_SHIFT)) - -#define FLUSH_ADDR_KERNEL(virt_addr) \ - __flush_addr(_FLUSH_ADDR_KERNEL(virt_addr)) - -#define flush_addr_get_va(flush_addr) \ - (flush_addr_val(flush_addr) & _FLUSH_ADDR_VA) -#define flush_addr_set_va(flush_addr, virt_addr) \ - (__flush_addr((flush_addr_val(flush_addr) & ~_FLUSH_ADDR_VA) | \ - ((va_page) & _FLUSH_ADDR_VA))) +#define FLUSH_VADDR_TO_VA(virt_addr) ((virt_addr) & FLUSH_ADDR_VA) #define flush_addr_get_pid(flush_addr) \ - ((flush_addr_val(flush_addr) & _FLUSH_ADDR_CONTEXT) >> \ - _FLUSH_ADDR_CONTEXT_SHIFT) -#define flush_addr_get_context(flush_addr) \ - (flush_addr_val(flush_addr) & _FLUSH_ADDR_CONTEXT) -#define flush_addr_set_context(flush_addr, context) \ - (__flush_addr((flush_addr_val(flush_addr) & \ - ~_FLUSH_ADDR_CONTEXT) | \ - ((long)(context) << _FLUSH_ADDR_CONTEXT_SHIFT) & \ - _FLUSH_ADDR_CONTEXT)) + (((flush_addr) & FLUSH_ADDR_CONTEXT) >> FLUSH_ADDR_CONTEXT_SHIFT) #define _flush_addr_make_sys(virt_addr, context, root) \ ({ \ e2k_addr_t __addr_val = FLUSH_VADDR_TO_VA(virt_addr); \ - __addr_val |= (((long)(context) << \ - _FLUSH_ADDR_CONTEXT_SHIFT) & \ - _FLUSH_ADDR_CONTEXT); \ + __addr_val |= (((long)(context) << FLUSH_ADDR_CONTEXT_SHIFT) & \ + FLUSH_ADDR_CONTEXT); \ if (root) \ - __addr_val |= _FLUSH_ADDR_ROOT; \ + __addr_val |= FLUSH_ADDR_ROOT; \ __addr_val; \ }) -#define _flush_addr_make_user(virt_addr) \ - FLUSH_VADDR_TO_VA(virt_addr) #define flush_addr_make_sys(virt_addr, context) \ - __flush_addr(_flush_addr_make_sys(virt_addr, context, 0)) -#define flush_addr_make_user(virt_addr) \ - __flush_addr(_flush_addr_make_user(virt_addr)) + _flush_addr_make_sys((virt_addr), (context), 0) +#define flush_addr_make_user(virt_addr) FLUSH_VADDR_TO_VA(virt_addr) #define flush_addr_make_ss(virt_addr, context) \ - __flush_addr(_flush_addr_make_sys(virt_addr, context, 1)) + _flush_addr_make_sys((virt_addr), (context), 1) /* * CACHE(s) flush operations @@ -644,14 +596,8 @@ typedef e2k_addr_t flush_addr_t; flush_op_set_type(flush_op, _FLUSH_WRITE_BACK_CACHE_L12_OP) #define flush_op_set_cache_all(flush_op) \ flush_op_set_write_back_cache_L12(flush_op) -#define _flush_op_invalidate_cache_L12 ((long)_FLUSH_INVALIDATE_CACHE_L12_OP) -#define _flush_op_write_back_cache_L12 ((long)_FLUSH_WRITE_BACK_CACHE_L12_OP) -#define _flush_op_cache_all _flush_op_write_back_cache_L12 -#define flush_op_invalidate_cache_L12 \ - __flush_op(_flush_op_invalidate_cache_L12) -#define flush_op_write_back_cache_L12 \ - __flush_op(_flush_op_write_back_cache_L12) -#define flush_op_cache_all flush_op_write_back_cache_L12 +#define flush_op_invalidate_cache_L12 ((long)_FLUSH_INVALIDATE_CACHE_L12_OP) +#define flush_op_write_back_cache_L12 ((long)_FLUSH_WRITE_BACK_CACHE_L12_OP) /* * ICACHE/TLB flush operations @@ -666,10 +612,8 @@ typedef e2k_addr_t flush_addr_t; flush_op_set_type(flush_op, _FLUSH_ICACHE_ALL_OP) #define flush_op_set_tlb_all(flush_op) \ flush_op_set_type(flush_op, _FLUSH_TLB_ALL_OP) -#define _flush_op_icache_all ((long)_FLUSH_ICACHE_ALL_OP) -#define _flush_op_tlb_all ((long)_FLUSH_TLB_ALL_OP) -#define flush_op_icache_all __flush_op(_flush_op_icache_all) -#define flush_op_tlb_all __flush_op(_flush_op_tlb_all) +#define flush_op_icache_all ((long)_FLUSH_ICACHE_ALL_OP) +#define flush_op_tlb_all ((long)_FLUSH_TLB_ALL_OP) /* @@ -839,7 +783,7 @@ typedef union { u64 sf0 : 1; u64 hw0 : 1; u64 t0 : 1; - u64 __x0 : 1; + u64 : 1; u64 v1 : 1; u64 root1 : 1; u64 rw1 : 2; @@ -850,7 +794,7 @@ typedef union { u64 sf1 : 1; u64 hw1 : 1; u64 t1 : 1; - u64 __x1 : 1; + u64 : 1; u64 v2 : 1; u64 root2 : 1; u64 rw2 : 2; @@ -861,7 +805,7 @@ typedef union { u64 sf2 : 1; u64 hw2 : 1; u64 t2 : 1; - u64 __x2 : 1; + u64 : 1; u64 v3 : 1; u64 root3 : 1; u64 rw3 : 2; @@ -872,56 +816,9 @@ typedef union { u64 sf3 : 1; u64 hw3 : 1; u64 t3 : 1; - u64 __x3 : 1; + u64 : 1; u64 gm : 1; }; - struct { - u64 v0 : 1; - u64 root0 : 1; - u64 rw0 : 2; - u64 lng0 : 3; - u64 sync0 : 1; - u64 spec0 : 1; - u64 ap0 : 1; - u64 sf0 : 1; - u64 hw0 : 1; - u64 t0 : 1; - u64 __x0 : 1; - u64 v1 : 1; - u64 root1 : 1; - u64 rw1 : 2; - u64 lng1 : 3; - u64 sync1 : 1; - u64 spec1 : 1; - u64 ap1 : 1; - u64 sf1 : 1; - u64 hw1 : 1; - u64 t1 : 1; - u64 __x1 : 1; - u64 v2 : 1; - u64 root2 : 1; - u64 rw2 : 2; - u64 lng2 : 3; - u64 sync2 : 1; - u64 spec2 : 1; - u64 ap2 : 1; - u64 sf2 : 1; - u64 hw2 : 1; - u64 t2 : 1; - u64 __x2 : 1; - u64 v3 : 1; - u64 root3 : 1; - u64 rw3 : 2; - u64 lng3 : 3; - u64 sync3 : 1; - u64 spec3 : 1; - u64 ap3 : 1; - u64 sf3 : 1; - u64 hw3 : 1; - u64 t3 : 1; - u64 __x3 : 1; - u64 gm : 1; - } fields; u64 word; } e2k_ddbcr_t; #define DDBCR_reg word diff --git a/arch/e2k/include/asm/mmu_types.h b/arch/e2k/include/asm/mmu_types.h index 8caa61e..b8b66b3 100644 --- a/arch/e2k/include/asm/mmu_types.h +++ b/arch/e2k/include/asm/mmu_types.h @@ -1,8 +1,9 @@ #ifndef _E2K_MMU_TYPES_H_ #define _E2K_MMU_TYPES_H_ +#include #include - +#include #include #ifndef __ASSEMBLY__ @@ -132,6 +133,12 @@ typedef struct { pgprotval_t pgprot; } pgprot_t; #define E2K_PUD_LEVEL_NUM 3 /* level number of native pud */ #define E2K_PGD_LEVEL_NUM 4 /* level number of native pgd */ +#define E2K_PAGES_LEVEL_MASK (1 << E2K_PAGES_LEVEL_NUM) +#define E2K_PTE_LEVEL_MASK (1 << E2K_PTE_LEVEL_NUM) +#define E2K_PMD_LEVEL_MASK (1 << E2K_PMD_LEVEL_NUM) +#define E2K_PUD_LEVEL_MASK (1 << E2K_PUD_LEVEL_NUM) +#define E2K_PGD_LEVEL_MASK (1 << E2K_PGD_LEVEL_NUM) + /* max level # on which can map huge pages: pmd, pud */ #define MAX_HUGE_PAGES_LEVEL E2K_PUD_LEVEL_NUM @@ -501,18 +508,68 @@ typedef union mmu_tc_cond_dword { } mmu_tc_cond_dword_t; typedef union { + struct { + u64 dst :10; // [0-9] + u64 opcode :6; // [10-15] + u64 r0 :1; // [16] + u64 store :1; // [17] + u64 mode_80 :1; // [18] + u64 s_f :1; // [19] + u64 mas :7; // [20-26] + u64 root :1; // [27] + u64 scal :1; // [28] + u64 sru :1; // [29] + u64 spec :1; // [30] + u64 pm :1; // [31] + u64 chan :2; // [32-33] + u64 r1 :1; // [34] + u64 fault_type :13; // [35-47] + u64 miss_lvl :2; // [48-49] + u64 num_align :1; // [50] + u64 empt :1; // [51] + u64 clw :1; // [52] + u64 dst_rcv :10; // [53-62] + u64 rcv :1; // [63] + }; + struct { + u64 address :8; // [0-7] + u64 vr :1; // [8] + u64 vl :1; // [9] + u64 fmt :3; // [10-12] + /* Be careful: npsp=1 => access is not protected, + * but npsp=0 does not mean that access is protected. */ + u64 npsp :1; // [13] + u64 fmtc :2; // [14-15] + u64 ___x1 :19; // [34-16] + u64 global_sp :1; /* [35] */ + u64 page_bound :1; /* [36] */ + u64 exc_mem_lock :1; /* [37] */ + u64 ph_pr_page :1; /* [38] */ + u64 io_page :1; /* [39] */ + u64 isys_page :1; /* [40] */ + u64 prot_page :1; /* [41] */ + u64 priv_page :1; /* [42] */ + u64 illegal_page :1; /* [43] */ + u64 nwrite_page :1; /* [44] */ + u64 page_miss :1; /* [45] */ + u64 ph_bound :1; /* [46] */ + u64 intl_res_bits :1; /* [47] */ + u64 ___x0 :5; /* [52:48] */ + u64 dst_ind :8; /* [60:53] */ + u64 ___x2 :3; /* [63-61] */ + }; u64 word; union mmu_tc_cond_dword fields; } tc_cond_t; -#define TC_COND_FMT_FULL(cond) (AS(cond).fmt | (AS(cond).fmtc << 3)) +#define TC_COND_FMT_FULL(cond) (cond.fmt | (cond.fmtc << 3)) static inline bool tc_cond_is_special_mmu_aau(tc_cond_t cond) { - unsigned int mas = AS(cond).mas; - int chan = AS(cond).chan; - int store = AS(cond).store; - int spec_mode = AS(cond).spec; + unsigned int mas = cond.mas; + int chan = cond.chan; + int store = cond.store; + int spec_mode = cond.spec; if (unlikely(is_mas_special_mmu_aau(mas) && (store || !store && !spec_mode && (chan == 1 || chan == 3)))) @@ -523,36 +580,36 @@ static inline bool tc_cond_is_special_mmu_aau(tc_cond_t cond) static inline bool tc_cond_is_check_ld(tc_cond_t cond) { - unsigned int mas = AS(cond).mas; - int store = AS(cond).store; - int spec_mode = AS(cond).spec; + unsigned int mas = cond.mas; + int store = cond.store; + int spec_mode = cond.spec; return is_mas_check(mas) && !spec_mode && !store; } static inline bool tc_cond_is_check_unlock_ld(tc_cond_t cond) { - unsigned int mas = AS(cond).mas; - int store = AS(cond).store; - int spec_mode = AS(cond).spec; + unsigned int mas = cond.mas; + int store = cond.store; + int spec_mode = cond.spec; return is_mas_check_unlock(mas) && !spec_mode && !store; } static inline bool tc_cond_is_lock_check_ld(tc_cond_t cond) { - unsigned int mas = AS(cond).mas; - int store = AS(cond).store; - int spec_mode = AS(cond).spec; + unsigned int mas = cond.mas; + int store = cond.store; + int spec_mode = cond.spec; return is_mas_lock_check(mas) && spec_mode && !store; } static inline bool tc_cond_is_spec_lock_check_ld(tc_cond_t cond) { - unsigned int mas = AS(cond).mas; - int store = AS(cond).store; - int spec_mode = AS(cond).spec; + unsigned int mas = cond.mas; + int store = cond.store; + int spec_mode = cond.spec; return is_mas_spec_lock_check(mas) && spec_mode && !store; } @@ -569,7 +626,7 @@ static inline int tc_cond_to_size(tc_cond_t cond) if (fmt == LDST_QP_FMT || fmt == TC_FMT_QPWORD_Q) { size = 16; } else if (fmt == LDST_QWORD_FMT || fmt == TC_FMT_QWORD_QP) { - if (AS(cond).chan == 0 || AS(cond).chan == 2) + if (cond.chan == 0 || cond.chan == 2) size = 16; else size = 8; @@ -621,11 +678,11 @@ ldst_chan_num_to_chan_opc(int chan_opc) static inline bool tc_cond_load_has_store_semantics(tc_cond_t condition, unsigned iset_ver) { - const unsigned mas = AS(condition).mas; + const unsigned mas = condition.mas; const unsigned mod = (mas & MAS_MOD_MASK) >> MAS_MOD_SHIFT; - const unsigned chan = AS(condition).chan; - const bool root = AS(condition).root; - const bool spec = AS(condition).spec; + const unsigned chan = condition.chan; + const bool root = condition.root; + const bool spec = condition.spec; if (chan != 0) return false; @@ -646,9 +703,9 @@ tc_cond_load_has_store_semantics(tc_cond_t condition, unsigned iset_ver) static inline bool tc_cond_is_store(tc_cond_t condition, unsigned iset_ver) { - const unsigned mas = AS(condition).mas; + const unsigned mas = condition.mas; - if (AS(condition).store && (mas != MAS_DCACHE_LINE_FLUSH)) + if (condition.store && (mas != MAS_DCACHE_LINE_FLUSH)) return true; return tc_cond_load_has_store_semantics(condition, iset_ver); } @@ -706,7 +763,7 @@ typedef struct { static inline bool is_record_asynchronous(tc_cond_t cond) { /* We use bitwise OR for performance */ - return AS(cond).mode_80 | AS(cond).s_f | AS(cond).sru | AS(cond).clw; + return cond.mode_80 | cond.s_f | cond.sru | cond.clw; } /** diff --git a/arch/e2k/include/asm/msgbuf.h b/arch/e2k/include/asm/msgbuf.h deleted file mode 100644 index ffbd1ef..0000000 --- a/arch/e2k/include/asm/msgbuf.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _E2K_MSGBUF_H_ -#define _E2K_MSGBUF_H_ - -/* - * The msqid64_ds structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - __kernel_time_t msg_rtime; /* last msgrcv time */ - __kernel_time_t msg_ctime; /* last change time */ - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _E2K_MSGBUF_H_ */ diff --git a/arch/e2k/include/asm/native_aau_regs_access.h b/arch/e2k/include/asm/native_aau_regs_access.h index 5094967..ef10cad 100644 --- a/arch/e2k/include/asm/native_aau_regs_access.h +++ b/arch/e2k/include/asm/native_aau_regs_access.h @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -137,7 +136,7 @@ static __always_inline void native_write_aasr_reg_value(u32 reg_value) { NATIVE_SET_AAU_AASR(reg_value); } -static inline u32 native_read_aafstr_reg_value(void) +static __always_inline u32 native_read_aafstr_reg_value(void) { return NATIVE_GET_AAU_AAFSTR(); } @@ -1165,7 +1164,8 @@ native_write_aaldas_reg_value(int AALDAs_no, u32 l_value, u32 r_value) r_value = 0; } } -static inline void native_read_aaldm_reg_value(u32 *lo_value, u32 *hi_value) +static __always_inline void native_read_aaldm_reg_value(u32 *lo_value, + u32 *hi_value) { u32 value1, value2; @@ -1174,19 +1174,20 @@ static inline void native_read_aaldm_reg_value(u32 *lo_value, u32 *hi_value) *hi_value = value2; } static __always_inline void native_write_aaldm_reg_value(u32 lo_value, - u32 hi_value) + u32 hi_value) { NATIVE_SET_AAU_AALDM(lo_value, hi_value); } -static inline void native_read_aaldm_reg(e2k_aaldm_t *aaldm) +static __always_inline void native_read_aaldm_reg(e2k_aaldm_t *aaldm) { native_read_aaldm_reg_value(&aaldm->lo, &aaldm->hi); } -static __always_inline void native_write_aaldm_reg(e2k_aaldm_t *aaldm) +static __always_inline void native_write_aaldm_reg(e2k_aaldm_t aaldm) { - native_write_aaldm_reg_value(aaldm->lo, aaldm->hi); + native_write_aaldm_reg_value(aaldm.lo, aaldm.hi); } -static inline void native_read_aaldv_reg_value(u32 *lo_value, u32 *hi_value) +static __always_inline void native_read_aaldv_reg_value(u32 *lo_value, + u32 *hi_value) { u32 value1, value2; @@ -1195,17 +1196,17 @@ static inline void native_read_aaldv_reg_value(u32 *lo_value, u32 *hi_value) *hi_value = value2; } static __always_inline void native_write_aaldv_reg_value(u32 lo_value, - u32 hi_value) + u32 hi_value) { NATIVE_SET_AAU_AALDV(lo_value, hi_value); } -static inline void native_read_aaldv_reg(e2k_aaldv_t *aaldv) +static __always_inline void native_read_aaldv_reg(e2k_aaldv_t *aaldv) { native_read_aaldv_reg_value(&aaldv->lo, &aaldv->hi); } -static __always_inline void native_write_aaldv_reg(e2k_aaldv_t *aaldv) +static __always_inline void native_write_aaldv_reg(e2k_aaldv_t aaldv) { - native_write_aaldv_reg_value(aaldv->lo, aaldv->hi); + native_write_aaldv_reg_value(aaldv.lo, aaldv.hi); } static inline void native_read_aad_reg(int AAD_no, e2k_aadj_t *mem_p) @@ -1449,7 +1450,7 @@ static __always_inline void native_read_aads_4_reg(int AADs_no, e2k_aadj_t *mem_ } static __always_inline void native_write_aads_4_reg(int AADs_no, - e2k_aadj_t *mem_p) + e2k_aadj_t *mem_p) { switch (AADs_no) { case 0: diff --git a/arch/e2k/include/asm/native_mmu_regs_access.h b/arch/e2k/include/asm/native_mmu_regs_access.h index c3dbdbd..dc99208 100644 --- a/arch/e2k/include/asm/native_mmu_regs_access.h +++ b/arch/e2k/include/asm/native_mmu_regs_access.h @@ -150,7 +150,7 @@ native_invalidate_CACHE_L12(void) unsigned long flags; DebugMR("Flush : Invalidate all CACHEs (op 0x%lx)\n", - _flush_op_invalidate_cache_L12); + flush_op_invalidate_cache_L12); /* Invalidate operation was removed in E2S */ invalidate_supported = NATIVE_IS_MACHINE_ES2; @@ -158,9 +158,9 @@ native_invalidate_CACHE_L12(void) raw_all_irq_save(flags); E2K_WAIT_MA; if (invalidate_supported) - NATIVE_FLUSH_CACHE_L12(_flush_op_invalidate_cache_L12); + NATIVE_FLUSH_CACHE_L12(flush_op_invalidate_cache_L12); else - NATIVE_FLUSH_CACHE_L12(_flush_op_write_back_cache_L12); + NATIVE_FLUSH_CACHE_L12(flush_op_write_back_cache_L12); E2K_WAIT_FLUSH; raw_all_irq_restore(flags); } @@ -171,10 +171,10 @@ native_write_back_CACHE_L12(void) unsigned long flags; DebugMR("Flush : Write back all CACHEs (op 0x%lx)\n", - _flush_op_write_back_cache_L12); + flush_op_write_back_cache_L12); raw_all_irq_save(flags); E2K_WAIT_MA; - NATIVE_FLUSH_CACHE_L12(_flush_op_write_back_cache_L12); + NATIVE_FLUSH_CACHE_L12(flush_op_write_back_cache_L12); E2K_WAIT_FLUSH; raw_all_irq_restore(flags); } @@ -191,10 +191,10 @@ native_flush_TLB_all(void) { unsigned long flags; - DebugMR("Flush all TLBs (op 0x%lx)\n", _flush_op_tlb_all); + DebugMR("Flush all TLBs (op 0x%lx)\n", flush_op_tlb_all); raw_all_irq_save(flags); E2K_WAIT_ST; - NATIVE_FLUSH_TLB_ALL(_flush_op_tlb_all); + NATIVE_FLUSH_TLB_ALL(flush_op_tlb_all); E2K_WAIT(_fl_c | _ma_c); raw_all_irq_restore(flags); } @@ -209,9 +209,9 @@ native_flush_TLB_all(void) static inline void native_flush_ICACHE_all(void) { - DebugMR("Flush all ICACHE op 0x%lx\n", _flush_op_icache_all); + DebugMR("Flush all ICACHE op 0x%lx\n", flush_op_icache_all); E2K_WAIT_ST; - NATIVE_FLUSH_ICACHE_ALL(_flush_op_icache_all); + NATIVE_FLUSH_ICACHE_ALL(flush_op_icache_all); E2K_WAIT_FLUSH; } diff --git a/arch/e2k/include/asm/page_io.h b/arch/e2k/include/asm/page_io.h index 46dfe7d..75d88f4 100644 --- a/arch/e2k/include/asm/page_io.h +++ b/arch/e2k/include/asm/page_io.h @@ -46,6 +46,8 @@ extern void e2k_remove_swap(struct swap_info_struct *sis); extern void restore_tags_for_data(u64 *, u8 *); extern u32 save_tags_from_data(u64 *, u8 *); extern void get_page_with_tags(u8 *, u8 *, int *); +extern u8 *alloc_page_with_tags(void); +extern void free_page_with_tags(u8 *); extern int check_tags(unsigned type, unsigned long beg, unsigned long end); #endif //_E2K_PAGE_IO_H diff --git a/arch/e2k/include/asm/param.h b/arch/e2k/include/asm/param.h deleted file mode 100644 index 816f4ee..0000000 --- a/arch/e2k/include/asm/param.h +++ /dev/null @@ -1,12 +0,0 @@ -/* $Id: param.h,v 1.4 2008/12/19 12:44:14 atic Exp $ */ -#ifndef _E2K_PARAM_H_ -#define _E2K_PARAM_H_ - -#include - - -# define HZ CONFIG_HZ /* Internal kernel timer frequency */ -# define USER_HZ HZ /* some user interfaces are in */ - /* "ticks" */ -# define CLOCKS_PER_SEC (USER_HZ) -#endif /* _E2K_PARAM_H_ */ diff --git a/arch/e2k/include/asm/paravirt/aau_context.h b/arch/e2k/include/asm/paravirt/aau_context.h index 1cabf8b..585205d 100644 --- a/arch/e2k/include/asm/paravirt/aau_context.h +++ b/arch/e2k/include/asm/paravirt/aau_context.h @@ -148,20 +148,20 @@ } \ }) -#define PV_GET_AAU_CONTEXT_V2(aau_context) \ +#define PV_GET_AAU_CONTEXT_V2(aau_context, aasr) \ ({ \ if (!paravirt_enabled()) { \ - NATIVE_GET_AAU_CONTEXT_V2(aau_context); \ + NATIVE_GET_AAU_CONTEXT_V2(aau_context, aasr); \ } else { \ - kvm_get_aau_context(aau_context); \ + kvm_get_aau_context(aau_context, aasr); \ } \ }) -#define PV_GET_AAU_CONTEXT_V5(aau_context) \ +#define PV_GET_AAU_CONTEXT_V5(aau_context, aasr) \ ({ \ if (!paravirt_enabled()) { \ - NATIVE_GET_AAU_CONTEXT_V5(aau_context); \ + NATIVE_GET_AAU_CONTEXT_V5(aau_context, aasr); \ } else { \ - kvm_get_aau_context(aau_context); \ + kvm_get_aau_context(aau_context, aasr); \ } \ }) diff --git a/arch/e2k/include/asm/paravirt/aau_regs_access.h b/arch/e2k/include/asm/paravirt/aau_regs_access.h index bb135ed..8c43e12 100644 --- a/arch/e2k/include/asm/paravirt/aau_regs_access.h +++ b/arch/e2k/include/asm/paravirt/aau_regs_access.h @@ -370,7 +370,7 @@ pv_read_aaldm_reg(e2k_aaldm_t *aaldm) kvm_read_aaldm_reg(aaldm); } static inline void -pv_write_aaldm_reg(e2k_aaldm_t *aaldm) +pv_write_aaldm_reg(e2k_aaldm_t aaldm) { if (!paravirt_enabled()) native_write_aaldm_reg(aaldm); @@ -402,7 +402,7 @@ pv_read_aaldv_reg(e2k_aaldv_t *aaldv) kvm_read_aaldv_reg(aaldv); } static inline void -pv_write_aaldv_reg(e2k_aaldv_t *aaldv) +pv_write_aaldv_reg(e2k_aaldv_t aaldv) { if (!paravirt_enabled()) native_write_aaldv_reg(aaldv); @@ -491,9 +491,9 @@ read_aaldm_reg(e2k_aaldm_t *aaldm) pv_read_aaldm_reg_value(&aaldm->lo, &aaldm->hi); } static inline void -write_aaldm_reg(e2k_aaldm_t *aaldm) +write_aaldm_reg(e2k_aaldm_t aaldm) { - pv_write_aaldm_reg_value(aaldm->lo, aaldm->hi); + pv_write_aaldm_reg_value(aaldm.lo, aaldm.hi); } static inline void read_aaldv_reg(e2k_aaldv_t *aaldv) @@ -501,9 +501,9 @@ read_aaldv_reg(e2k_aaldv_t *aaldv) pv_read_aaldv_reg_value(&aaldv->lo, &aaldv->hi); } static inline void -write_aaldv_reg(e2k_aaldv_t *aaldv) +write_aaldv_reg(e2k_aaldv_t aaldv) { - pv_write_aaldm_reg_value(aaldv->lo, aaldv->hi); + pv_write_aaldm_reg_value(aaldv.lo, aaldv.hi); } #endif /* CONFIG_PARAVIRT_GUEST */ diff --git a/arch/e2k/include/asm/paravirt/mm_hooks.h b/arch/e2k/include/asm/paravirt/mm_hooks.h index f9cb001..2101b70 100644 --- a/arch/e2k/include/asm/paravirt/mm_hooks.h +++ b/arch/e2k/include/asm/paravirt/mm_hooks.h @@ -4,9 +4,10 @@ #ifdef __KERNEL__ #ifdef CONFIG_PARAVIRT_GUEST -static inline void +static inline int get_mm_notifier_locked(struct mm_struct *mm) { + return 0; } #endif /* CONFIG_PARAVIRT_GUEST */ diff --git a/arch/e2k/include/asm/paravirt/pv_ops.h b/arch/e2k/include/asm/paravirt/pv_ops.h index fc454dd..e7496eb 100644 --- a/arch/e2k/include/asm/paravirt/pv_ops.h +++ b/arch/e2k/include/asm/paravirt/pv_ops.h @@ -409,16 +409,6 @@ typedef struct pv_cpu_ops { void (*csd_unlock)(struct __call_single_data *data); void (*setup_local_pic_virq)(unsigned int cpuid); void (*startup_local_pic_virq)(unsigned int cpuid); - void (*smp_flush_tlb_all)(void); - void (*smp_flush_tlb_mm)(struct mm_struct *mm); - void (*smp_flush_tlb_page)(struct vm_area_struct *vma, - e2k_addr_t addr); - void (*smp_flush_tlb_range)(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); - void (*smp_flush_pmd_tlb_range)(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); - void (*smp_flush_tlb_range_and_pgtables)(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); void (*smp_flush_icache_range)(e2k_addr_t start, e2k_addr_t end); void (*smp_flush_icache_range_array)( void *icache_range_arr); @@ -427,6 +417,13 @@ typedef struct pv_cpu_ops { void (*smp_flush_icache_all)(void); void (*smp_flush_icache_kernel_line)(e2k_addr_t addr); #endif /* CONFIG_SMP */ + void (*flush_tlb_all)(void); + void (*flush_tlb_mm)(struct mm_struct *mm); + void (*flush_tlb_page)(struct vm_area_struct *vma, + e2k_addr_t addr); + void (*flush_tlb_mm_range)(struct mm_struct *mm, + unsigned long start, unsigned long end, + unsigned long stride, u32 levels_mask); int (*host_printk)(const char *fmt, ...); void (*arch_spin_lock_slow)(void *lock); diff --git a/arch/e2k/include/asm/paravirt/tlbflush.h b/arch/e2k/include/asm/paravirt/tlbflush.h index daf9c9d..ff0dbab 100644 --- a/arch/e2k/include/asm/paravirt/tlbflush.h +++ b/arch/e2k/include/asm/paravirt/tlbflush.h @@ -9,77 +9,46 @@ #include #include -#ifdef CONFIG_SMP -static inline void -pv_smp_flush_tlb_all(void) +static inline void pv_flush_tlb_all(void) { - pv_cpu_ops.smp_flush_tlb_all(); + pv_cpu_ops.flush_tlb_all(); +} +static inline void pv_flush_tlb_mm(struct mm_struct *mm) +{ + pv_cpu_ops.flush_tlb_mm(mm); } static inline void -pv_smp_flush_tlb_mm(struct mm_struct *mm) +pv_flush_tlb_page(struct vm_area_struct *vma, e2k_addr_t addr) { - pv_cpu_ops.smp_flush_tlb_mm(mm); + pv_cpu_ops.flush_tlb_page(vma, addr); } -static inline void -pv_smp_flush_tlb_page(struct vm_area_struct *vma, e2k_addr_t addr) +static inline void pv_flush_tlb_mm_range(struct mm_struct *mm, + unsigned long start, unsigned long end, + unsigned long stride, u32 levels_mask) { - pv_cpu_ops.smp_flush_tlb_page(vma, addr); + pv_cpu_ops.flush_tlb_mm_range(mm, start, end, stride, levels_mask); } -static inline void -pv_smp_flush_tlb_range(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end) -{ - pv_cpu_ops.smp_flush_tlb_range(mm, start, end); -} -static inline void -pv_smp_flush_pmd_tlb_range(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end) -{ - pv_cpu_ops.smp_flush_pmd_tlb_range(mm, start, end); -} -static inline void -pv_smp_flush_tlb_range_and_pgtables(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end) -{ - pv_cpu_ops.smp_flush_tlb_range_and_pgtables(mm, start, end); -} -#endif /* CONFIG_SMP */ #ifdef CONFIG_PARAVIRT_GUEST /* it is paravirtualized host and guest kernel */ -#ifdef CONFIG_SMP -static inline void -smp_flush_tlb_all(void) +static inline void flush_tlb_all(void) { - pv_smp_flush_tlb_all(); + pv_flush_tlb_all(); } -static inline void -smp_flush_tlb_mm(struct mm_struct *mm) +static inline void flush_tlb_mm(struct mm_struct *mm) { - pv_smp_flush_tlb_mm(mm); + pv_flush_tlb_mm(mm); } -static inline void -smp_flush_tlb_page(struct vm_area_struct *vma, e2k_addr_t addr) +static inline void flush_tlb_page(struct vm_area_struct *vma, e2k_addr_t addr) { - pv_smp_flush_tlb_page(vma, addr); + pv_flush_tlb_page(vma, addr); } -static inline void -smp_flush_tlb_range(struct mm_struct *mm, e2k_addr_t start, e2k_addr_t end) +static inline void flush_tlb_mm_range(struct mm_struct *mm, + unsigned long start, unsigned long end, + unsigned long stride, u32 levels_mask) { - pv_smp_flush_tlb_range(mm, start, end); + pv_flush_tlb_mm_range(mm, start, end, stride, levels_mask); } -static inline void -smp_flush_pmd_tlb_range(struct mm_struct *mm, e2k_addr_t start, e2k_addr_t end) -{ - pv_smp_flush_pmd_tlb_range(mm, start, end); -} -static inline void -smp_flush_tlb_range_and_pgtables(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end) -{ - pv_smp_flush_tlb_range_and_pgtables(mm, start, end); -} -#endif /* CONFIG_SMP */ #endif /* CONFIG_PARAVIRT_GUEST */ #endif /* _E2K_PARAVIRT_TLBFLUSH_H */ diff --git a/arch/e2k/include/asm/pgalloc.h b/arch/e2k/include/asm/pgalloc.h index 148ebee..2f03a37 100644 --- a/arch/e2k/include/asm/pgalloc.h +++ b/arch/e2k/include/asm/pgalloc.h @@ -250,7 +250,7 @@ pgd_populate_cpu_root_pt(struct mm_struct *mm, pgd_t *pgd) } if (pgd_val(*cpu_pgd) != pgd_val(*pgd)) { *cpu_pgd = *pgd; - __flush_tlb_page(mm, (e2k_addr_t) cpu_pgd); + local_flush_tlb_page(mm, (e2k_addr_t) cpu_pgd); } DebugPT("CPU #%d set kernel root pgd %px to 0x%lx\n", smp_processor_id(), cpu_pgd, pgd_val(*cpu_pgd)); diff --git a/arch/e2k/include/asm/pgtable_def.h b/arch/e2k/include/asm/pgtable_def.h index 1271c88..8269f87 100644 --- a/arch/e2k/include/asm/pgtable_def.h +++ b/arch/e2k/include/asm/pgtable_def.h @@ -272,27 +272,27 @@ mmu_clear_pte_val_flags(pteval_t pte_val, const uni_pteval_t uni_flags, else return clear_pte_val_v2_flags(pte_val, uni_flags); } -static inline pteval_t +static __must_check inline pteval_t fill_pte_val_flags(const uni_pteval_t uni_flags) { return mmu_fill_pte_val_flags(uni_flags, MMU_IS_PT_V6()); } -static inline pteval_t +static __must_check inline pteval_t get_pte_val_flags(pteval_t pte_val, const uni_pteval_t uni_flags) { return mmu_get_pte_val_flags(pte_val, uni_flags, MMU_IS_PT_V6()); } -static inline bool +static __must_check inline bool test_pte_val_flags(pteval_t pte_val, const uni_pteval_t uni_flags) { return mmu_test_pte_val_flags(pte_val, uni_flags, MMU_IS_PT_V6()); } -static inline pteval_t +static __must_check inline pteval_t set_pte_val_flags(pteval_t pte_val, const uni_pteval_t uni_flags) { return mmu_set_pte_val_flags(pte_val, uni_flags, MMU_IS_PT_V6()); } -static inline pteval_t +static __must_check inline pteval_t clear_pte_val_flags(pteval_t pte_val, const uni_pteval_t uni_flags) { return mmu_clear_pte_val_flags(pte_val, uni_flags, MMU_IS_PT_V6()); diff --git a/arch/e2k/include/asm/poll.h b/arch/e2k/include/asm/poll.h deleted file mode 100644 index c98509d..0000000 --- a/arch/e2k/include/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/asm/posix_types.h b/arch/e2k/include/asm/posix_types.h deleted file mode 100644 index 575deb1..0000000 --- a/arch/e2k/include/asm/posix_types.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _E2K_POSIX_TYPES_H_ -#define _E2K_POSIX_TYPES_H_ - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. - */ - -#include - -#endif /* _E2K_POSIX_TYPES_H_ */ diff --git a/arch/e2k/include/asm/preempt.h b/arch/e2k/include/asm/preempt.h new file mode 100644 index 0000000..38f0201 --- /dev/null +++ b/arch/e2k/include/asm/preempt.h @@ -0,0 +1,101 @@ +#pragma once + +#include + +register unsigned long long __cpu_preempt_reg DO_ASM_GET_GREG_MEMONIC( + SMP_CPU_ID_GREG); + +#define PREEMPT_COUNTER_SHIFT 33ull + +#define PREEMPT_NEED_RESCHED 0x100000000ull + +#define PREEMPT_ENABLED (0) + +static __always_inline int preempt_count(void) +{ + return __cpu_preempt_reg >> PREEMPT_COUNTER_SHIFT; +} + +/* + * must be macros to avoid header recursion hell + */ +#define init_task_preempt_count(p) do { } while (0) + +#define init_idle_preempt_count(p, cpu) do { \ + __cpu_preempt_reg = (u64) (u32) __cpu_preempt_reg; \ +} while (0) + +static __always_inline void set_preempt_need_resched(void) +{ + __cpu_preempt_reg |= PREEMPT_NEED_RESCHED; +} + +static __always_inline void clear_preempt_need_resched(void) +{ + __cpu_preempt_reg &= ~PREEMPT_NEED_RESCHED; +} + +static __always_inline bool test_preempt_need_resched(void) +{ + return __cpu_preempt_reg & PREEMPT_NEED_RESCHED; +} + +/* + * The various preempt_count set/add/sub methods + * + * Careful here: an interrupt can arrive at any moment and set or clear + * the PREEMPT_NEED_RESCHED flag. We want to change preempt_count + * in a safe way so that the flag set in interrupt is not lost. + */ + +static __always_inline void preempt_count_set(int pc) +{ + E2K_INSFD_ATOMIC(pc, + 31 /*shift*/ | (33 /*size*/ << 6) | (1 /*me1hi*/ << 13), + __cpu_preempt_reg); +} + + +static __always_inline void __preempt_count_add(int val) +{ + E2K_ADDD_ATOMIC(__cpu_preempt_reg, (u64) (u32) val << PREEMPT_COUNTER_SHIFT); +} + +static __always_inline void __preempt_count_sub(int val) +{ + E2K_SUBD_ATOMIC(__cpu_preempt_reg, (u64) (u32) val << PREEMPT_COUNTER_SHIFT); +} + +static __always_inline bool __preempt_count_dec_and_test(void) +{ + u64 old; + + E2K_SUBD_ATOMIC__SHRD32(__cpu_preempt_reg, 1ull << PREEMPT_COUNTER_SHIFT, old); + + return unlikely(old == 1); +} + +static __always_inline void init_preempt_count_resched(int pc, int resched) +{ + __cpu_preempt_reg = (u64) (u32) __cpu_preempt_reg; + preempt_count_set(pc); + if (resched) + set_preempt_need_resched(); +} + +/* + * Returns true when we need to resched and can (barring IRQ state). + */ +static __always_inline bool should_resched(int preempt_offset) +{ + return unlikely((__cpu_preempt_reg >> 32ull) == + (((u64) (u32) preempt_offset << 1) | 1)); +} + +#ifdef CONFIG_PREEMPTION +extern asmlinkage void preempt_schedule(void); +#define __preempt_schedule() preempt_schedule() +extern asmlinkage void preempt_schedule_notrace(void); +#define __preempt_schedule_notrace() preempt_schedule_notrace() +#endif /* CONFIG_PREEMPTION */ + diff --git a/arch/e2k/include/asm/processor.h b/arch/e2k/include/asm/processor.h index 71cdd2a..05dcdb8 100644 --- a/arch/e2k/include/asm/processor.h +++ b/arch/e2k/include/asm/processor.h @@ -68,8 +68,7 @@ extern cpuinfo_e2k_t cpu_data[NR_CPUS]; #define INVALID_IO_BITMAP_OFFSET 0x8000 typedef struct thread_struct { -#ifndef CONFIG_CPU_HAS_FILL_INSTRUCTION - /* Used as a temporary area */ + /* Used as a temporary area for !CPU_FEAT_FILL_INSTRUCTION case */ struct { e2k_cr0_hi_t cr0_hi; e2k_cr1_lo_t cr1_lo; @@ -84,7 +83,7 @@ typedef struct thread_struct { bool from_paravirt_guest; # endif } fill; -#endif + u32 context; /* context of running process */ struct sw_regs sw_regs; /* switch regs */ diff --git a/arch/e2k/include/asm/ptrace.h b/arch/e2k/include/asm/ptrace.h index 38103ec..0db2519 100644 --- a/arch/e2k/include/asm/ptrace.h +++ b/arch/e2k/include/asm/ptrace.h @@ -149,6 +149,7 @@ typedef struct pt_regs { int sys_num; /* to restart sys_call */ int kernel_entry; union pt_regs_flags flags; + e2k_aasr_t aasr; e2k_ctpr_t ctpr1; /* CTPRj for control transfer */ e2k_ctpr_t ctpr2; e2k_ctpr_t ctpr3; @@ -231,23 +232,6 @@ pt_regs_to_trap_regs(struct pt_regs *regs) return PTR_ALIGN((void *) regs + sizeof(*regs), 8); } -#ifdef CONFIG_USE_AAU -static inline e2k_aau_t * -pt_regs_to_aau_regs(struct pt_regs *regs) -{ - struct trap_pt_regs *trap; - - trap = pt_regs_to_trap_regs(regs); - - return PTR_ALIGN((void *) trap + sizeof(*trap), 8); -} -#else /* ! CONFIG_USE_AAU */ -static inline e2k_aau_t * -pt_regs_to_aau_regs(struct pt_regs *regs) -{ - return NULL; -} -#endif static inline bool is_sys_call_pt_regs(struct pt_regs *regs) { diff --git a/arch/e2k/include/asm/regs_state.h b/arch/e2k/include/asm/regs_state.h index fdd289a..42bce7f 100644 --- a/arch/e2k/include/asm/regs_state.h +++ b/arch/e2k/include/asm/regs_state.h @@ -1201,6 +1201,7 @@ NATIVE_SWITCH_TO_KERNEL_STACK(e2k_addr_t ps_base, e2k_size_t ps_size, e2k_addr_t pcs_base, e2k_size_t pcs_size, e2k_addr_t ds_base, e2k_size_t ds_size) { + pcsp_struct_t pcsp = {{ 0 }}; e2k_rwap_lo_struct_t reg_lo; e2k_rwap_hi_struct_t reg_hi; e2k_rwap_lo_struct_t stack_reg_lo; @@ -1219,13 +1220,10 @@ NATIVE_SWITCH_TO_KERNEL_STACK(e2k_addr_t ps_base, e2k_size_t ps_size, reg_hi.PSP_hi_size = ps_size; reg_hi.PSP_hi_ind = 0; NATIVE_NV_WRITE_PSP_REG(reg_hi, reg_lo); - reg_lo.PCSP_lo_half = 0; - reg_lo.PCSP_lo_base = pcs_base; - reg_lo._PCSP_lo_rw = E2K_PCSR_RW_PROTECTIONS; - reg_hi.PCSP_hi_half = 0; - reg_hi.PCSP_hi_size = pcs_size; - reg_hi.PCSP_hi_ind = 0; - NATIVE_NV_WRITE_PCSP_REG(reg_hi, reg_lo); + pcsp.base = pcs_base; + pcsp.size = pcs_size; + pcsp.rw = E2K_PCSR_RW_PROTECTIONS; + NATIVE_NV_WRITE_PCSP_REG(pcsp.hi, pcsp.lo); /* diff --git a/arch/e2k/include/asm/sembuf.h b/arch/e2k/include/asm/sembuf.h deleted file mode 100644 index 8a95f09..0000000 --- a/arch/e2k/include/asm/sembuf.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _E2K_SEMBUF_H_ -#define _E2K_SEMBUF_H_ - -/* - * The semid64_ds structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - __kernel_time_t sem_ctime; /* last change time */ - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _E2K_SEMBUF_H_ */ diff --git a/arch/e2k/include/asm/serial.h b/arch/e2k/include/asm/serial.h index 2482000..d08ffe7 100644 --- a/arch/e2k/include/asm/serial.h +++ b/arch/e2k/include/asm/serial.h @@ -1,455 +1,2 @@ -/* - * include/asm-i386/serial.h - */ - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ - -#define BASE_BAUD ( 1843200 / 16 ) - -/* Standard COM flags (except for COM4, because of the 8514 problem) */ -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF -#endif - -#ifdef CONFIG_SERIAL_MANY_PORTS -#define FOURPORT_FLAGS ASYNC_FOURPORT -#define ACCENT_FLAGS 0 -#define BOCA_FLAGS 0 -#define HUB6_FLAGS 0 -#define RS_TABLE_SIZE 64 -#else -#define RS_TABLE_SIZE -#endif - -#define NS16550_SERIAL_PORT_0 0x3f8 -#define NS16550_SERIAL_PORT_1 0x2f8 -#define NS16550_SERIAL_PORT_2 0x3e8 -#define NS16550_SERIAL_PORT_3 0x2e8 - -#define SERIAL_PORT_DFNS \ - /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ - { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ - { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ - -#define AM85C30_RES_Tx_P 0x28 -#define AM85C30_EXT_INT_ENAB 0x01 -#define AM85C30_TxINT_ENAB 0x02 -#define AM85C30_RxINT_MASK 0x18 - - -/* AM85C30 WRITE Registers */ - -#define AM85C30_WR0 0x00 -#define AM85C30_WR1 0x01 -#define AM85C30_WR2 0x02 -#define AM85C30_WR3 0x03 -#define AM85C30_WR4 0x04 -#define AM85C30_WR5 0x05 -#define AM85C30_WR6 0x06 -#define AM85C30_WR7 0x07 -#define AM85C30_WR8 0x08 -#define AM85C30_WR9 0x09 -#define AM85C30_WR10 0x0a -#define AM85C30_WR11 0x0b -#define AM85C30_WR12 0x0c -#define AM85C30_WR13 0x0d -#define AM85C30_WR14 0x0e -#define AM85C30_WR15 0x0f - -/* READ (Status) Registers */ - -#define AM85C30_RR0 0x00 -#define AM85C30_RR1 0x01 -#define AM85C30_RR2 0x02 -#define AM85C30_RR3 0x03 -#define AM85C30_RR8 0x08 -#define AM85C30_RR10 0x0a -#define AM85C30_RR12 0x0c -#define AM85C30_RR13 0x0d - -#define AM85C30_D0 (0x01 << 0) -#define AM85C30_D1 (0x01 << 1) -#define AM85C30_D2 (0x01 << 2) -#define AM85C30_D3 (0x01 << 3) -#define AM85C30_D4 (0x01 << 4) -#define AM85C30_D5 (0x01 << 5) -#define AM85C30_D6 (0x01 << 6) -#define AM85C30_D7 (0x01 << 7) - -/* WR0 */ -/* D2,D1,D0 -* Register Access Pointer -* -* 000 - N0, [N8]* -* 001 - N1, [N9]* -* 010 - N2, [N10]* -* 011 - N3, [N11]* -* 100 - N4, [N12]* -* 101 - N5, [N13]* -* 110 - N6, [N14]* -* 111 - N7, [N15]* -* -* if Point High Register Group = 1 -* -* D5,D4,D3 -* -* SCC Command -* -* 000 - Null Code -* 001 - Point High Register Group -* 010 - Reset Ext/Status Interrupts -* 011 - Send Abort -* 100 - Enable Int. on Next Rx Character -* 101 - Reset Tx Int. Pending -* 110 - Error Reset -* 111 - Reset Highest IUS -* -* D7,D6 -* SCC Command -* -* 00 - Null Code -* 01 - Reset Rx CRC Checker -* 10 - Reset Tx CRC Generator -* 11 - Reset Tx Underrun/EOM Latch -*/ - -/* WR1 */ -/* D0 -* Ext. Int. Enable -* D1 -* Tx Int. Enable -* D2 -* Parity is Special Condition -* D4,D3 -* Rx Int Mode -* -* 00 - Rx Int Disable -* 01 - Rx Int on First Char. or Special Condition -* 10 - Int on All Rx Char. or Special Condition -* 11 - Rx Int. on Special Condition Only -* D5 -* Wait/DMA Request on Receive/Transmit -* D6 -* Wait/DMA Request Function -* D7 -* Wait/DMA Request Enable -*/ - -/* WR2 */ -/* D7 - D0 -* Interrupt Vector -*/ - -/* WR3 */ -/* D0 -* Rx Enable -* D1 -* Sync Character Load Inhibit -* D2 -* Address Search Mode (SDLC) -* D3 -* Rx CRC Enable -* D4 -* Enter Hunt Mode -* D5 -* Auto Enable -* D7,D6 -* -* 00 - Rx 5 Bits / Character -* 01 - Rx 6 Bits / Character -* 10 - Rx 7 Bits / Character -* 11 - Rx 8 Bits / Character -*/ - -/* WR4 */ -/* D0 -* ParityEnable -* D1 -* Parity Even(0) / Odd(1) -* D3,D2 -* -* 00 - Sync Modes Enable -* 01 - 1 Stop Bit / Character -* 10 - 1.5 Stop Bits / Character -* 11 - 2 Stop Bits / Character -* D5,D4 -* -* 00 - 8-Bit Sync Character -* 01 - 16-Bit Sync Character -* 10 - SDLC Mode -* 11 - External Sync Mode -* D7,D6 -* -* 00 - X1 Clock Mode -* 01 - X16 Clock Mode -* 10 - X32 Clock Mode -* 11 - X64 Clock Mode -*/ - -/* WR5 */ -/* D0 -* Tx CRC Enable -* D1 -* RTS -* D2 -* SDLC-/CRC-16 -* D3 -* Tx Enable -* D4 -* Send Break -* D6,D5 -* -* 00 - Tx 5 Bits / Character -* 01 - Tx 6 Bits / Character -* 10 - Tx 7 Bits / Character -* 11 - Tx 8 Bits / Character -* D7 -* DTR -*/ - -/* WR6 */ -/* D5-D0 -* xN constant -* D7,D6 -* Reserved (not used in asynchronous mode) -*/ - -/* WR7 */ -/* D6-D0 -* Reserved (not used in asynchronous mode) -* D7 -* xN Mode Enable -*/ - -/* WR8 */ -/* D7-D0 -* Transmit Buffer -*/ - -/* WR9 */ -/* D0 -* Vector Includes Status -* D1 -* No Vector -* D2 -* Disable Lower Chain -* D3 -* Master Interrupt Enable -* D4 -* Status High/Low_ -* D5 -* Interrupt Masking Without INTACK_ -* D7-D6 -* -* 00 - No Reset -* 01 - Channel B Reset -* 10 - Channel A Reset -* 11 - Force Hardware Reset -*/ - -/* WR10 */ -/* D0 -* 6 bit / 8 bit SYNC -* D1 -* Loop Mode -* D2 -* Abort/Flag on Underrun -* D3 -* Mark/Flag Idle -* D4 -* Go Active on Poll -* D6-D5 -* -* 00 - NRZ -* 01 - NRZI -* 10 - FM1 (Transition = 1) -* 11 - FM0 (Transition = 0) -* D7 -* CRC Preset '1' or '0' -*/ - -/* WR11 */ -/* D1-D0 -* -* 00 - TRxC Out = XTAL output -* 01 - TRxC Out = Transmit Clock -* 10 - TRxC Out = BRG output -* 11 - TRxC Out = DPLL output -* D2 -* TRxC O/I -* D4-D3 -* -* 00 - Transmit Clock = RTxC pin -* 01 - Transmit Clock = TRxC pin -* 10 - Transmit Clock = BRG output -* 11 - Transmit Clock = DPLL output -* D6-D5 -* -* 00 - Receive Clock = RTxC pin -* 01 - Receive Clock = TRxC pin -* 10 - Receive Clock = BRG output -* 11 - Receive Clock = DPLL output -* D7 -* RTxC XTAL / NO XTAL -*/ - -/* WR12 */ -/* D7-D0 -* Lower Byte of Time Constant -*/ - -/* WR13 */ -/* D7-D0 -* Upper Byte of Time Constant -*/ - -/* WR14 */ -/* D0 -* BRG Enable -* D1 -* BRG Source -* D2 -* DTR / REQUESTt Function -* D3 -* Auto Echo -* D4 -* Local Loopback -* D7-D5 -* -* 000 - Null Command -* 001 - Enter Search Mode -* 010 - Reset Missing Clock -* 011 - Disable DPLL -* 100 - Set Source = BR Generator -* 101 - Set Source = RTxC_ -* 110 - Set FM Mode -* 111 - Set NRZI Mode -*/ - -/* WR15 */ -/* D0 -* SDLC/HDLC Enhancement Enable -* D1 -* Zero Count IE (Interrupt Enable) -* D2 -* 10 * 19-bit Frame Status FIFO Enable -* D3 -* DCD IE -* D4 -* Sync/Hunt IE -* D5 -* CTS IE -* D6 -* Tx Underrun / EOM IE -* D7 -* Break/Abort IE -*/ - - -/* RR0 */ -/* D0 -* Rx Character Availiable -* D1 -* Zero Count -* D2 -* Tx Buffer Empty -* D3 -* DCD -* D4 -* Sync/Hunt -* D5 -* CTS -* D6 -* Tx Underrun / EOM -* D7 -* Break/Abort -*/ - -/* RR1 */ -/* D0 -* All Sent -* D1 -* Residue Code 2 -* D2 -* Residue Code 1 -* D3 -* Residue Code 0 -* D4 -* Parity Error -* D5 -* Rx Overrun Error -* D6 -* CRC / Framing Error -* D7 -* End of Frame (SDLC) -*/ - -/* RR2 */ -/* D7-D0 -* Interrupt Vector -* -* Channel A RR2 = WR2 -* Channel B RR2 = Interrupt Vector Modified* -* -* * -* D3 D2 D1 Status High/Low = 0 -* D4 D5 D6 Status High/Low = 1 -* -* 0 0 0 Ch B Transmit Buffer Empty -* 0 0 1 Ch B External/Status Change -* 0 1 0 Ch B Receive Char. Availiable -* 0 1 1 Ch B Special Receive Condition -* 1 0 0 Ch A Transmit Buffer Empty -* 1 0 1 Ch A External/Status Change -* 1 1 0 Ch A Receive Char. Availiable -* 1 1 1 Ch A Special Receive Condition -*/ - -/* RR3 */ -/* D0 -* Channel B Ext/Status IP (Interrupt Pending) -* D1 -* Channel B Tx IP -* D2 -* Channel B Rx IP -* D3 -* Channel A Ext/Status IP -* D4 -* Channel A Tx IP -* D5 -* Channel A Rx IP -* D7-D6 -* Always 00 -*/ - -/* RR8 */ -/* D7-D0 -* Receive Buffer -*/ - -/* RR10 */ -/* D7-D0 -* Reserved (not used in asynchronous mode) -*/ - -/* RR12 */ -/* D7-D0 -* Lower Byte of Time Constant -*/ - -/* RR13 */ -/* D7-D0 -* Upper Byte of Time Constant -*/ +#pragma once +#include diff --git a/arch/e2k/include/asm/smp.h b/arch/e2k/include/asm/smp.h index 5985733..a70d82c 100644 --- a/arch/e2k/include/asm/smp.h +++ b/arch/e2k/include/asm/smp.h @@ -106,9 +106,15 @@ extern void smp_cpus_recovery_done(unsigned int max_cpus); * This function is needed by all SMP systems. It must _always_ be valid * from the initial startup. */ -register unsigned long long __cpu_reg DO_ASM_GET_GREG_MEMONIC( +register unsigned long long __cpu_preempt_reg DO_ASM_GET_GREG_MEMONIC( SMP_CPU_ID_GREG); -#define raw_smp_processor_id() ((unsigned int) __cpu_reg) +#define raw_smp_processor_id() ((unsigned int) __cpu_preempt_reg) + +#define set_smp_processor_id(cpu) \ +do { \ + __cpu_preempt_reg = (__cpu_preempt_reg & 0xffffffff00000000ull) | \ + ((u64) (u32) (cpu)); \ +} while (0) #endif /* !ASSEMBLY */ diff --git a/arch/e2k/include/asm/socket.h b/arch/e2k/include/asm/socket.h deleted file mode 100644 index 6b71384..0000000 --- a/arch/e2k/include/asm/socket.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/asm/sockios.h b/arch/e2k/include/asm/sockios.h deleted file mode 100644 index def6d47..0000000 --- a/arch/e2k/include/asm/sockios.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/asm/statfs.h b/arch/e2k/include/asm/statfs.h deleted file mode 100644 index 8f2a792..0000000 --- a/arch/e2k/include/asm/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _E2K_STATFS_H_ -#define _E2K_STATFS_H_ - -#include - -#endif /* _E2K_STATFS_H_ */ diff --git a/arch/e2k/include/asm/string.h b/arch/e2k/include/asm/string.h index 411c408..196adf6 100644 --- a/arch/e2k/include/asm/string.h +++ b/arch/e2k/include/asm/string.h @@ -3,7 +3,6 @@ #include -#include #include #define __HAVE_ARCH_STRNLEN @@ -20,43 +19,59 @@ extern int __memcmp(const void *cs, const void *ct, size_t count) __pure; #define memcmp(dst, src, n) _memcmp((dst), (src), (n)) static inline int _memcmp(const void *s1, const void *s2, size_t n) { - if (__builtin_constant_p(n)) { - u64 v1, v2; - if (n == 16) { - v1 = *(u64 *) s1; - v2 = *(u64 *) s2; +#ifdef E2K_P2V + bool manual_inline = !IS_ENABLED(CONFIG_CPU_ES2); +#else + bool manual_inline = !cpu_has(CPU_HWBUG_UNALIGNED_LOADS); +#endif + if (__builtin_constant_p(n) && n < 0x20 && manual_inline) { + /* Inline small memcmp's */ + if (n & 0x10) { + u64 v1 = *(u64 *) s1; + u64 v2 = *(u64 *) s2; u64 v21 = *(u64 *) (s1 + 8); u64 v22 = *(u64 *) (s2 + 8); if (v1 != v2) return (__swab64(v1) > __swab64(v2)) ? 1 : -1; - if (v21 == v22) - return 0; - return (__swab64(v21) > __swab64(v22)) ? 1 : -1; + if (v21 != v22) + return (__swab64(v21) > __swab64(v22)) ? 1 : -1; + + s1 += 0x10; + s2 += 0x10; } - if (n == 8) { - v1 = *(u64 *) s1; - v2 = *(u64 *) s2; - if (v1 == v2) - return 0; - return (__swab64(v1) > __swab64(v2)) ? 1 : -1; + if (n & 0x8) { + u64 v1 = *(u64 *) s1; + u64 v2 = *(u64 *) s2; + if (v1 != v2) + return (__swab64(v1) > __swab64(v2)) ? 1 : -1; + + s1 += 0x8; + s2 += 0x8; } - if (n == 4) { - v1 = *(u32 *) s1; - v2 = *(u32 *) s2; - if (v1 == v2) - return 0; - return (__swab32(v1) > __swab32(v2)) ? 1 : -1; + if (n & 0x4) { + u64 v1 = *(u32 *) s1; + u64 v2 = *(u32 *) s2; + if (v1 != v2) + return (__swab32(v1) > __swab32(v2)) ? 1 : -1; + + s1 += 0x4; + s2 += 0x4; } - if (n == 2) { - v1 = *(u16 *) s1; - v2 = *(u16 *) s2; - return (u32) __swab16(v1) - (u32) __swab16(v2); + if (n & 0x2) { + u64 v1 = *(u16 *) s1; + u64 v2 = *(u16 *) s2; + if (!(n & 0x1) || v1 != v2) + return (u32) __swab16(v1) - (u32) __swab16(v2); + + s1 += 0x1; + s2 += 0x1; } - if (n == 1) { - v1 = *(u8 *) s1; - v2 = *(u8 *) s2; + if (n & 0x1) { + u64 v1 = *(u8 *) s1; + u64 v2 = *(u8 *) s2; return v1 - v2; } + return 0; } E2K_PREFETCH_L1_SPEC(s1); @@ -160,9 +175,17 @@ static inline void *_memcpy(void *__restrict dst, const void *__restrict src, size_t n, const unsigned long dst_align) { +#if defined E2K_P2V || defined CONFIG_BOOT_E2K + bool manual_inline = !IS_ENABLED(CONFIG_CPU_ES2); +#else + bool manual_inline = !cpu_has(CPU_HWBUG_UNALIGNED_LOADS) && + (dst_align >= 8 || cpu_has(CPU_FEAT_ISET_V6)); +#endif + /* - * As measurements show, an unaligned dst causes a 20x slowdown, - * but unaligned src causes only a 2x slowdown. + * As measurements show, an unaligned dst causes a 4x slowdown, + * but unaligned src causes only a 2x slowdown (also note that + * since v6 unaligned accesses do not cause any slowdown at all). * * We can manually assure dst's alignment, but what about src? * @@ -180,8 +203,8 @@ static inline void *_memcpy(void *__restrict dst, * alignment and do the copy with 8-bytes words. */ - if (__builtin_constant_p(n) && dst_align >= 8 && n < 136) { - /* Inline small aligned memcpy's */ + if (__builtin_constant_p(n) && n < 136 && manual_inline) { + /* Inline small memcpy's */ const u64 *__restrict l_src = src; u64 *__restrict l_dst = dst; @@ -433,13 +456,7 @@ static inline void native_tagged_memcpy_8(void *__restrict dst, * * All parameters must be 8-bytes aligned. */ -#ifdef CONFIG_BOOT_E2K -#define tagged_memcpy_8(dst, src, n) \ -({ \ - native_tagged_memcpy_8(dst, src, n, \ - __alignof(*(dst)), __alignof(*(src))); \ -}) -#elif defined(CONFIG_PARAVIRT_GUEST) +#if defined(CONFIG_PARAVIRT_GUEST) #include #elif defined(CONFIG_KVM_GUEST_KERNEL) #include @@ -454,23 +471,7 @@ static inline void native_tagged_memcpy_8(void *__restrict dst, extern void boot_fast_memcpy(void *, const void *, size_t); extern notrace void boot_fast_memset(void *s_va, long c, size_t count); -#ifdef CONFIG_BOOT_E2K -/* own small bios (boot loader) for kernel */ -static inline unsigned long -fast_tagged_memory_copy(void *dst, const void *src, size_t len, - unsigned long strd_opcode, unsigned long ldrd_opcode, - int prefetch) -{ - return native_fast_tagged_memory_copy(dst, src, len, - strd_opcode, ldrd_opcode, prefetch); -} -static inline unsigned long -fast_tagged_memory_set(void *addr, u64 val, u64 tag, - size_t len, u64 strd_opcode) -{ - return native_fast_tagged_memory_set(addr, val, tag, len, strd_opcode); -} -#elif defined(CONFIG_PARAVIRT_GUEST) +#if defined(CONFIG_PARAVIRT_GUEST) /* it is paravirtualized host/guest kernel */ #include #elif defined(CONFIG_KVM_GUEST_KERNEL) diff --git a/arch/e2k/include/asm/system.h b/arch/e2k/include/asm/system.h index 3fc61f5..f6a574b 100644 --- a/arch/e2k/include/asm/system.h +++ b/arch/e2k/include/asm/system.h @@ -47,13 +47,6 @@ static inline bool native_sge_is_set(void) } #ifdef CONFIG_E2K_PROFILING - -#define boot_smp_processor_id_() \ - (((e2k_addr_t)current_thread_info() >= TASK_SIZE) ? \ - smp_processor_id() \ - : \ - ((long)READ_CURRENT_REG_VALUE())) - typedef struct { // FIRST ELEMENT long max_disable_interrupt; // max #ticks of disable_interrupt @@ -87,7 +80,7 @@ extern disable_interrupt_t disable_interrupt[NR_CPUS]; #define add_info_interrupt(n, ticks) \ ({ long t; int cpu; \ t = NATIVE_READ_CLKR_REG_VALUE() - ticks; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ disable_interrupt[cpu].interrupts[n]++; \ disable_interrupt[cpu].interrupts_time[n] += t; \ if (t > disable_interrupt[cpu].max_interrupts_time[n]) { \ @@ -148,7 +141,7 @@ extern system_info_t system_info[NR_CPUS]; extern int enable_collect_interrupt_ticks; #define collect_disable_interrupt_ticks() \ ({ int cpu; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ if (system_info[cpu].max_disabled_interrupt.begin_time >0){ \ store_max_time_in_system_info( \ system_info[cpu].max_disabled_interrupt.begin_time, \ @@ -161,13 +154,13 @@ extern int enable_collect_interrupt_ticks; store_begin_ip_in_system_info(max_disabled_interrupt) #define store_do_irq_ticks() \ -({ int cpu = boot_smp_processor_id_(); \ +({ int cpu = boot_smp_processor_id(); \ disable_interrupt[cpu].clk_of_do_irq = NATIVE_READ_CLKR_REG_VALUE(); \ }) #define define_time_of_do_irq(N) \ ({ long t; int cpu; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ t = NATIVE_READ_CLKR_REG_VALUE() - \ disable_interrupt[cpu].clk_of_do_irq; \ disable_interrupt[cpu].do_irq_time[N] += t; \ @@ -202,7 +195,7 @@ extern int enable_collect_interrupt_ticks; ({ long t; int cpu; \ register e2k_cr0_hi_t cr0_hi; \ if (enable_collect_interrupt_ticks) { \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ t = NATIVE_READ_CLKR_REG_VALUE(); \ AS_WORD(cr0_hi) = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \ system_info[cpu].FIELD.begin_time = tick; \ @@ -215,7 +208,7 @@ extern int enable_collect_interrupt_ticks; ({ \ int cpu; \ register e2k_cr0_hi_t cr0_hi; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ disable_interrupt[cpu].clk = NATIVE_READ_CLKR_REG_VALUE(); \ cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \ system_info[cpu].FIELD.beg_ip = NATIVE_READ_IP_REG_VALUE(); \ @@ -239,7 +232,7 @@ extern int enable_collect_interrupt_ticks; ({ \ int cpu; \ register e2k_cr0_hi_t cr0_hi; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ cr0_hi = NATIVE_NV_READ_CR0_HI_REG_VALUE(); \ system_info[cpu].FIELD.beg_ip = mutex->ip; \ system_info[cpu].FIELD.beg_parent_ip = mutex->caller; \ @@ -252,7 +245,7 @@ extern int enable_collect_interrupt_ticks; ({ \ long t; int cpu; \ register e2k_cr0_hi_t cr0_hi; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ if (enable_collect_interrupt_ticks) { \ t = NATIVE_READ_CLKR_REG_VALUE()-system_info[cpu]. \ FIELD.begin_time; \ @@ -281,7 +274,7 @@ extern long TIME; ({ \ long t; int cpu; \ register e2k_cr0_hi_t cr0_hi; \ - cpu = boot_smp_processor_id_(); \ + cpu = boot_smp_processor_id(); \ t = NATIVE_READ_CLKR_REG_VALUE()-tick; \ if (enable_collect_interrupt_ticks) { \ system_info[cpu].FIELD.number++; \ diff --git a/arch/e2k/include/asm/termbits.h b/arch/e2k/include/asm/termbits.h deleted file mode 100644 index 8484205..0000000 --- a/arch/e2k/include/asm/termbits.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _E2K_TERMBITS_H_ -#define _E2K_TERMBITS_H_ - -#include - -#endif /* _E2K_TERMBITS_H_ */ diff --git a/arch/e2k/include/asm/termios.h b/arch/e2k/include/asm/termios.h deleted file mode 100644 index 8b3d2b0..0000000 --- a/arch/e2k/include/asm/termios.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _E2K_TERMIOS_H_ -#define _E2K_TERMIOS_H_ - -#include - -#endif /* _E2K_TERMIOS_H_ */ diff --git a/arch/e2k/include/asm/thread_info.h b/arch/e2k/include/asm/thread_info.h index 7ba4cd5..5c1b73e 100644 --- a/arch/e2k/include/asm/thread_info.h +++ b/arch/e2k/include/asm/thread_info.h @@ -53,8 +53,6 @@ typedef struct thread_info { unsigned long status; /* thread synchronous flags */ long long irq_enter_clk; /* CPU clock when irq enter */ /* occured */ - int preempt_count; /* 0 => preemptable, <0 */ - /* => BUG */ mm_segment_t addr_limit; /* thread address space */ struct pt_regs *pt_regs; /* head of pt_regs */ /* structure queue: */ @@ -396,12 +394,9 @@ void clear_g_list(struct thread_info *thread_info) { } /* * Macros/functions for gaining access to the thread information structure. - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ - .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .k_usd_lo = (e2k_usd_lo_t) { \ .word = (unsigned long) init_stack + \ @@ -429,6 +424,7 @@ extern void clear_thread_info(struct task_struct *task); extern unsigned long *alloc_thread_stack_node(struct task_struct *, int); extern void free_thread_stack(struct task_struct *tsk); +extern int free_vm_stack_cache(unsigned int cpu); #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/e2k/include/asm/tlb-context.h b/arch/e2k/include/asm/tlb-context.h deleted file mode 100644 index a5906ba..0000000 --- a/arch/e2k/include/asm/tlb-context.h +++ /dev/null @@ -1,791 +0,0 @@ -/* - * TLB context support & flushing - */ - -#ifndef _E2K_TLB_CONTEXT_H_ -#define _E2K_TLB_CONTEXT_H_ - -#include -#include -#include - -#include -#include -#include - -#undef DEBUG_PT_MODE -#undef DebugPT -#define DEBUG_PT_MODE 0 /* Data Caches */ -#define DebugPT(...) DebugPrint(DEBUG_PT_MODE, ##__VA_ARGS__) - -/* - * TLB flushing: - */ - -/* - * Flush all processes TLBs of the processor - */ -static inline void -mmu_pid_flush_tlb_all(bool trace_enabled) -{ - flush_TLB_all(); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_all(raw_smp_processor_id()); - } -} - -/* - * Flush a specified user mapping on the processor - */ -static inline void -mmu_pid_flush_tlb_mm(mm_context_t *context, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int cpu; - unsigned long old_pid, pid; - - count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); - - cpu = raw_smp_processor_id(); - old_pid = context->cpumsk[cpu]; - - if (likely(is_active)) { - unsigned long pid, flags; - - /* Should update right now */ - DebugPT("mm context will be reloaded\n"); - raw_all_irq_save(flags); - cpu = smp_processor_id(); - pid = get_new_mmu_pid(context, cpu); - reload_context_mask(pid); - raw_all_irq_restore(flags); - - DebugPT("CPU #%d new mm context is 0x%lx\n", - cpu, context->cpumsk[cpu]); - } else { -#ifdef CONFIG_SMP - /* Remove this cpu from mm_cpumask. This might be - * needed, for example, after sys_io_setup() if the - * kernel thread which was using this mm received - * flush ipi (unuse_mm() does not clear mm_cpumask). - * And maybe there are other such places where - * a kernel thread uses user mm. */ - if (likely(mm_cpumask != NULL)) { - cpumask_clear_cpu(cpu, mm_cpumask); - } -#endif - context->cpumsk[cpu] = 0; - pid = 0; - } - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_mm(cpu, context, is_active, old_pid, pid); - } -} - -/* - * Flush just one specified address of current process. - */ -static inline void -mmu_pid_flush_tlb_address(mm_context_t *context, - e2k_addr_t addr, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int cpu = raw_smp_processor_id(); - unsigned long old_pid, pid; - - old_pid = context->cpumsk[cpu]; - - if (unlikely(old_pid == 0)) { - /* See comment in __flush_tlb_range(). */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = context->cpumsk[cpu]; - } else { - count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE); - pid = old_pid; - flush_TLB_page(addr, CTX_HARDWARE(pid)); - } - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_address(cpu, context, addr, old_pid, pid); - } -} - -/* - * Flush the TLB entries mapping the virtually mapped linear page - * table corresponding to specified address of current process. - */ -static inline void -mmu_pid_flush_tlb_address_pgtables(mm_context_t *context, - e2k_addr_t addr, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int cpu = raw_smp_processor_id(); - unsigned long old_pid, pid; - - old_pid = context->cpumsk[cpu]; - - if (unlikely(old_pid == 0)) { - /* See comment in __flush_tlb_range(). */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = context->cpumsk[cpu]; - } else { - pid = old_pid; - flush_TLB_page_begin(); - /* flush virtual mapping of PTE entry (third level) */ - __flush_TLB_page(pte_virt_offset(_PAGE_ALIGN_UP(addr, - PTE_SIZE)), - CTX_HARDWARE(pid)); - /* flush virtual mapping of PMD entry (second level) */ - __flush_TLB_page(pmd_virt_offset(_PAGE_ALIGN_UP(addr, - PMD_SIZE)), - CTX_HARDWARE(pid)); - /* flush virtual mapping of PUD entry (first level) */ - __flush_TLB_page(pud_virt_offset(_PAGE_ALIGN_UP(addr, - PUD_SIZE)), - CTX_HARDWARE(pid)); - flush_TLB_page_end(); - } - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_address(cpu, context, addr, old_pid, pid); - trace_mmu_pid_flush_tlb_address(cpu, context, - pte_virt_offset(_PAGE_ALIGN_UP(addr, PTE_SIZE)), - old_pid, pid); - trace_mmu_pid_flush_tlb_address(cpu, context, - pmd_virt_offset(_PAGE_ALIGN_UP(addr, PMD_SIZE)), - old_pid, pid); - trace_mmu_pid_flush_tlb_address(cpu, context, - pud_virt_offset(_PAGE_ALIGN_UP(addr, PUD_SIZE)), - old_pid, pid); - } -} - -/* - * Flush just one page of a specified user. - */ -static inline void -mmu_pid_flush_tlb_page(mm_context_t *context, - e2k_addr_t addr, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int cpu = raw_smp_processor_id(); - unsigned long old_pid, pid; - - old_pid = context->cpumsk[cpu]; - - if (unlikely(old_pid == 0)) { - /* See comment in __flush_tlb_range(). */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = context->cpumsk[cpu]; - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_address(cpu, context, addr, - old_pid, pid); - } - return; - } - - count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE); - - pid = old_pid; - flush_TLB_page_begin(); - __flush_TLB_page(addr, CTX_HARDWARE(pid)); - /* flush virtual mapping of PTE entry (third level) */ - __flush_TLB_page(pte_virt_offset(addr), CTX_HARDWARE(pid)); - flush_TLB_page_end(); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_address(cpu, context, addr, old_pid, pid); - trace_mmu_pid_flush_tlb_address(cpu, context, - pte_virt_offset(_PAGE_ALIGN_UP(addr, PTE_SIZE)), - old_pid, pid); - } -} - -/* - * Flush a specified range of pages - */ - -/* If the number of pages to be flushed is below this value, - * then only those pages will be flushed. - * - * Flushing one page takes ~150 cycles, flushing the whole mm - * takes ~400 cycles. Also note that __flush_tlb_range() may - * be called repeatedly for the same process so high values - * are bad. */ -#define FLUSH_TLB_RANGE_MAX_PAGES 8 - -static inline void -mmu_pid_flush_tlb_range(mm_context_t *context, - const e2k_addr_t start, const e2k_addr_t end, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - const long pages_num = (PAGE_ALIGN_DOWN(end) - PAGE_ALIGN_UP(start)) - / PAGE_SIZE; - int cpu = raw_smp_processor_id(); - unsigned long old_pid, pid; - - BUG_ON(start > end); - - DebugPT("range start 0x%lx end 0x%lx context 0x%lx PID 0x%lx CPU #%d\n", - PAGE_ALIGN_UP(start), PAGE_ALIGN_DOWN(end), - CTX_HARDWARE(context->cpumsk[cpu]), - context->cpumsk[cpu], cpu); - - old_pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (pages_num <= FLUSH_TLB_RANGE_MAX_PAGES) { - unsigned long page, pmd_start, pmd_end; - - if (unlikely(old_pid == 0)) { - /* We were trying to flush a range of pages, - * but someone is flushing the whole mm. - * Now we cannot flush pages (we do not know - * the context) so we have to flush the whole mm. - * - * Even if we will receive the flush ipi we will - * just end up flushing mm twice - which is OK - * considering how rare this case is. */ - goto flush_mm; - } - - count_vm_tlb_events(NR_TLB_LOCAL_FLUSH_ONE, pages_num); - - pid = old_pid; - flush_TLB_page_begin(); - for (page = PAGE_ALIGN_UP(start); page < end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - /* - * flush virtual mapping of PTE entry (third level) - * - * Needed because Linux assumes that flush_tlb_*() - * interfaces flush both pte and pmd levels (this - * may be changed in future versions, in which case - * this flush can be removed). - */ - pmd_start = pte_virt_offset(round_down(start, PMD_SIZE)); - pmd_end = pte_virt_offset(round_up(end, PMD_SIZE)); - for (page = round_down(pmd_start, PAGE_SIZE); - page < pmd_end; page += PAGE_SIZE) - __flush_TLB_page(page, pid); - flush_TLB_page_end(); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - trace_mmu_pid_flush_tlb_range(cpu, context, - pmd_start, pmd_end, old_pid, pid); - } - } else { -flush_mm: - /* Too many pages to flush. - * It is faster to change the context instead. - * If mm != current->active_mm then setting this - * CPU's mm context to 0 will do the trick, - * otherwise we duly increment it. */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - } - } -} - -static inline void -mmu_pid_flush_pmd_tlb_range(mm_context_t *context, - unsigned long start, unsigned long end, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - long pages_num; - int cpu = raw_smp_processor_id(); - unsigned long old_pid, pid; - - BUG_ON(start > end); - - end = round_up(end, PMD_SIZE); - start = round_down(start, PMD_SIZE); - - pages_num = (end - start) / PMD_SIZE; - - old_pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (pages_num <= FLUSH_TLB_RANGE_MAX_PAGES) { - unsigned long pmd_start, pmd_end; - e2k_addr_t page; - - if (unlikely(old_pid == 0)) { - /* We were trying to flush a range of pages, - * but someone is flushing the whole mm. - * Now we cannot flush pages (we do not know - * the context) so we have to flush the whole mm. - * - * Even if we will receive the flush ipi we will - * just end up flushing mm twice - which is OK - * considering how rare this case is. */ - goto flush_mm; - } - - count_vm_tlb_events(NR_TLB_LOCAL_FLUSH_ONE, - pages_num * (PMD_SIZE / PTE_SIZE)); - - pid = old_pid; - flush_TLB_page_begin(); - for (page = start; page < end; page += PMD_SIZE) - __flush_TLB_page(page, pid); - /* - * flush virtual mapping of PTE entry (third level). - * - * When flushing high order page table entries, - * we must also flush all links below it. E.g. when - * flushing PMD, also flush PMD->PTE link (i.e. DTLB - * entry for address 0xff8000000000|(address >> 9)). - * - * Otherwise the following can happen: - * 1) High-order page is allocated. - * 2) Someone accesses the PMD->PTE link (e.g. half-spec. load) - * and creates invalid entry in DTLB. - * 3) High-order page is split into 4 Kb pages. - * 4) Someone accesses the PMD->PTE link address (e.g. DTLB - * entry probe) and reads the invalid entry created earlier. - */ - pmd_start = pte_virt_offset(round_down(start, PMD_SIZE)); - pmd_end = pte_virt_offset(round_up(end, PMD_SIZE)); - for (page = round_down(pmd_start, PAGE_SIZE); - page < pmd_end; page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - trace_mmu_pid_flush_tlb_range(cpu, context, - pmd_start, pmd_end, old_pid, pid); - } - flush_TLB_page_end(); - } else { -flush_mm: - /* Too many pages to flush. - * It is faster to change the context instead. - * If mm != current->active_mm then setting this - * CPU's mm context to 0 will do the trick, - * otherwise we duly increment it. */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - } - } -} - -/* - * Flush the TLB entries mapping the virtually mapped linear page - * table corresponding to address range [start : end]. - */ -static inline void -mmu_pid_flush_tlb_pgtables(mm_context_t *context, - e2k_addr_t start, e2k_addr_t end, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - const long pages_num = (PAGE_ALIGN_DOWN(end) - PAGE_ALIGN_UP(start)) - / PAGE_SIZE; - int cpu = raw_smp_processor_id(); - unsigned long old_pid, pid; - - BUG_ON(start > end); - - DebugPT("range start 0x%lx end 0x%lx context 0x%lx pid 0x%lx CPU #%d\n", - PAGE_ALIGN_UP(start), PAGE_ALIGN_DOWN(end), - CTX_HARDWARE(context->cpumsk[cpu]), - context->cpumsk[cpu], cpu); - - old_pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (pages_num <= FLUSH_TLB_RANGE_MAX_PAGES) { - e2k_addr_t page; - unsigned long range_begin, range_end; - - if (unlikely(old_pid == 0)) { - /* We were trying to flush a range of pages, - * but someone is flushing the whole mm. - * Now we cannot flush pages (we do not know - * the context) so we have to flush the whole mm. - * - * Even if we will receive the flush ipi we will - * just end up flushing mm twice - which is OK - * considering how rare this case is. */ - goto flush_mm; - } - - pid = old_pid; - flush_TLB_page_begin(); - - /* flush virtual mapping of PTE entries (third level) */ - range_begin = pte_virt_offset(_PAGE_ALIGN_UP(start, PTE_SIZE)); - range_end = pte_virt_offset(_PAGE_ALIGN_DOWN(end, PTE_SIZE)); - for (page = PAGE_ALIGN_UP(range_begin); page < range_end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - range_begin, range_end, old_pid, pid); - } - - /* flush virtual mapping of PMD entries (second level) */ - range_begin = pmd_virt_offset(_PAGE_ALIGN_UP(start, PMD_SIZE)); - range_end = pmd_virt_offset(_PAGE_ALIGN_DOWN(end, PMD_SIZE)); - for (page = PAGE_ALIGN_UP(range_begin); page < range_end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - range_begin, range_end, old_pid, pid); - } - - /* flush virtual mapping of PUD entries (first level) */ - range_begin = pud_virt_offset(_PAGE_ALIGN_UP(start, PUD_SIZE)); - range_end = pud_virt_offset(_PAGE_ALIGN_DOWN(end, PUD_SIZE)); - for (page = PAGE_ALIGN_UP(range_begin); page < range_end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - range_begin, range_end, old_pid, pid); - } - - flush_TLB_page_end(); - } else { -flush_mm: - /* Too many pages to flush. - * It is faster to change the context instead. - * If mm != current->active_mm then setting this - * CPU's mm context to 0 will do the trick, - * otherwise we duly increment it. */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - } - } -} - -/* - * Flush a specified range of pages and the TLB entries mapping the virtually - * mapped linear page table corresponding to address range [start : end]. - */ -static inline void -mmu_pid_flush_tlb_range_and_pgtables(mm_context_t *context, - e2k_addr_t start, e2k_addr_t end, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - mmu_pid_flush_tlb_range(context, start, end, is_active, mm_cpumask, - trace_enabled); - mmu_pid_flush_tlb_pgtables(context, start, end, is_active, mm_cpumask, - trace_enabled); -} - -static inline void -mmu_pid_flush_tlb_page_and_pgtables(mm_context_t *context, - unsigned long address, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - unsigned long page; - unsigned long start = address, end = address + E2K_MAX_FORMAT; - unsigned long range_begin, range_end; - unsigned long pid = context->cpumsk[raw_smp_processor_id()]; - int cpu = raw_smp_processor_id(); - unsigned long old_pid, new_pid; - - old_pid = context->cpumsk[cpu]; - if (unlikely(old_pid == 0)) { - /* See comment in __flush_tlb_range(). */ - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - pid = CTX_HARDWARE(context->cpumsk[cpu]); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - } - return; - } - - new_pid = old_pid; - pid = CTX_HARDWARE(new_pid); - - flush_TLB_page_begin(); - - /* flush virtual mapping of PUD entries (first level) */ - range_begin = pud_virt_offset(_PAGE_ALIGN_UP(start, PUD_SIZE)); - range_end = pud_virt_offset(_PAGE_ALIGN_DOWN(end, PUD_SIZE)); - for (page = PAGE_ALIGN_UP(range_begin); page < range_end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - range_begin, range_end, old_pid, new_pid); - } - - /* flush virtual mapping of PMD entries (second level) */ - range_begin = pmd_virt_offset(_PAGE_ALIGN_UP(start, PMD_SIZE)); - range_end = pmd_virt_offset(_PAGE_ALIGN_DOWN(end, PMD_SIZE)); - for (page = PAGE_ALIGN_UP(range_begin); page < range_end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - range_begin, range_end, old_pid, new_pid); - } - - /* flush virtual mapping of PTE entries (third level) */ - range_begin = pte_virt_offset(_PAGE_ALIGN_UP(start, PTE_SIZE)); - range_end = pte_virt_offset(_PAGE_ALIGN_DOWN(end, PTE_SIZE)); - for (page = PAGE_ALIGN_UP(range_begin); page < range_end; - page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - range_begin, range_end, old_pid, new_pid); - } - - for (page = PAGE_ALIGN_UP(start); page < end; page += PAGE_SIZE) - __flush_TLB_page(page, pid); - if (unlikely(trace_enabled)) { - trace_mmu_pid_flush_tlb_range(cpu, context, - start, end, old_pid, pid); - } - - flush_TLB_page_end(); -} - -#ifdef CONFIG_SMP - -/* - * Flush a specified user mapping - */ - -static inline void -mmu_pid_smp_flush_tlb_mm(mm_context_t *context, - void (*flush_ipi_func)(void *data), void *flush_ipi_data, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - preempt_disable(); - - /* Signal to all users of this mm that it has been flushed. - * Invalid context will be updated while activating or switching to. */ - memset(context->cpumsk, 0, nr_cpu_ids * sizeof(context->cpumsk[0])); - - /* See comment about memory barriers in do_switch_mm(). */ - smp_mb(); - - mmu_pid_flush_tlb_mm(context, is_active, mm_cpumask, trace_enabled); - - /* Check that mm_cpumask() has some other CPU set */ - if (cpumask_any_but(mm_cpumask, smp_processor_id()) < nr_cpu_ids) { - /* Send flush ipi to all other cpus in mm_cpumask(). */ - count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); - smp_call_function_many(mm_cpumask, flush_ipi_func, - flush_ipi_data, 1); - } - - preempt_enable(); -} - -/* - * Flush a single page from TLB - */ - -static inline void -mmu_pid_smp_flush_tlb_page(mm_context_t *context, const e2k_addr_t addr, - void (*flush_ipi_func)(void *data), void *flush_ipi_data, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int i, cpu; - - preempt_disable(); - - cpu = smp_processor_id(); - - /* See comment in smp_flush_tlb_range() */ - for (i = 0; i < nr_cpu_ids; i++) { - if (i == cpu) - continue; - context->cpumsk[i] = 0; - } - - mmu_pid_flush_tlb_page(context, addr, is_active, mm_cpumask, - trace_enabled); - - /* See comment about memory barriers in do_switch_mm(). */ - smp_mb(); - - /* Check that mm_cpumask() has some other CPU set */ - if (cpumask_any_but(mm_cpumask, cpu) < nr_cpu_ids) { - /* Send flush ipi to all other cpus in mm_cpumask(). */ - count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); - smp_call_function_many(mm_cpumask, flush_ipi_func, - flush_ipi_data, 1); - } - - preempt_enable(); -} - -/* - * Flush a range of pages - */ - -static inline void -mmu_pid_smp_flush_tlb_range(mm_context_t *context, - const e2k_addr_t start, const e2k_addr_t end, - void (*flush_ipi_func)(void *data), void *flush_ipi_data, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int cpu, i; - - preempt_disable(); - - cpu = smp_processor_id(); - - /* Signal to all users of this mm that it has been flushed. - * Invalid context will be updated while activating or switching to. - * - * Things to consider: - * - * 1) Clearing the whole context for CPUs to which we send the flush - * ipi looks unnecessary, but is needed to avoid race conditions. The - * problem is that there is a window between reading mm_cpumask() and - * deciding which context should be set to 0. In that window situation - * could have changed, so the only safe way is to set mm context on - * ALL cpus to 0. - * - * 2) Setting it to 0 essentially means that the cpus which receive the - * flush ipis cannot flush only a range of pages because they do not - * know the context, so they will flush the whole mm. - * - * 3) TODO FIXME This way of doing things is OK for 2 CPUs, for 4 CPUs, - * but it may become a problem for e2s with its 64 CPUs if there is a - * really-multi-threaded application running. If this is the case it - * would be better to implement scheme which will remember pending TLB - * flush requests. But such a scheme will greatly increase struct mm - * size (64 * 4 * 32 = 8 Kb for 64-processors system with a maximum - * of 4 simultaneously pending flushes each taking up 32 bytes). - * - * This problem (3) only gets worse when we are making all pages valid - * since EVERY mmap/sys_brk and some other calls will end up sending - * 63 flush ipis which will flush all the TLBs. - */ - for (i = 0; i < nr_cpu_ids; i++) { - if (i == cpu) - /* That being said, current CPU can still - * flush only the given range of pages. */ - continue; - context->cpumsk[i] = 0; - } - - mmu_pid_flush_tlb_range(context, start, end, is_active, mm_cpumask, - trace_enabled); - - /* See comment about memory barriers in do_switch_mm(). */ - smp_mb(); - - /* Check that mm_cpumask() has some other CPU set */ - if (cpumask_any_but(mm_cpumask, cpu) < nr_cpu_ids) { - /* Send flush ipi to all other cpus in mm_cpumask(). */ - count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); - smp_call_function_many(mm_cpumask, flush_ipi_func, - flush_ipi_data, 1); - } - - preempt_enable(); -} - -/* - * As native_smp_flush_tlb_range() but for pmd's - */ -static inline void -mmu_pid_smp_flush_pmd_tlb_range(mm_context_t *context, - const e2k_addr_t start, const e2k_addr_t end, - void (*flush_ipi_func)(void *data), void *flush_ipi_data, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) - -{ - int cpu, i; - - preempt_disable(); - - cpu = smp_processor_id(); - - /* See comment in smp_flush_tlb_range() */ - for (i = 0; i < nr_cpu_ids; i++) { - if (i == cpu) - /* That being said, current CPU can still - * flush only the given range of pages. */ - continue; - context->cpumsk[i] = 0; - } - - mmu_pid_flush_pmd_tlb_range(context, start, end, is_active, mm_cpumask, - trace_enabled); - - /* See comment about memory barriers in do_switch_mm(). */ - smp_mb(); - - /* Check that mm_cpumask() has some other CPU set */ - if (cpumask_any_but(mm_cpumask, cpu) < nr_cpu_ids) { - /* Send flush ipi to all other cpus in mm_cpumask(). */ - count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); - smp_call_function_many(mm_cpumask, flush_ipi_func, - flush_ipi_data, 1); - } - - preempt_enable(); -} - -/* - * Flush a range of pages and page tables. - */ - -static inline void -mmu_pid_smp_flush_tlb_range_and_pgtables(mm_context_t *context, - const e2k_addr_t start, const e2k_addr_t end, - void (*flush_ipi_func)(void *data), void *flush_ipi_data, - bool is_active, cpumask_t *mm_cpumask, - bool trace_enabled) -{ - int i, cpu; - - preempt_disable(); - - cpu = smp_processor_id(); - - /* See comment in smp_flush_tlb_range() */ - for (i = 0; i < nr_cpu_ids; i++) { - if (i == cpu) - continue; - context->cpumsk[i] = 0; - } - - mmu_pid_flush_tlb_range_and_pgtables(context, start, end, is_active, - mm_cpumask, trace_enabled); - - /* See comment about memory barriers in do_switch_mm(). */ - smp_mb(); - - /* Check that mm_cpumask() has some other CPU set */ - if (cpumask_any_but(mm_cpumask, cpu) < nr_cpu_ids) { - /* Send flush ipi to all other cpus in mm_cpumask(). */ - count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); - smp_call_function_many(mm_cpumask, flush_ipi_func, - flush_ipi_data, 1); - } - - preempt_enable(); -} - -#endif /* CONFIG_SMP */ - -#endif /* _E2K_TLB_CONTEXT_H_ */ diff --git a/arch/e2k/include/asm/tlb.h b/arch/e2k/include/asm/tlb.h index 94194c4..9ed1b2f 100644 --- a/arch/e2k/include/asm/tlb.h +++ b/arch/e2k/include/asm/tlb.h @@ -1,35 +1,39 @@ #ifndef _E2K_TLB_H #define _E2K_TLB_H -#include +struct mmu_gather; - -static inline void __tlb_remove_table(void *_table) -{ - free_page_and_swap_cache((struct page *)_table); -} - -#define tlb_flush(tlb) \ -{ \ - if (!(tlb)->fullmm && !(tlb)->need_flush_all) \ - flush_tlb_mm_range((tlb)->mm, (tlb)->start, (tlb)->end); \ - else \ - flush_tlb_mm((tlb)->mm); \ -} - -#define tlb_start_vma(tlb, vma) \ -do { \ -} while (0) - -#define tlb_end_vma(tlb, vma) \ -do { \ -} while (0) - -#define __tlb_remove_tlb_entry(tlb, ptep, address) \ - do { } while (0) +#define tlb_flush tlb_flush +static void tlb_flush(struct mmu_gather *tlb); #include +static inline void tlb_flush(struct mmu_gather *tlb) +{ + if (tlb->fullmm || tlb->need_flush_all) { + flush_tlb_mm(tlb->mm); + } else if (tlb->end) { + unsigned long stride = tlb_get_unmap_size(tlb); + u32 levels_mask = E2K_PAGES_LEVEL_MASK; + + if (tlb->freed_tables) { + /* Note: if we ever have 5-level page tables then + * we'll have to unconditinally add P4D_LEVEL + * here since there is no corresponding bit in + * [struct mmu_gather] (or add the bit). */ + if (tlb->cleared_pmds) + levels_mask |= E2K_PTE_LEVEL_MASK; + if (tlb->cleared_puds) + levels_mask |= E2K_PMD_LEVEL_MASK; + if (tlb->cleared_p4ds) + levels_mask |= E2K_PUD_LEVEL_MASK; + } + + flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, + stride, levels_mask); + } +} + #define __pud_free_tlb(tlb, pudp, start) pud_free((tlb)->mm, pudp) #define __pmd_free_tlb(tlb, pmdp, start) pmd_free((tlb)->mm, pmdp) #define __pte_free_tlb(tlb, ptep, addr) pte_free((tlb)->mm, ptep) diff --git a/arch/e2k/include/asm/tlbflush.h b/arch/e2k/include/asm/tlbflush.h index 23f596a..3b9e43d 100644 --- a/arch/e2k/include/asm/tlbflush.h +++ b/arch/e2k/include/asm/tlbflush.h @@ -17,35 +17,82 @@ * - flush_tlb_mm(mm) flushes the specified mm context TLB's * - flush_tlb_page(vma, vmaddr) flushes one page * - flush_tlb_range(mm, start, end) flushes a range of pages + * + * "local_" versions flush on the calling CPU only. */ -extern void __flush_tlb_all(void); -extern void __flush_tlb_mm(struct mm_struct *mm); -extern void __flush_tlb_page(struct mm_struct *mm, e2k_addr_t addr); -extern void __flush_tlb_range(struct mm_struct *mm, e2k_addr_t start, - e2k_addr_t end); -extern void __flush_pmd_tlb_range(struct mm_struct *mm, - unsigned long start, unsigned long end); -extern void __flush_tlb_pgtables(struct mm_struct *mm, e2k_addr_t start, - e2k_addr_t end); -extern void __flush_tlb_page_and_pgtables(struct mm_struct *mm, - unsigned long addr); +/** + * native_flush_tlb_mm_range - flush specified range from all TLU caches + * (i.e. from L1D, L1I, DTLB, TLU_CACHE.PWC, TLU_CACHE.GWC) + * @mm: contains hardware context (called ASID on other arch-es) + * @start: start of the range to flush + * @end: end of the range to flush + * @stride: distance between consequential flushes + * @levels_mask: set if there are intermediate page table levels to flush. + * + * Note that @levels_mask should be 0 if we want to flush only the last level. + * For example, to flush just huge PMDs: levels_mask=0 and stride=PMD_SIZE. + * + * Macros are defined for convenience: + * FLUSH_TLB_LEVELS_ALL - flush all levels + * FLUSH_TLB_LEVELS_LAST - flush last level only (be it huge mapping or not) + * FLUSH_TLB_LEVELS_INTERMEDIATE - flush everything but the last level + */ +#define FLUSH_TLB_LEVELS_ALL (E2K_PAGES_LEVEL_MASK | E2K_PTE_LEVEL_MASK | \ + E2K_PMD_LEVEL_MASK | E2K_PUD_LEVEL_MASK) +#define FLUSH_TLB_LEVELS_LAST E2K_PAGES_LEVEL_MASK +#define FLUSH_TLB_LEVELS_INTERMEDIATE (E2K_PTE_LEVEL_MASK | \ + E2K_PMD_LEVEL_MASK | E2K_PUD_LEVEL_MASK) +extern void native_flush_tlb_mm_range(struct mm_struct *mm, + unsigned long start, unsigned long end, + unsigned long stride, u32 levels_mask); +extern void native_flush_tlb_page(struct mm_struct *mm, unsigned long addr); +extern void native_flush_tlb_mm(struct mm_struct *mm); +extern void native_flush_tlb_all(void); -extern void __flush_tlb_range_and_pgtables(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); -extern void __flush_tlb_address(e2k_addr_t addr); -extern void __flush_tlb_address_pgtables(e2k_addr_t addr); -extern void native_smp_flush_tlb_all(void); -extern void native_smp_flush_tlb_mm(struct mm_struct *mm); -extern void native_smp_flush_tlb_page(struct vm_area_struct *vma, - e2k_addr_t addr); -extern void native_smp_flush_tlb_range(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); -extern void native_smp_flush_pmd_tlb_range(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); -extern void native_smp_flush_tlb_range_and_pgtables(struct mm_struct *mm, - e2k_addr_t start, e2k_addr_t end); +/* Linux assumes that flush_tlb_range() interface flushes + * all levels (this may be changed in future versions in + * which case we can pass FLUSH_TLB_LEVELS_LAST instead). + * + * E.g. we may be invalidating table entries as part of + * collapsing hugepages or moving page tables. */ +#define native_flush_tlb_range(mm, start, end) \ + native_flush_tlb_mm_range((mm), (start), (end), \ + PAGE_SIZE, FLUSH_TLB_LEVELS_ALL) + +#define native_flush_tlb_range_and_pgtables(mm, start, end) \ + native_flush_tlb_mm_range((mm), (start), (end), \ + PAGE_SIZE, FLUSH_TLB_LEVELS_ALL) + +#define native_flush_pmd_tlb_range(mm, start, end) \ + native_flush_tlb_mm_range((mm), (start), (end), \ + PMD_SIZE, FLUSH_TLB_LEVELS_LAST) + +static inline void native_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + native_flush_tlb_all(); +} + +extern void generic_flush_tlb_mm(struct mm_struct *mm, mm_context_t *context, + cpumask_t *mm_cpumask, bool trace_enabled); +extern void generic_flush_tlb_page(struct mm_struct *mm, mm_context_t *context, + cpumask_t *mm_cpumask, unsigned long addr, bool trace_enabled); +extern void generic_flush_tlb_mm_range(struct mm_struct *mm, mm_context_t *context, + cpumask_t *mm_cpumask, unsigned long start, unsigned long end, + unsigned long stride, u32 levels_mask, bool trace_enabled); + +extern void native_local_flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long stride, u32 levels_mask); +extern void native_local_flush_tlb_page(struct mm_struct *mm, unsigned long addr); +extern void native_local_flush_tlb_mm(struct mm_struct *mm); +extern void native_local_flush_tlb_all(void); +static inline void native_local_flush_tlb_page_and_pgtables( + struct mm_struct *mm, unsigned long uaddr) +{ + native_local_flush_tlb_mm_range(mm, uaddr, uaddr + 1, + PAGE_SIZE, FLUSH_TLB_LEVELS_ALL); +} #ifdef CONFIG_COPY_USER_PGD_TO_KERNEL_ROOT_PT extern void __flush_cpu_root_pt_mm(struct mm_struct *mm); @@ -58,64 +105,53 @@ extern void __flush_cpu_root_pt(void); #if defined(CONFIG_PARAVIRT_GUEST) /* it is paravirtualized host and guest kernel */ -#include +# include #elif defined(CONFIG_KVM_GUEST_KERNEL) /* it is native guest kernel */ #include -#define flush_tlb_all kvm_flush_tlb_all -#define flush_tlb_mm kvm_flush_tlb_mm -#define flush_tlb_page(vma, addr) kvm_flush_tlb_page(vma, addr) -#define flush_tlb_range(vma, start, end) \ - kvm_flush_tlb_range(vma->vm_mm, start, end) -#define flush_tlb_kernel_range(start, end) \ - kvm_flush_tlb_kernel_range(start, end) -#define flush_pmd_tlb_range(vma, start, end) \ - kvm_flush_pmd_tlb_range(vma->vm_mm, start, end) -#define flush_tlb_mm_range(mm, start, end) \ - kvm_flush_tlb_range(mm, start, end) -#define flush_tlb_range_and_pgtables(mm, start, end) \ - kvm_flush_tlb_range_and_pgtables(mm, start, end) +# define flush_tlb_all kvm_flush_tlb_all +# define flush_tlb_kernel_range kvm_flush_tlb_kernel_range +# define flush_tlb_mm kvm_flush_tlb_mm +# define flush_tlb_page(vma, addr) kvm_flush_tlb_page((vma)->vm_mm, (addr)) +# define flush_tlb_mm_range kvm_flush_tlb_mm_range +# define flush_tlb_range_and_pgtables kvm_flush_tlb_range_and_pgtables +# define flush_tlb_range(vma, start, end) \ + kvm_flush_tlb_range((vma)->vm_mm, (start), (end)) +# define flush_pmd_tlb_range(vma, start, end) \ + kvm_flush_pmd_tlb_range((vma)->vm_mm, (start), (end)) +/* local_*() versions are for flushing current CPU only. + * A bit of an overkill: flushing whole mm instead of just current CPU... */ +# define local_flush_tlb_mm_range kvm_flush_tlb_mm_range +# define local_flush_tlb_page kvm_flush_tlb_page +# define local_flush_tlb_mm kvm_flush_tlb_mm +# define local_flush_tlb_page_and_pgtables kvm_flush_tlb_page_and_pgtables +/* TODO FIXME write flush_tlb_kernel_range_nmi() function and use it + * in set_memory_attr() */ +# define local_flush_tlb_all() \ + pr_warn_once("%s(): try to flush whole local TLB : op 0x%lx\n", \ + __func__, flush_op_tlb_all) #else /* ! CONFIG_PARAVIRT_GUEST && ! CONFIG_KVM_GUEST_KERNEL */ /* it is native kernel without virtualization support */ /* or native kernel with virtualization support */ - -#ifndef CONFIG_SMP - -#define flush_tlb_all __flush_tlb_all -#define flush_tlb_mm __flush_tlb_mm -#define flush_tlb_page(vma, addr) __flush_tlb_page(vma->vm_mm, addr) -#define flush_tlb_range(vma, start, end) \ - __flush_tlb_range(vma->vm_mm, start, end) -#define flush_pmd_tlb_range(vma, start, end) \ - __flush_pmd_tlb_range(vma->vm_mm, start, end) -#define flush_tlb_mm_range(mm, start, end) \ - __flush_tlb_range(mm, start, end) -#define flush_tlb_range_and_pgtables(mm, start, end) \ - __flush_tlb_range_and_pgtables(mm, start, end) - -#else /* CONFIG_SMP */ - -#include - -#define flush_tlb_all native_smp_flush_tlb_all -#define flush_tlb_mm native_smp_flush_tlb_mm -#define flush_tlb_page(vma, addr) native_smp_flush_tlb_page(vma, addr) -#define flush_tlb_range(vma, start, end) \ - native_smp_flush_tlb_range(vma->vm_mm, start, end) -#define flush_pmd_tlb_range(vma, start, end) \ - native_smp_flush_pmd_tlb_range(vma->vm_mm, start, end) -#define flush_tlb_mm_range(mm, start, end) \ - native_smp_flush_tlb_range(mm, start, end) -#define flush_tlb_range_and_pgtables(mm, start, end) \ - native_smp_flush_tlb_range_and_pgtables(mm, start, end) - -#endif /* CONFIG_SMP */ - -#define flush_tlb_kernel_range(start, end) flush_tlb_all() - +# define flush_tlb_all native_flush_tlb_all +# define flush_tlb_kernel_range native_flush_tlb_kernel_range +# define flush_tlb_mm native_flush_tlb_mm +# define flush_tlb_page(vma, addr) native_flush_tlb_page((vma)->vm_mm, (addr)) +# define flush_tlb_mm_range native_flush_tlb_mm_range +# define flush_tlb_range_and_pgtables native_flush_tlb_range_and_pgtables +# define flush_tlb_range(vma, start, end) \ + native_flush_tlb_range((vma)->vm_mm, (start), (end)) +# define flush_pmd_tlb_range(vma, start, end) \ + native_flush_pmd_tlb_range((vma)->vm_mm, (start), (end)) +/* local_*() versions are for flushing current CPU only */ +# define local_flush_tlb_mm_range native_local_flush_tlb_mm_range +# define local_flush_tlb_page native_local_flush_tlb_page +# define local_flush_tlb_mm native_local_flush_tlb_mm +# define local_flush_tlb_all native_local_flush_tlb_all +# define local_flush_tlb_page_and_pgtables \ + native_local_flush_tlb_page_and_pgtables #endif /* ! CONFIG_PARAVIRT_GUEST && ! CONFIG_KVM_GUEST_KERNEL */ - static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *pte) { diff --git a/arch/e2k/include/asm/trace-defs.h b/arch/e2k/include/asm/trace-defs.h index 89d2589..d75dfc2 100644 --- a/arch/e2k/include/asm/trace-defs.h +++ b/arch/e2k/include/asm/trace-defs.h @@ -2,6 +2,7 @@ #define _E2K_TRACE_DEFS_H_ #include +#include #include #include diff --git a/arch/e2k/include/asm/trace-mmu-dtlb-v2.h b/arch/e2k/include/asm/trace-mmu-dtlb-v2.h index bcee44a..62eb27d 100644 --- a/arch/e2k/include/asm/trace-mmu-dtlb-v2.h +++ b/arch/e2k/include/asm/trace-mmu-dtlb-v2.h @@ -4,8 +4,6 @@ #if !defined(_TRACE_E2K_MMU_DTLB_V2_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_E2K_MMU_DTLB_V2_H -#include - #define E2K_TRACE_PRINT_DTLB_ENTRY_V2(entry) \ ((entry & DTLB_ENTRY_ERROR_MASK_V2) ? \ __print_flags(entry & DTLB_ENTRY_ERROR_MASK_V2, "|", \ diff --git a/arch/e2k/include/asm/trace-mmu-dtlb-v6.h b/arch/e2k/include/asm/trace-mmu-dtlb-v6.h index 8dc7f19..88afd60 100644 --- a/arch/e2k/include/asm/trace-mmu-dtlb-v6.h +++ b/arch/e2k/include/asm/trace-mmu-dtlb-v6.h @@ -4,8 +4,6 @@ #if !defined(_TRACE_E2K_MMU_DTLB_V6_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_E2K_MMU_DTLB_V6_H -#include - #define E2K_TRACE_PRINT_DTLB_ENTRY_V6(entry) \ ((entry & DTLB_ENTRY_ERROR_MASK_V6) ? \ __print_flags(entry & DTLB_ENTRY_ERROR_MASK_V6, "|", \ diff --git a/arch/e2k/include/asm/trace-tlb-flush.h b/arch/e2k/include/asm/trace-tlb-flush.h index f626cc2..e1fea92 100644 --- a/arch/e2k/include/asm/trace-tlb-flush.h +++ b/arch/e2k/include/asm/trace-tlb-flush.h @@ -58,7 +58,7 @@ TRACE_EVENT( ); TRACE_EVENT( - mmu_pid_flush_tlb_address, + mmu_pid_flush_tlb_page, TP_PROTO(int cpu_id, mm_context_t *context, e2k_addr_t addr, unsigned long old_pid, unsigned long new_pid diff --git a/arch/e2k/include/asm/trace.h b/arch/e2k/include/asm/trace.h index 533bb79..18f1c87 100644 --- a/arch/e2k/include/asm/trace.h +++ b/arch/e2k/include/asm/trace.h @@ -5,7 +5,6 @@ #define _TRACE_E2K_H #include -#include #include #include #include diff --git a/arch/e2k/include/asm/trap_table.S.h b/arch/e2k/include/asm/trap_table.S.h index 846503a..3ae5ed2 100644 --- a/arch/e2k/include/asm/trap_table.S.h +++ b/arch/e2k/include/asm/trap_table.S.h @@ -48,7 +48,7 @@ rrd %rpr.lo, GCPUOFFSET; \ } \ { \ - rrd %rpr.hi, GCPUID; \ + rrd %rpr.hi, GCPUID_PREEMPT; \ /* Disable load/store generations */ \ crp; \ } \ @@ -56,7 +56,8 @@ /* * This assumes that GVCPUSTATE points to current_thread_info() - * and %psp.hi has been read into GCURTASK + * and %psp.hi has been read into GCURTASK. + * %pred0 == true if this is a kernel trap handler. * * %pred0 - set to "true" if PSP/PCSP should be switched. * %pred1 - set to "true" if RPR should be restored. @@ -81,19 +82,20 @@ __VA_ARGS__ \ } \ { \ - rwd GCPUID, %rpr.hi ? %pred1; \ - ldd,2 GVCPUSTATE, TI_K_PCSP_LO, GCPUID; \ + rwd GCPUID_PREEMPT, %rpr.hi ? %pred1; \ + ldd,2 GVCPUSTATE, TI_K_PCSP_LO, GCPUID_PREEMPT; \ } \ { \ rrd %psp.lo, GCURTASK ? %pred0; \ stgdd,2 GCURTASK, 0, TSK_TI_TMP_U_PSP_HI ? %pred0; \ - SMP_ONLY(ldgdw,5 0, TSK_TI_CPU_DELTA, GCPUID ? ~ %pred0;) \ + ldgdd,5 0, TSK_TI_TMP_G_MY_CPU_OFFSET_EXT, GCPUID_PREEMPT ? ~ %pred0; \ } \ { \ rrd %pcsp.hi, GCURTASK ? %pred0; \ stgdd,2 GCURTASK, 0, TSK_TI_TMP_U_PSP_LO ? %pred0; \ /* Nothing to do if this is kernel (%pred0 == false) */ \ subd,1 GVCPUSTATE, TSK_TI, GCURTASK ? ~ %pred0; \ + SMP_ONLY(ldgdd,5 0, TSK_TI_TMP_G_MY_CPU_OFFSET, GCPUOFFSET ? ~ %pred0;) \ ibranch trap_handler_switched_stacks ? ~ %pred0; \ } \ { \ @@ -106,9 +108,9 @@ ldrd,5 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_MY_CPU_OFFSET_EXT, GCPUOFFSET; \ } \ { \ - rwd GCPUID, %pcsp.lo; \ + rwd GCPUID_PREEMPT, %pcsp.lo; \ ldd,2 GVCPUSTATE, TI_K_PSP_HI, GCURTASK; \ - ldrd,5 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_VCPU_STATE_EXT, GCPUID; \ + ldrd,5 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_VCPU_STATE_EXT, GCPUID_PREEMPT; \ } \ { \ rwd GCURTASK, %psp.hi; \ @@ -121,12 +123,12 @@ rrd %pshtp, GCURTASK; \ } \ { \ - ldrd,3 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_CPU_ID, GCPUOFFSET; \ - strd,5 GCPUOFFSET, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_CPU_ID; \ + ldrd,3 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_CPU_ID_PREEMPT, GCPUOFFSET; \ + strd,5 GCPUOFFSET, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_CPU_ID_PREEMPT; \ } \ { \ - ldrd,3 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_TASK, GCPUID; \ - strd,5 GCPUID, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_TASK; \ + ldrd,3 GVCPUSTATE, TAGGED_MEM_LOAD_REC_OPC | PREFIX##G_TASK, GCPUID_PREEMPT; \ + strd,5 GCPUID_PREEMPT, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_TASK; \ } \ { \ nop 2; /* ld -> use */ \ @@ -139,8 +141,9 @@ strd,5 GCPUOFFSET, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_MY_CPU_OFFSET_EXT; \ } \ { \ - SMP_ONLY(ldw,3 GVCPUSTATE, TSK_TI_CPU_DELTA, GCPUID;) \ - strd,5 GCPUID, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_VCPU_STATE_EXT; \ + SMP_ONLY(ldw,3 GVCPUSTATE, TSK_TI_CPU_DELTA, GCPUID_PREEMPT;) \ + NOT_SMP_ONLY(addd,3 0, 0, GCPUID_PREEMPT;) \ + strd,5 GCPUID_PREEMPT, GVCPUSTATE, TAGGED_MEM_STORE_REC_OPC | PREFIX##G_VCPU_STATE_EXT; \ } .macro HANDLER_TRAMPOLINE ctprN, scallN, fn, wbsL @@ -153,7 +156,7 @@ call \ctprN, wbs=\wbsL disp \ctprN, \fn SWITCH_HW_STACKS_FROM_USER() - SMP_ONLY(shld,1 GCPUID, 3, GCPUOFFSET) + SMP_ONLY(shld,1 GCPUID_PREEMPT, 3, GCPUOFFSET) { SMP_ONLY(ldd,2 [ __per_cpu_offset + GCPUOFFSET ], GCPUOFFSET) ct \ctprN diff --git a/arch/e2k/include/asm/trap_table.h b/arch/e2k/include/asm/trap_table.h index 91ee634..f00642e 100644 --- a/arch/e2k/include/asm/trap_table.h +++ b/arch/e2k/include/asm/trap_table.h @@ -156,29 +156,30 @@ extern SYS_RET_TYPE notrace handle_sys_call(system_call_func sys_call, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, struct pt_regs *regs); +extern void notrace handle_guest_fast_sys_call(void); + extern const system_call_func sys_call_table[NR_syscalls]; extern const system_call_func sys_call_table_32[NR_syscalls]; extern const protected_system_call_func sys_call_table_entry8[NR_syscalls]; extern const system_call_func sys_protcall_table[NR_syscalls]; extern const system_call_func sys_call_table_deprecated[NR_syscalls]; -#ifndef CONFIG_CPU_HAS_FILL_INSTRUCTION #define native_restore_some_values_after_fill(__regs, __from, __return_to_user) \ do { \ - __regs = current_thread_info()->pt_regs; \ - if (!__builtin_constant_p(from)) \ - __from = current->thread.fill.from; \ - __return_to_user = current->thread.fill.return_to_user; \ + if (!cpu_has(CPU_FEAT_FILLC) || !cpu_has(CPU_FEAT_FILLR)) { \ + __regs = current_thread_info()->pt_regs; \ + if (!__builtin_constant_p(from)) \ + __from = current->thread.fill.from; \ + __return_to_user = current->thread.fill.return_to_user; \ + } \ } while (false) -#else /* CONFIG_CPU_HAS_FILL_INSTRUCTION */ -#define native_restore_some_values_after_fill(__regs, __from, __return_to_user) -#endif /* !CONFIG_CPU_HAS_FILL_INSTRUCTION */ #if !defined(CONFIG_PARAVIRT_GUEST) && !defined(CONFIG_KVM_GUEST_KERNEL) /* it is native kernel without any virtualization */ /* or it is host kernel with virtualization support */ -#define FILL_HARDWARE_STACKS() NATIVE_FILL_HARDWARE_STACKS() +#define FILL_HARDWARE_STACKS__HW() NATIVE_FILL_HARDWARE_STACKS__HW() +#define FILL_HARDWARE_STACKS__SW() NATIVE_FILL_HARDWARE_STACKS__SW() static inline void clear_fork_child_pt_regs(struct pt_regs *childregs) { @@ -256,7 +257,7 @@ is_kernel_data_stack_bounds(bool on_kernel, e2k_usd_lo_t usd_lo) #define GCURTASK DO_GET_GREG_MEMONIC(CURRENT_TASK_GREG) #define GCPUOFFSET DO_GET_GREG_MEMONIC(MY_CPU_OFFSET_GREG) -#define GCPUID DO_GET_GREG_MEMONIC(SMP_CPU_ID_GREG) +#define GCPUID_PREEMPT DO_GET_GREG_MEMONIC(SMP_CPU_ID_GREG) /* Macroses for virtualization support on assembler */ #define GVCPUSTATE DO_GET_GREG_MEMONIC(GUEST_VCPU_STATE_GREG) diff --git a/arch/e2k/include/asm/traps.h b/arch/e2k/include/asm/traps.h index 770e6c5..6aec14d 100644 --- a/arch/e2k/include/asm/traps.h +++ b/arch/e2k/include/asm/traps.h @@ -150,6 +150,14 @@ native_host_apply_pcsp_delta_to_signal_stack(unsigned long base, return 0; } +static inline int +native_host_apply_usd_delta_to_signal_stack(unsigned long top, + unsigned long delta, bool incr) +{ + /* native & host kernel cannot be paravirtualized guest */ + return 0; +} + /* * MMIO page fault cannot occur on native or host mode, * so ignore such traps @@ -213,6 +221,8 @@ extern int apply_psp_delta_to_signal_stack(unsigned long base, extern int apply_pcsp_delta_to_signal_stack(unsigned long base, unsigned long size, unsigned long start, unsigned long end, unsigned long delta); +extern int apply_usd_delta_to_signal_stack(unsigned long top, + unsigned long delta, bool incr); static inline int host_apply_psp_delta_to_signal_stack(unsigned long base, unsigned long size, unsigned long start, @@ -230,6 +240,12 @@ static inline int host_apply_pcsp_delta_to_signal_stack(unsigned long base, start, end, delta); } +static inline int host_apply_usd_delta_to_signal_stack(unsigned long top, + unsigned long delta, bool incr) +{ + return native_host_apply_usd_delta_to_signal_stack(top, delta, incr); +} + static inline unsigned long mmio_page_fault(struct pt_regs *regs, trap_cellar_t *tcellar) { diff --git a/arch/e2k/include/asm/uaccess.h b/arch/e2k/include/asm/uaccess.h index 3e9c960..948ed7b 100644 --- a/arch/e2k/include/asm/uaccess.h +++ b/arch/e2k/include/asm/uaccess.h @@ -197,7 +197,8 @@ extern int __get_user_bad(void) __attribute__((noreturn)); const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ might_fault(); \ access_ok(__gu_ptr, sizeof(*__gu_ptr)) ? \ - __get_user((x), __gu_ptr) : -EFAULT; \ + __get_user((x), __gu_ptr) : \ + ((x) = (__typeof__(x)) 0, -EFAULT); \ }) diff --git a/arch/e2k/include/asm/user.h b/arch/e2k/include/asm/user.h index 4cebe8e..fb2a4e6 100644 --- a/arch/e2k/include/asm/user.h +++ b/arch/e2k/include/asm/user.h @@ -14,12 +14,12 @@ #define __CHECK_KERNEL 0x1234567887654321ULL #define MLT_NUM (16 * 3) -/* FIXME comments - * ATTENTION!!! Any change should be sumited to debuger +/* + * ATTENTION!!! Any change should be submitted to debugger */ struct user_regs_struct { - unsigned long long sizeof_struct; // interface with debuger + unsigned long long sizeof_struct; /* interface with debugger */ unsigned long long g[32]; unsigned long long psr; diff --git a/arch/e2k/include/uapi/asm/auxvec.h b/arch/e2k/include/uapi/asm/auxvec.h deleted file mode 100644 index 777896c..0000000 --- a/arch/e2k/include/uapi/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _E2K_AUXVEC_H -#define _E2K_AUXVEC_H - -#endif /* _E2K_AUXVEC_H */ diff --git a/arch/e2k/include/uapi/asm/errno.h b/arch/e2k/include/uapi/asm/errno.h deleted file mode 100644 index 969b343..0000000 --- a/arch/e2k/include/uapi/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _I386_ERRNO_H -#define _I386_ERRNO_H - -#include - -#endif diff --git a/arch/e2k/include/uapi/asm/fcntl.h b/arch/e2k/include/uapi/asm/fcntl.h deleted file mode 100644 index 27fa498..0000000 --- a/arch/e2k/include/uapi/asm/fcntl.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include diff --git a/arch/e2k/include/uapi/asm/ioctl.h b/arch/e2k/include/uapi/asm/ioctl.h deleted file mode 100644 index b279fe0..0000000 --- a/arch/e2k/include/uapi/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/uapi/asm/ioctls.h b/arch/e2k/include/uapi/asm/ioctls.h deleted file mode 100644 index dd12291..0000000 --- a/arch/e2k/include/uapi/asm/ioctls.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _E2K_IOCTLS_H_ -#define _E2K_IOCTLS_H_ - -/* - * We are too far from real ioctl handling and it is difficult to predict - * any errors now. So I accept i386(ia64) ioctl's stuff as the basis. - */ - - -#include -#include - -#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ -#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ -#define TIOCGDB 0x547F /* enable GDB stub mode on this tty */ - -#endif /* _E2K_IOCTLS_H_ */ diff --git a/arch/e2k/include/uapi/asm/ipcbuf.h b/arch/e2k/include/uapi/asm/ipcbuf.h deleted file mode 100644 index 61689ce..0000000 --- a/arch/e2k/include/uapi/asm/ipcbuf.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _E2K_IPCBUF_H_ -#define _E2K_IPCBUF_H_ - -/* - * The ipc64_perm structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 32-bit seq - * - 2 miscellaneous 64-bit values - */ - -struct ipc64_perm { - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned short seq; - unsigned short __pad1; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _E2K_IPCBUF_H_ */ diff --git a/arch/e2k/include/uapi/asm/kvm.h b/arch/e2k/include/uapi/asm/kvm.h index dfa94cc..ea20bd4 100644 --- a/arch/e2k/include/uapi/asm/kvm.h +++ b/arch/e2k/include/uapi/asm/kvm.h @@ -467,6 +467,8 @@ typedef struct kvm_guest_nbsr_state { /* paravirtualized guest */ /* (same as ttable #0) */ +#define GUEST_FAST_SYSCALL_TRAP_NUM 6 + #ifndef __ASSEMBLY__ #define KVM_GET_ARCH_API_VERSION _IO(KVMIO, 0xe1) diff --git a/arch/e2k/include/uapi/asm/msgbuf.h b/arch/e2k/include/uapi/asm/msgbuf.h deleted file mode 100644 index d8d912d..0000000 --- a/arch/e2k/include/uapi/asm/msgbuf.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _E2K_MSGBUF_H_ -#define _E2K_MSGBUF_H_ - -/* - * The msqid64_ds structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - __kernel_time_t msg_rtime; /* last msgrcv time */ - __kernel_time_t msg_ctime; /* last change time */ - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _E2K_MSGBUF_H_ */ diff --git a/arch/e2k/include/uapi/asm/param.h b/arch/e2k/include/uapi/asm/param.h deleted file mode 100644 index d1c59aa..0000000 --- a/arch/e2k/include/uapi/asm/param.h +++ /dev/null @@ -1,20 +0,0 @@ -/* $Id: param.h,v 1.4 2008/12/19 12:44:14 atic Exp $ */ - -#ifndef _UAPI_E2K_PARAM_H_ -#define _UAPI_E2K_PARAM_H_ - - -#ifndef __KERNEL__ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 /* Intel size. */ - /* Check for 64K native pages if used. */ - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _UAPI_E2K_PARAM_H_ */ diff --git a/arch/e2k/include/uapi/asm/poll.h b/arch/e2k/include/uapi/asm/poll.h deleted file mode 100644 index c98509d..0000000 --- a/arch/e2k/include/uapi/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/uapi/asm/posix_types.h b/arch/e2k/include/uapi/asm/posix_types.h deleted file mode 100644 index 575deb1..0000000 --- a/arch/e2k/include/uapi/asm/posix_types.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _E2K_POSIX_TYPES_H_ -#define _E2K_POSIX_TYPES_H_ - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. - */ - -#include - -#endif /* _E2K_POSIX_TYPES_H_ */ diff --git a/arch/e2k/include/uapi/asm/sembuf.h b/arch/e2k/include/uapi/asm/sembuf.h deleted file mode 100644 index 816081c..0000000 --- a/arch/e2k/include/uapi/asm/sembuf.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _E2K_SEMBUF_H_ -#define _E2K_SEMBUF_H_ - -/* - * The semid64_ds structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - __kernel_time_t sem_ctime; /* last change time */ - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _E2K_SEMBUF_H_ */ diff --git a/arch/e2k/include/uapi/asm/setup.h b/arch/e2k/include/uapi/asm/setup.h deleted file mode 100644 index 7b4ae51..0000000 --- a/arch/e2k/include/uapi/asm/setup.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _UAPI_ASM_E2K_SETUP_H -#define _UAPI_ASM_E2K_SETUP_H - -#define COMMAND_LINE_SIZE 512 - -#endif /* _UAPI_ASM_E2K_SETUP_H */ diff --git a/arch/e2k/include/uapi/asm/shmbuf.h b/arch/e2k/include/uapi/asm/shmbuf.h deleted file mode 100644 index c4bbaf6..0000000 --- a/arch/e2k/include/uapi/asm/shmbuf.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _E2K_SHMBUF_H_ -#define _E2K_SHMBUF_H_ - -/* - * The shmid64_ds structure for E2K architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 2 miscellaneous 64-bit values - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_time_t shm_atime; /* last attach time */ - __kernel_time_t shm_dtime; /* last detach time */ - __kernel_time_t shm_ctime; /* last change time */ - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused1; - unsigned long __unused2; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _E2K_SHMBUF_H_ */ diff --git a/arch/e2k/include/uapi/asm/siginfo.h b/arch/e2k/include/uapi/asm/siginfo.h index ddc8b3f..765901b 100644 --- a/arch/e2k/include/uapi/asm/siginfo.h +++ b/arch/e2k/include/uapi/asm/siginfo.h @@ -4,7 +4,6 @@ #include #include -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #define __ARCH_SI_TRAPNO #define __ARCH_SI_BAND_T int @@ -13,13 +12,6 @@ #define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) #define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3) -/* - * SIGSEGV si_codes - */ -#define SEGV_BOUNDS 3 /* Bounds overflow */ -#undef NSIGSEGV -#define NSIGSEGV 3 - /* * SIGTRAP si_codes */ diff --git a/arch/e2k/include/uapi/asm/socket.h b/arch/e2k/include/uapi/asm/socket.h deleted file mode 100644 index 6b71384..0000000 --- a/arch/e2k/include/uapi/asm/socket.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/uapi/asm/sockios.h b/arch/e2k/include/uapi/asm/sockios.h deleted file mode 100644 index def6d47..0000000 --- a/arch/e2k/include/uapi/asm/sockios.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/e2k/include/uapi/asm/statfs.h b/arch/e2k/include/uapi/asm/statfs.h deleted file mode 100644 index 8f2a792..0000000 --- a/arch/e2k/include/uapi/asm/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _E2K_STATFS_H_ -#define _E2K_STATFS_H_ - -#include - -#endif /* _E2K_STATFS_H_ */ diff --git a/arch/e2k/include/uapi/asm/termbits.h b/arch/e2k/include/uapi/asm/termbits.h deleted file mode 100644 index 8484205..0000000 --- a/arch/e2k/include/uapi/asm/termbits.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _E2K_TERMBITS_H_ -#define _E2K_TERMBITS_H_ - -#include - -#endif /* _E2K_TERMBITS_H_ */ diff --git a/arch/e2k/include/uapi/asm/termios.h b/arch/e2k/include/uapi/asm/termios.h deleted file mode 100644 index 8b3d2b0..0000000 --- a/arch/e2k/include/uapi/asm/termios.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _E2K_TERMIOS_H_ -#define _E2K_TERMIOS_H_ - -#include - -#endif /* _E2K_TERMIOS_H_ */ diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 233a72f..e1de0fe 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -59,11 +59,11 @@ struct acpi_exception_info { #define AE_OK (acpi_status) 0x0000 -#define ACPI_ENV_EXCEPTION(status) (status & AE_CODE_ENVIRONMENTAL) -#define ACPI_AML_EXCEPTION(status) (status & AE_CODE_AML) -#define ACPI_PROG_EXCEPTION(status) (status & AE_CODE_PROGRAMMER) -#define ACPI_TABLE_EXCEPTION(status) (status & AE_CODE_ACPI_TABLES) -#define ACPI_CNTL_EXCEPTION(status) (status & AE_CODE_CONTROL) +#define ACPI_ENV_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_ENVIRONMENTAL) +#define ACPI_AML_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_AML) +#define ACPI_PROG_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_PROGRAMMER) +#define ACPI_TABLE_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_ACPI_TABLES) +#define ACPI_CNTL_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_CONTROL) /* * Environmental exceptions diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index defed62..1e5ae3b 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -232,6 +232,7 @@ struct acpi_pnp_type { struct acpi_device_pnp { acpi_bus_id bus_id; /* Object name */ + int instance_no; /* Instance number of this object */ struct acpi_pnp_type type; /* ID type */ acpi_bus_address bus_address; /* _ADR */ char *unique_id; /* _UID */ @@ -680,7 +681,8 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv); static inline void acpi_dev_put(struct acpi_device *adev) { - put_device(&adev->dev); + if (adev) + put_device(&adev->dev); } #else /* CONFIG_ACPI */ diff --git a/include/asm-generic/bitops/atomic.h b/include/asm-generic/bitops/atomic.h index dd90c97..0e7316a 100644 --- a/include/asm-generic/bitops/atomic.h +++ b/include/asm-generic/bitops/atomic.h @@ -11,19 +11,19 @@ * See Documentation/atomic_bitops.txt for details. */ -static inline void set_bit(unsigned int nr, volatile unsigned long *p) +static __always_inline void set_bit(unsigned int nr, volatile unsigned long *p) { p += BIT_WORD(nr); atomic_long_or(BIT_MASK(nr), (atomic_long_t *)p); } -static inline void clear_bit(unsigned int nr, volatile unsigned long *p) +static __always_inline void clear_bit(unsigned int nr, volatile unsigned long *p) { p += BIT_WORD(nr); atomic_long_andnot(BIT_MASK(nr), (atomic_long_t *)p); } -static inline void change_bit(unsigned int nr, volatile unsigned long *p) +static __always_inline void change_bit(unsigned int nr, volatile unsigned long *p) { p += BIT_WORD(nr); atomic_long_xor(BIT_MASK(nr), (atomic_long_t *)p); diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index d1779d4..66397ed 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -53,6 +53,9 @@ extern char __ctors_start[], __ctors_end[]; /* Start and end of .opd section - used for function descriptors. */ extern char __start_opd[], __end_opd[]; +/* Start and end of instrumentation protected text section */ +extern char __noinstr_text_start[], __noinstr_text_end[]; + extern __visible const void __nosave_begin, __nosave_end; /* Function descriptor handling (if any). Override in asm/sections.h */ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 130f16c..8a5ced9 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -396,7 +396,7 @@ } \ \ /* Built-in firmware blobs */ \ - .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \ + .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) ALIGN(8) { \ __start_builtin_fw = .; \ KEEP(*(.builtin_fw)) \ __end_builtin_fw = .; \ @@ -510,6 +510,15 @@ #define RODATA RO_DATA_SECTION(4096) #define RO_DATA(align) RO_DATA_SECTION(align) +/* + * Non-instrumentable text section + */ +#define NOINSTR_TEXT \ + ALIGN_FUNCTION(); \ + __noinstr_text_start = .; \ + *(.noinstr.text) \ + __noinstr_text_end = .; + /* * .text section. Map to function alignment to avoid address changes * during second ld run in second ld pass when generating System.map @@ -524,8 +533,10 @@ *(TEXT_MAIN .text.fixup) \ *(.text.unlikely .text.unlikely.*) \ *(.text.unknown .text.unknown.*) \ + NOINSTR_TEXT \ *(.text..refcount) \ *(.ref.text) \ + *(.text.asan.* .text.tsan.*) \ MEM_KEEP(init.text*) \ MEM_KEEP(exit.text*) \ @@ -746,8 +757,13 @@ /* DWARF 4 */ \ .debug_types 0 : { *(.debug_types) } \ /* DWARF 5 */ \ + .debug_addr 0 : { *(.debug_addr) } \ + .debug_line_str 0 : { *(.debug_line_str) } \ + .debug_loclists 0 : { *(.debug_loclists) } \ .debug_macro 0 : { *(.debug_macro) } \ - .debug_addr 0 : { *(.debug_addr) } + .debug_names 0 : { *(.debug_names) } \ + .debug_rnglists 0 : { *(.debug_rnglists) } \ + .debug_str_offsets 0 : { *(.debug_str_offsets) } /* Stabs debugging sections. */ #define STABS_DEBUG \ @@ -867,6 +883,7 @@ #ifdef CONFIG_AMD_MEM_ENCRYPT #define PERCPU_DECRYPTED_SECTION \ . = ALIGN(PAGE_SIZE); \ + *(.data..decrypted) \ *(.data..percpu..decrypted) \ . = ALIGN(PAGE_SIZE); #else diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h index d873f99..3a801a7 100644 --- a/include/crypto/acompress.h +++ b/include/crypto/acompress.h @@ -147,6 +147,8 @@ static inline struct crypto_acomp *crypto_acomp_reqtfm(struct acomp_req *req) * crypto_free_acomp() -- free ACOMPRESS tfm handle * * @tfm: ACOMPRESS tfm handle allocated with crypto_alloc_acomp() + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_acomp(struct crypto_acomp *tfm) { diff --git a/include/crypto/aead.h b/include/crypto/aead.h index 3c245b1..3b870b4 100644 --- a/include/crypto/aead.h +++ b/include/crypto/aead.h @@ -179,6 +179,8 @@ static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm) /** * crypto_free_aead() - zeroize and free aead handle * @tfm: cipher handle to be freed + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_aead(struct crypto_aead *tfm) { diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h index 6924b09..8913b42 100644 --- a/include/crypto/akcipher.h +++ b/include/crypto/akcipher.h @@ -174,6 +174,8 @@ static inline struct crypto_akcipher *crypto_akcipher_reqtfm( * crypto_free_akcipher() - free AKCIPHER tfm handle * * @tfm: AKCIPHER tfm handle allocated with crypto_alloc_akcipher() + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_akcipher(struct crypto_akcipher *tfm) { diff --git a/include/crypto/cast6.h b/include/crypto/cast6.h index c71f6ef..4c8d0c7 100644 --- a/include/crypto/cast6.h +++ b/include/crypto/cast6.h @@ -19,7 +19,7 @@ int __cast6_setkey(struct cast6_ctx *ctx, const u8 *key, unsigned int keylen, u32 *flags); int cast6_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen); -void __cast6_encrypt(struct cast6_ctx *ctx, u8 *dst, const u8 *src); -void __cast6_decrypt(struct cast6_ctx *ctx, u8 *dst, const u8 *src); +void __cast6_encrypt(const void *ctx, u8 *dst, const u8 *src); +void __cast6_decrypt(const void *ctx, u8 *dst, const u8 *src); #endif diff --git a/include/crypto/hash.h b/include/crypto/hash.h index d52b95b..e993c6b 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -141,7 +141,7 @@ struct ahash_alg { struct shash_desc { struct crypto_shash *tfm; - void *__ctx[] CRYPTO_MINALIGN_ATTR; + void *__ctx[] __aligned(ARCH_SLAB_MINALIGN); }; #define HASH_MAX_DIGESTSIZE 64 @@ -154,9 +154,9 @@ struct shash_desc { #define HASH_MAX_STATESIZE 512 -#define SHASH_DESC_ON_STACK(shash, ctx) \ - char __##shash##_desc[sizeof(struct shash_desc) + \ - HASH_MAX_DESCSIZE] CRYPTO_MINALIGN_ATTR; \ +#define SHASH_DESC_ON_STACK(shash, ctx) \ + char __##shash##_desc[sizeof(struct shash_desc) + HASH_MAX_DESCSIZE] \ + __aligned(__alignof__(struct shash_desc)); \ struct shash_desc *shash = (struct shash_desc *)__##shash##_desc /** @@ -260,6 +260,8 @@ static inline struct crypto_tfm *crypto_ahash_tfm(struct crypto_ahash *tfm) /** * crypto_free_ahash() - zeroize and free the ahash handle * @tfm: cipher handle to be freed + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_ahash(struct crypto_ahash *tfm) { @@ -703,6 +705,8 @@ static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm) /** * crypto_free_shash() - zeroize and free the message digest handle * @tfm: cipher handle to be freed + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_shash(struct crypto_shash *tfm) { diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index bfc9db7..9cc7f1c 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -77,13 +77,7 @@ int ahash_register_instance(struct crypto_template *tmpl, struct ahash_instance *inst); void ahash_free_instance(struct crypto_instance *inst); -int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, - unsigned int keylen); - -static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) -{ - return alg->setkey != shash_no_setkey; -} +bool crypto_shash_alg_has_setkey(struct shash_alg *alg); bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg); diff --git a/include/crypto/kpp.h b/include/crypto/kpp.h index cd9a9b5..19a2ead 100644 --- a/include/crypto/kpp.h +++ b/include/crypto/kpp.h @@ -154,6 +154,8 @@ static inline void crypto_kpp_set_flags(struct crypto_kpp *tfm, u32 flags) * crypto_free_kpp() - free KPP tfm handle * * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_kpp(struct crypto_kpp *tfm) { diff --git a/include/crypto/rng.h b/include/crypto/rng.h index 8b4b844..17bb367 100644 --- a/include/crypto/rng.h +++ b/include/crypto/rng.h @@ -111,6 +111,8 @@ static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm) /** * crypto_free_rng() - zeroize and free RNG handle * @tfm: cipher handle to be freed + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_rng(struct crypto_rng *tfm) { diff --git a/include/crypto/serpent.h b/include/crypto/serpent.h index 7dd780c..75c7eaa 100644 --- a/include/crypto/serpent.h +++ b/include/crypto/serpent.h @@ -22,7 +22,7 @@ int __serpent_setkey(struct serpent_ctx *ctx, const u8 *key, unsigned int keylen); int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen); -void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src); -void __serpent_decrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src); +void __serpent_encrypt(const void *ctx, u8 *dst, const u8 *src); +void __serpent_decrypt(const void *ctx, u8 *dst, const u8 *src); #endif diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index aada879..0bce600 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -203,6 +203,8 @@ static inline struct crypto_tfm *crypto_skcipher_tfm( /** * crypto_free_skcipher() - zeroize and free cipher handle * @tfm: cipher handle to be freed + * + * If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_skcipher(struct crypto_skcipher *tfm) { diff --git a/include/crypto/xts.h b/include/crypto/xts.h index 75fd96f..15ae7fd 100644 --- a/include/crypto/xts.h +++ b/include/crypto/xts.h @@ -8,8 +8,6 @@ #define XTS_BLOCK_SIZE 16 -#define XTS_TWEAK_CAST(x) ((void (*)(void *, u8*, const u8*))(x)) - static inline int xts_check_key(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index c1a96fd..875e002 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -31,16 +31,37 @@ extern int restrict_link_by_builtin_and_secondary_trusted( #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted #endif +extern struct pkcs7_message *pkcs7; #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING extern int mark_hash_blacklisted(const char *hash); extern int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type); +extern int is_binary_blacklisted(const u8 *hash, size_t hash_len); #else static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type) { return 0; } + +static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len) +{ + return 0; +} +#endif + +#ifdef CONFIG_SYSTEM_REVOCATION_LIST +extern int add_key_to_revocation_list(const char *data, size_t size); +extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7); +#else +static inline int add_key_to_revocation_list(const char *data, size_t size) +{ + return 0; +} +static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7) +{ + return -ENOKEY; +} #endif #ifdef CONFIG_IMA_BLACKLIST_KEYRING diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dd61703..c708fd8 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -222,10 +222,14 @@ void __iomem *__acpi_map_table(unsigned long phys, unsigned long size); void __acpi_unmap_table(void __iomem *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); +void acpi_boot_table_prepare (void); void acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void); +int acpi_locate_initial_tables (void); +void acpi_reserve_initial_tables (void); +void acpi_table_init_complete (void); int acpi_table_init (void); int acpi_table_parse(char *id, acpi_tbl_table_handler handler); int __init acpi_table_parse_entries(char *id, unsigned long table_size, @@ -759,9 +763,12 @@ static inline int acpi_boot_init(void) return 0; } +static inline void acpi_boot_table_prepare(void) +{ +} + static inline void acpi_boot_table_init(void) { - return; } static inline int acpi_mps_check(void) diff --git a/include/linux/bio.h b/include/linux/bio.h index 853d92c..b0927b2 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -40,9 +40,6 @@ #define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter) #define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter) -#define bio_multiple_segments(bio) \ - ((bio)->bi_iter.bi_size != bio_iovec(bio).bv_len) - #define bvec_iter_sectors(iter) ((iter).bi_size >> 9) #define bvec_iter_end_sector(iter) ((iter).bi_sector + bvec_iter_sectors((iter))) @@ -246,7 +243,7 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit) static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv) { - *bv = bio_iovec(bio); + *bv = mp_bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); } static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv) @@ -254,10 +251,9 @@ static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv) struct bvec_iter iter = bio->bi_iter; int idx; - if (unlikely(!bio_multiple_segments(bio))) { - *bv = bio_iovec(bio); - return; - } + bio_get_first_bvec(bio, bv); + if (bv->bv_len == bio->bi_iter.bi_size) + return; /* this bio only has a single bvec */ bio_advance_iter(bio, &iter, iter.bi_size); diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 576f008..cb3c094 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -535,7 +535,7 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array, struct bpf_prog *include_prog, struct bpf_prog_array **new_array); -#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null) \ +#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null, set_cg_storage) \ ({ \ struct bpf_prog_array_item *_item; \ struct bpf_prog *_prog; \ @@ -548,7 +548,8 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array, goto _out; \ _item = &_array->items[0]; \ while ((_prog = READ_ONCE(_item->prog))) { \ - bpf_cgroup_storage_set(_item->cgroup_storage); \ + if (set_cg_storage) \ + bpf_cgroup_storage_set(_item->cgroup_storage); \ _ret &= func(_prog, ctx); \ _item++; \ } \ @@ -609,10 +610,10 @@ _out: \ }) #define BPF_PROG_RUN_ARRAY(array, ctx, func) \ - __BPF_PROG_RUN_ARRAY(array, ctx, func, false) + __BPF_PROG_RUN_ARRAY(array, ctx, func, false, true) #define BPF_PROG_RUN_ARRAY_CHECK(array, ctx, func) \ - __BPF_PROG_RUN_ARRAY(array, ctx, func, true) + __BPF_PROG_RUN_ARRAY(array, ctx, func, true, false) #ifdef CONFIG_BPF_SYSCALL DECLARE_PER_CPU(int, bpf_prog_active); @@ -741,7 +742,10 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size) /* verify correctness of eBPF program */ int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, union bpf_attr __user *uattr); + +#ifndef CONFIG_BPF_JIT_ALWAYS_ON void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth); +#endif /* Map specifics */ struct xdp_buff; diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 81c7ea8..22f0700 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -281,10 +281,11 @@ struct bpf_verifier_state_list { }; /* Possible states for alu_state member. */ -#define BPF_ALU_SANITIZE_SRC 1U -#define BPF_ALU_SANITIZE_DST 2U +#define BPF_ALU_SANITIZE_SRC (1U << 0) +#define BPF_ALU_SANITIZE_DST (1U << 1) #define BPF_ALU_NEG_VALUE (1U << 2) #define BPF_ALU_NON_POINTER (1U << 3) +#define BPF_ALU_IMMEDIATE (1U << 4) #define BPF_ALU_SANITIZE (BPF_ALU_SANITIZE_SRC | \ BPF_ALU_SANITIZE_DST) diff --git a/include/linux/can/can-ml.h b/include/linux/can/can-ml.h index 2f5d731..8afa92d 100644 --- a/include/linux/can/can-ml.h +++ b/include/linux/can/can-ml.h @@ -44,6 +44,7 @@ #include #include +#include #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS) #define CAN_EFF_RCV_HASH_BITS 10 @@ -65,4 +66,15 @@ struct can_ml_priv { #endif }; +static inline struct can_ml_priv *can_get_ml_priv(struct net_device *dev) +{ + return netdev_get_ml_priv(dev, ML_PRIV_CAN); +} + +static inline void can_set_ml_priv(struct net_device *dev, + struct can_ml_priv *ml_priv) +{ + netdev_set_ml_priv(dev, ml_priv, ML_PRIV_CAN); +} + #endif /* CAN_ML_H */ diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index 0783b0c..1ef071e 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -49,8 +49,12 @@ static inline void can_skb_reserve(struct sk_buff *skb) static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) { - if (sk) { - sock_hold(sk); + /* If the socket has already been closed by user space, the + * refcount may already be 0 (and the socket will be freed + * after the last TX skb has been freed). So only increase + * socket refcount if the refcount is > 0. + */ + if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { skb->destructor = sock_efree; skb->sk = sk; } diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 88bb4bd..f4992d6 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -14,6 +14,12 @@ #if GCC_VERSION < 40600 # error Sorry, your compiler is too old - please upgrade it. +#elif defined(CONFIG_ARM64) && GCC_VERSION < 50100 +/* + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293 + * https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk + */ +# error Sorry, your version of GCC is too old - please use 5.1 or newer. #endif /* diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 223f9e2..558d4ec 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -153,12 +153,65 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, /* Annotate a C jump table to allow objtool to follow the code flow */ #define __annotate_jump_table __section(.rodata..c_jump_table) +#ifdef CONFIG_DEBUG_ENTRY +/* Begin/end of an instrumentation safe region */ +#define instrumentation_begin() ({ \ + asm volatile("%c0:\n\t" \ + ".pushsection .discard.instr_begin\n\t" \ + ".long %c0b - .\n\t" \ + ".popsection\n\t" : : "i" (__COUNTER__)); \ +}) + +/* + * Because instrumentation_{begin,end}() can nest, objtool validation considers + * _begin() a +1 and _end() a -1 and computes a sum over the instructions. + * When the value is greater than 0, we consider instrumentation allowed. + * + * There is a problem with code like: + * + * noinstr void foo() + * { + * instrumentation_begin(); + * ... + * if (cond) { + * instrumentation_begin(); + * ... + * instrumentation_end(); + * } + * bar(); + * instrumentation_end(); + * } + * + * If instrumentation_end() would be an empty label, like all the other + * annotations, the inner _end(), which is at the end of a conditional block, + * would land on the instruction after the block. + * + * If we then consider the sum of the !cond path, we'll see that the call to + * bar() is with a 0-value, even though, we meant it to happen with a positive + * value. + * + * To avoid this, have _end() be a NOP instruction, this ensures it will be + * part of the condition block and does not escape. + */ +#define instrumentation_end() ({ \ + asm volatile("%c0: nop\n\t" \ + ".pushsection .discard.instr_end\n\t" \ + ".long %c0b - .\n\t" \ + ".popsection\n\t" : : "i" (__COUNTER__)); \ +}) +#endif /* CONFIG_DEBUG_ENTRY */ + #else #define annotate_reachable() #define annotate_unreachable() #define __annotate_jump_table #endif +#ifndef instrumentation_begin +#define instrumentation_begin() do { } while(0) +#define instrumentation_end() do { } while(0) +#endif + #ifndef ASM_UNREACHABLE # define ASM_UNREACHABLE #endif diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 21281bc..593e5f3 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -127,6 +127,10 @@ struct ftrace_likely_data { #endif /* CONFIG_KVM_HOST_KERNEL */ #endif /* CONFIG_MCST */ +/* Section for code which can't be instrumented at all */ +#define noinstr \ + noinline notrace __attribute((__section__(".noinstr.text"))) + /* * it doesn't make sense on ARM (currently the only user of __naked) * to trace naked functions because then mcount is called without diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 24d4c16..717f51e 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -62,6 +62,7 @@ struct vc_data { unsigned int vc_rows; unsigned int vc_size_row; /* Bytes per row */ unsigned int vc_scan_lines; /* # of scan lines */ + unsigned int vc_cell_height; /* CRTC character cell height */ unsigned long vc_origin; /* [!] Start of real screen */ unsigned long vc_scr_end; /* [!] End of real screen */ unsigned long vc_visible_origin; /* [!] Top of visible window */ diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 2d55cee..bd1f235 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -119,6 +119,7 @@ enum cpuhp_state { CPUHP_AP_ARM_L2X0_STARTING, CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, CPUHP_AP_ARM_ARCH_TIMER_STARTING, + CPUHP_AP_OMAP_DM_TIMER_STARTING, CPUHP_AP_ARM_GLOBAL_TIMER_STARTING, CPUHP_AP_JCORE_TIMER_STARTING, CPUHP_AP_ARM_TWD_STARTING, diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 19ea3a3..0c720a2 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -130,9 +130,12 @@ * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual * declaration) is used to ensure that the crypto_tfm context structure is * aligned correctly for the given architecture so that there are no alignment - * faults for C data types. In particular, this is required on platforms such - * as arm where pointers are 32-bit aligned but there are data types such as - * u64 which require 64-bit alignment. + * faults for C data types. On architectures that support non-cache coherent + * DMA, such as ARM or arm64, it also takes into account the minimal alignment + * that is required to ensure that the context struct member does not share any + * cachelines with the rest of the struct. This is needed to ensure that cache + * maintenance for non-coherent DMA (cache invalidation in particular) does not + * affect data that may be accessed by the CPU concurrently. */ #define CRYPTO_MINALIGN ARCH_KMALLOC_MINALIGN diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index e4e1f5c..a53d7d2 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -316,6 +316,11 @@ struct dm_target { * whether or not its underlying devices have support. */ bool discards_supported:1; + + /* + * Set if we need to limit the number of in-flight bios when swapping. + */ + bool limit_swap_bios:1; }; /* Each target can link one of these into the table */ diff --git a/include/linux/device.h b/include/linux/device.h index 297239a..3414b5a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1260,6 +1260,7 @@ struct device { struct dev_pin_info *pins; #endif #ifdef CONFIG_GENERIC_MSI_IRQ + raw_spinlock_t msi_lock; struct list_head msi_list; #endif diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h index eec7928..99580c2 100644 --- a/include/linux/eeprom_93xx46.h +++ b/include/linux/eeprom_93xx46.h @@ -16,6 +16,8 @@ struct eeprom_93xx46_platform_data { #define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) /* Instructions such as EWEN are (addrlen + 2) in length. */ #define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) +/* Add extra cycle after address during a read */ +#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2) /* * optional hooks to control additional logic diff --git a/include/linux/efi.h b/include/linux/efi.h index 13ed2c6..c82ef0e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -63,8 +63,10 @@ typedef void *efi_handle_t; */ typedef guid_t efi_guid_t __aligned(__alignof__(u32)); -#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ - GUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) +#define EFI_GUID(a, b, c, d...) (efi_guid_t){ { \ + (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, d } } /* * Generic EFI table header diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 901bda3..7b4d5fa 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -34,7 +34,7 @@ struct elevator_mq_ops { void (*depth_updated)(struct blk_mq_hw_ctx *); bool (*allow_merge)(struct request_queue *, struct request *, struct bio *); - bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *, unsigned int); + bool (*bio_merge)(struct request_queue *, struct bio *, unsigned int); int (*request_merge)(struct request_queue *q, struct request **, struct bio *); void (*request_merged)(struct request_queue *, struct request *, enum elv_merge); void (*requests_merged)(struct request_queue *, struct request *, struct request *); diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index 9da9d4e..5576038 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -58,6 +58,7 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregse } #endif +#if defined(CONFIG_UM) || defined(CONFIG_IA64) || defined(CONFIG_E2K) /* * These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out * extra segments containing the gate DSO contents. Dumping its @@ -71,10 +72,31 @@ extern int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset); extern int elf_core_write_extra_data(struct coredump_params *cprm); -#ifndef CONFIG_E2K +# ifndef CONFIG_E2K extern size_t elf_core_extra_data_size(void); -#else +# else extern size_t elf_core_extra_data_size(struct coredump_params *cprm); -#endif /* CONFIG_E2K */ +# endif /* CONFIG_E2K */ +#else +static inline Elf_Half elf_core_extra_phdrs(void) +{ + return 0; +} + +static inline int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset) +{ + return 1; +} + +static inline int elf_core_write_extra_data(struct coredump_params *cprm) +{ + return 1; +} + +static inline size_t elf_core_extra_data_size(void) +{ + return 0; +} +#endif #endif /* _LINUX_ELFCORE_H */ diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 2bdf643..47d3e19 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -271,6 +271,29 @@ static inline void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb) { } +static inline int extcon_register_notifier_all(struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline int extcon_unregister_notifier_all(struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline int devm_extcon_register_notifier_all(struct device *dev, + struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline void devm_extcon_unregister_notifier_all(struct device *dev, + struct extcon_dev *edev, + struct notifier_block *nb) { } + static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) { return ERR_PTR(-ENODEV); diff --git a/include/linux/filter.h b/include/linux/filter.h index c466b3b..81ece78 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -867,7 +867,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp); u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); #define __bpf_call_base_args \ ((u64 (*)(u64, u64, u64, u64, u64, const struct bpf_insn *)) \ - __bpf_call_base) + (void *)__bpf_call_base) struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog); void bpf_jit_compile(struct bpf_prog *prog); diff --git a/include/linux/fs.h b/include/linux/fs.h index 0c4cf54..17a1477 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2170,7 +2170,6 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) #define I_DIO_WAKEUP (1 << __I_DIO_WAKEUP) #define I_LINKABLE (1 << 10) #define I_DIRTY_TIME (1 << 11) -#define I_DIRTY_TIME_EXPIRED (1 << 12) #define I_WB_SWITCH (1 << 13) #define I_OVL_INUSE (1 << 14) #define I_CREATING (1 << 15) diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h index e5c14e2..ba8a587 100644 --- a/include/linux/fs_context.h +++ b/include/linux/fs_context.h @@ -134,6 +134,7 @@ extern int vfs_parse_fs_string(struct fs_context *fc, const char *key, extern int generic_parse_monolithic(struct fs_context *fc, void *data); extern int vfs_get_tree(struct fs_context *fc); extern void put_fs_context(struct fs_context *fc); +extern void fc_drop_locked(struct fs_context *fc); /* * sget() wrappers to be called from the ->get_tree() op. diff --git a/include/linux/hid.h b/include/linux/hid.h index c7044a1..85bedeb 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -261,6 +261,8 @@ struct hid_item { #define HID_CP_SELECTION 0x000c0080 #define HID_CP_MEDIASELECTION 0x000c0087 #define HID_CP_SELECTDISC 0x000c00ba +#define HID_CP_VOLUMEUP 0x000c00e9 +#define HID_CP_VOLUMEDOWN 0x000c00ea #define HID_CP_PLAYBACKSPEED 0x000c00f1 #define HID_CP_PROXIMITY 0x000c0109 #define HID_CP_SPEAKERSYSTEM 0x000c0160 @@ -1152,8 +1154,7 @@ static inline void hid_hw_wait(struct hid_device *hdev) */ static inline u32 hid_report_len(struct hid_report *report) { - /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ - return ((report->size - 1) >> 3) + 1 + (report->id > 0); + return DIV_ROUND_UP(report->size, 8) + (report->id > 0); } int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 93d5cf0..d2dbe46 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -231,6 +231,19 @@ static inline spinlock_t *pud_trans_huge_lock(pud_t *pud, else return NULL; } + +/** + * thp_order - Order of a transparent huge page. + * @page: Head page of a transparent huge page. + */ +static inline unsigned int thp_order(struct page *page) +{ + VM_BUG_ON_PGFLAGS(PageTail(page), page); + if (PageHead(page)) + return HPAGE_PMD_ORDER; + return 0; +} + static inline int hpage_nr_pages(struct page *page) { if (unlikely(PageTransHuge(page))) @@ -246,6 +259,7 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, extern vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd); extern struct page *huge_zero_page; +extern unsigned long huge_zero_pfn; static inline bool is_huge_zero_page(struct page *page) { @@ -254,7 +268,7 @@ static inline bool is_huge_zero_page(struct page *page) static inline bool is_huge_zero_pmd(pmd_t pmd) { - return is_huge_zero_page(pmd_page(pmd)); + return READ_ONCE(huge_zero_pfn) == pmd_pfn(pmd) && pmd_present(pmd); } static inline bool is_huge_zero_pud(pud_t pud) @@ -290,6 +304,12 @@ static inline struct list_head *page_deferred_list(struct page *page) #define HPAGE_PUD_MASK ({ BUILD_BUG(); 0; }) #define HPAGE_PUD_SIZE ({ BUILD_BUG(); 0; }) +static inline unsigned int thp_order(struct page *page) +{ + VM_BUG_ON_PGFLAGS(PageTail(page), page); + return 0; +} + #define hpage_nr_pages(x) 1 static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma) @@ -379,6 +399,11 @@ static inline bool is_huge_zero_page(struct page *page) return false; } +static inline bool is_huge_zero_pmd(pmd_t pmd) +{ + return false; +} + static inline bool is_huge_zero_pud(pud_t pud) { return false; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 8a03f39..a0513c4 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -106,7 +106,7 @@ void free_huge_page(struct page *page); void hugetlb_fix_reserve_counts(struct inode *inode); extern struct mutex *hugetlb_fault_mutex_table; u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping, - pgoff_t idx, unsigned long address); + pgoff_t idx); pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud); @@ -469,17 +469,6 @@ static inline int hstate_index(struct hstate *h) return h - hstates; } -pgoff_t __basepage_index(struct page *page); - -/* Return page->index in PAGE_SIZE units */ -static inline pgoff_t basepage_index(struct page *page) -{ - if (!PageCompound(page)) - return page->index; - - return __basepage_index(page); -} - extern int dissolve_free_huge_page(struct page *page); extern int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn); @@ -590,6 +579,8 @@ static inline void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, } #endif +void set_page_huge_active(struct page *page); + #else /* CONFIG_HUGETLB_PAGE */ struct hstate {}; @@ -693,11 +684,6 @@ static inline int hstate_index(struct hstate *h) return 0; } -static inline pgoff_t basepage_index(struct page *page) -{ - return page->index; -} - static inline int dissolve_free_huge_page(struct page *page) { return 0; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 1361637..af2b799 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -677,6 +677,8 @@ struct i2c_adapter_quirks { #define I2C_AQ_NO_ZERO_LEN_READ BIT(5) #define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6) #define I2C_AQ_NO_ZERO_LEN (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE) +/* adapter cannot do repeated START */ +#define I2C_AQ_NO_REP_START BIT(7) /* * i2c_adapter is the structure used to identify a physical i2c bus along diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index a8f8889..0be0d68 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -3,6 +3,7 @@ #define _LINUX_ICMPV6_H #include +#include #include static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) @@ -13,21 +14,64 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) #include #if IS_ENABLED(CONFIG_IPV6) -extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, - const struct in6_addr *force_saddr); + const struct in6_addr *force_saddr, + const struct inet6_skb_parm *parm); +void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct in6_addr *force_saddr, + const struct inet6_skb_parm *parm); +#if IS_BUILTIN(CONFIG_IPV6) +static inline void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct inet6_skb_parm *parm) +{ + icmp6_send(skb, type, code, info, NULL, parm); +} +static inline int inet6_register_icmp_sender(ip6_icmp_send_t *fn) +{ + BUILD_BUG_ON(fn != icmp6_send); + return 0; +} +static inline int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) +{ + BUILD_BUG_ON(fn != icmp6_send); + return 0; +} +#else +extern void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct inet6_skb_parm *parm); extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); +#endif + +static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +{ + __icmpv6_send(skb, type, code, info, IP6CB(skb)); +} + int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, unsigned int data_len); +#if IS_ENABLED(CONFIG_NF_NAT) +void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); +#else +static inline void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info) +{ + struct inet6_skb_parm parm = { 0 }; + __icmpv6_send(skb_in, type, code, info, &parm); +} +#endif + #else static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) { +} +static inline void icmpv6_ndo_send(struct sk_buff *skb, + u8 type, u8 code, __u32 info) +{ } #endif diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index a367ead..e115559 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -42,13 +42,14 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, if (likely(success)) { struct vlan_pcpu_stats *pcpu_stats; - pcpu_stats = this_cpu_ptr(vlan->pcpu_stats); + pcpu_stats = get_cpu_ptr(vlan->pcpu_stats); u64_stats_update_begin(&pcpu_stats->syncp); pcpu_stats->rx_packets++; pcpu_stats->rx_bytes += len; if (multicast) pcpu_stats->rx_multicast++; u64_stats_update_end(&pcpu_stats->syncp); + put_cpu_ptr(vlan->pcpu_stats); } else { this_cpu_inc(vlan->pcpu_stats->rx_errors); } diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index bb331e6..a321531 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -68,7 +68,7 @@ struct cros_ec_sensors_core_state { u16 scale; } calib[CROS_EC_SENSOR_MAX_AXIS]; s8 sign[CROS_EC_SENSOR_MAX_AXIS]; - u8 samples[CROS_EC_SAMPLE_SIZE]; + u8 samples[CROS_EC_SAMPLE_SIZE] __aligned(8); int (*read_ec_sensors_data)(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 3515ca6..b68fca0 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -41,7 +41,7 @@ struct in_device { unsigned long mr_qri; /* Query Response Interval */ unsigned char mr_qrv; /* Query Robustness Variable */ unsigned char mr_gq_running; - unsigned char mr_ifc_count; + u32 mr_ifc_count; struct timer_list mr_gq_timer; /* general query timer */ struct timer_list mr_ifc_timer; /* interface change timer */ diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 6b559d2..88ac8ed 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -556,6 +556,8 @@ struct intel_iommu { struct iommu_device iommu; /* IOMMU core code handle */ int node; u32 flags; /* Software defined flags */ + + struct dmar_drhd_unit *drhd; }; /* PCI domain-device relationship */ diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 7aa5d61..53b16f1 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -139,6 +139,7 @@ loff_t iomap_apply(struct inode *inode, loff_t pos, loff_t length, struct iomap_page { atomic_t read_count; atomic_t write_count; + spinlock_t uptodate_lock; DECLARE_BITMAP(uptodate, PAGE_SIZE / 512); }; diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index ea7c790..bbe297b 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -83,7 +83,6 @@ struct ipv6_params { __s32 autoconf; }; extern struct ipv6_params ipv6_defaults; -#include #include #include diff --git a/include/linux/irq.h b/include/linux/irq.h index e9e69c5..5655da9 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -542,6 +542,7 @@ struct irq_chip { * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode * IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs * IRQCHIP_SUPPORTS_NMI: Chip can deliver NMIs, only for root irqchips + * IRQCHIP_AFFINITY_PRE_STARTUP: Default affinity update before startup */ enum { IRQCHIP_SET_TYPE_MASKED = (1 << 0), @@ -553,6 +554,7 @@ enum { IRQCHIP_EOI_THREADED = (1 << 6), IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7), IRQCHIP_SUPPORTS_NMI = (1 << 8), + IRQCHIP_AFFINITY_PRE_STARTUP = (1 << 10), }; #include diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 1776eb2..a1cffce 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -293,6 +293,11 @@ struct kimage { /* Information for loading purgatory */ struct purgatory_info purgatory_info; #endif + +#ifdef CONFIG_IMA_KEXEC + /* Virtual address of IMA measurement buffer for kexec syscall */ + void *ima_buffer; +#endif }; /* kexec interface functions */ diff --git a/include/linux/key.h b/include/linux/key.h index 6cf8e71..9c26cc9 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -269,6 +269,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_BUILT_IN 0x0004 /* Key is built into kernel */ #define KEY_ALLOC_BYPASS_RESTRICTION 0x0008 /* Override the check on restricted keyrings */ #define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ +#define KEY_ALLOC_SET_KEEP 0x0020 /* Set the KEEP flag on the key/keyring */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index a604888..a121fd8 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -232,7 +232,7 @@ extern void kprobes_inc_nmissed_count(struct kprobe *p); extern bool arch_within_kprobe_blacklist(unsigned long addr); extern int arch_populate_kprobe_blacklist(void); extern bool arch_kprobe_on_func_entry(unsigned long offset); -extern bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); +extern int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); extern bool within_kprobe_blacklist(unsigned long addr); extern int kprobe_add_ksym_blacklist(unsigned long entry); diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 09be688..81516d0 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -35,6 +35,9 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), unsigned int cpu, const char *namefmt); +void kthread_set_per_cpu(struct task_struct *k, int cpu); +bool kthread_is_per_cpu(struct task_struct *k); + /** * kthread_run - create and wake a thread. * @threadfn: the function to run until signal_pending(current). diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index d7601f9..ec8110c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -192,8 +192,8 @@ int kvm_io_bus_read(struct kvm_vcpu *vcpu, enum kvm_bus bus_idx, gpa_t addr, int len, void *val); int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, struct kvm_io_device *dev); -void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, - struct kvm_io_device *dev); +int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, + struct kvm_io_device *dev); struct kvm_io_device *kvm_io_bus_get_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr); @@ -1053,7 +1053,15 @@ __gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn) static inline unsigned long __gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn) { - return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE; + /* + * The index was checked originally in search_memslots. To avoid + * that a malicious guest builds a Spectre gadget out of e.g. page + * table walks, do not let the processor speculate loads outside + * the guest's registered memslots. + */ + unsigned long offset = gfn - slot->base_gfn; + offset = array_index_nospec(offset, slot->npages); + return slot->userspace_addr + offset * PAGE_SIZE; } static inline int memslot_id(struct kvm *kvm, gfn_t gfn) diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index af6b11d..1847a07 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -23,11 +23,12 @@ #define MARVELL_PHY_ID_88X3310 0x002b09a0 #define MARVELL_PHY_ID_88E2110 0x002b09b0 -/* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do +/* These Ethernet switch families contain embedded PHYs, but they do * not have a model ID. So the switch driver traps reads to the ID2 * register and returns the switch family ID */ -#define MARVELL_PHY_ID_88E6390 0x01410f90 +#define MARVELL_PHY_ID_88E6341_FAMILY 0x01410f41 +#define MARVELL_PHY_ID_88E6390_FAMILY 0x01410f90 #define MARVELL_PHY_FAMILY_ID(id) ((id) >> 4) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index fb5b2a4..b6d0b68 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -356,17 +356,54 @@ static inline bool mem_cgroup_disabled(void) return !cgroup_subsys_enabled(memory_cgrp_subsys); } -static inline unsigned long mem_cgroup_protection(struct mem_cgroup *memcg, - bool in_low_reclaim) +static inline void mem_cgroup_protection(struct mem_cgroup *root, + struct mem_cgroup *memcg, + unsigned long *min, + unsigned long *low) { + *min = *low = 0; + if (mem_cgroup_disabled()) - return 0; + return; - if (in_low_reclaim) - return READ_ONCE(memcg->memory.emin); + /* + * There is no reclaim protection applied to a targeted reclaim. + * We are special casing this specific case here because + * mem_cgroup_protected calculation is not robust enough to keep + * the protection invariant for calculated effective values for + * parallel reclaimers with different reclaim target. This is + * especially a problem for tail memcgs (as they have pages on LRU) + * which would want to have effective values 0 for targeted reclaim + * but a different value for external reclaim. + * + * Example + * Let's have global and A's reclaim in parallel: + * | + * A (low=2G, usage = 3G, max = 3G, children_low_usage = 1.5G) + * |\ + * | C (low = 1G, usage = 2.5G) + * B (low = 1G, usage = 0.5G) + * + * For the global reclaim + * A.elow = A.low + * B.elow = min(B.usage, B.low) because children_low_usage <= A.elow + * C.elow = min(C.usage, C.low) + * + * With the effective values resetting we have A reclaim + * A.elow = 0 + * B.elow = B.low + * C.elow = C.low + * + * If the global reclaim races with A's reclaim then + * B.elow = C.elow = 0 because children_low_usage > A.elow) + * is possible and reclaiming B would be violating the protection. + * + */ + if (root == memcg) + return; - return max(READ_ONCE(memcg->memory.emin), - READ_ONCE(memcg->memory.elow)); + *min = READ_ONCE(memcg->memory.emin); + *low = READ_ONCE(memcg->memory.elow); } enum mem_cgroup_protection mem_cgroup_protected(struct mem_cgroup *root, @@ -847,10 +884,12 @@ static inline void memcg_memory_event_mm(struct mm_struct *mm, { } -static inline unsigned long mem_cgroup_protection(struct mem_cgroup *memcg, - bool in_low_reclaim) +static inline void mem_cgroup_protection(struct mem_cgroup *root, + struct mem_cgroup *memcg, + unsigned long *min, + unsigned long *low) { - return 0; + *min = *low = 0; } static inline enum mem_cgroup_protection mem_cgroup_protected( diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h index 9b97d28..bc3819d 100644 --- a/include/linux/mfd/abx500/ux500_chargalg.h +++ b/include/linux/mfd/abx500/ux500_chargalg.h @@ -15,7 +15,7 @@ * - POWER_SUPPLY_TYPE_USB, * because only them store as drv_data pointer to struct ux500_charger. */ -#define psy_to_ux500_charger(x) power_supply_get_drvdata(psy) +#define psy_to_ux500_charger(x) power_supply_get_drvdata(x) /* Forward declaration */ struct ux500_charger; diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h index b0109ee..1c3014d 100644 --- a/include/linux/mfd/rohm-bd70528.h +++ b/include/linux/mfd/rohm-bd70528.h @@ -25,9 +25,7 @@ struct bd70528_data { struct mutex rtc_timer_lock; }; -#define BD70528_BUCK_VOLTS 17 -#define BD70528_BUCK_VOLTS 17 -#define BD70528_BUCK_VOLTS 17 +#define BD70528_BUCK_VOLTS 0x10 #define BD70528_LDO_VOLTS 0x20 #define BD70528_REG_BUCK1_EN 0x0F diff --git a/include/linux/mfd/rt5033-private.h b/include/linux/mfd/rt5033-private.h index f812105..f2271bf 100644 --- a/include/linux/mfd/rt5033-private.h +++ b/include/linux/mfd/rt5033-private.h @@ -200,13 +200,13 @@ enum rt5033_reg { #define RT5033_REGULATOR_BUCK_VOLTAGE_MIN 1000000U #define RT5033_REGULATOR_BUCK_VOLTAGE_MAX 3000000U #define RT5033_REGULATOR_BUCK_VOLTAGE_STEP 100000U -#define RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM 32 +#define RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM 21 /* RT5033 regulator LDO output voltage uV */ #define RT5033_REGULATOR_LDO_VOLTAGE_MIN 1200000U #define RT5033_REGULATOR_LDO_VOLTAGE_MAX 3000000U #define RT5033_REGULATOR_LDO_VOLTAGE_STEP 100000U -#define RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM 32 +#define RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM 19 /* RT5033 regulator SAFE LDO output voltage uV */ #define RT5033_REGULATOR_SAFE_LDO_VOLTAGE 4900000U diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 36e412c..35b4e32 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -632,6 +632,7 @@ struct mlx4_caps { bool wol_port[MLX4_MAX_PORTS + 1]; struct mlx4_rate_limit_caps rl_caps; u32 health_buffer_addrs; + bool map_clock_to_user; }; struct mlx4_buf_list { diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 75e5a7f..36516fe 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -415,11 +415,11 @@ struct mlx5_ifc_flow_table_prop_layout_bits { u8 reserved_at_60[0x18]; u8 log_max_ft_num[0x8]; - u8 reserved_at_80[0x18]; + u8 reserved_at_80[0x10]; + u8 log_max_flow_counter[0x8]; u8 log_max_destination[0x8]; - u8 log_max_flow_counter[0x8]; - u8 reserved_at_a8[0x10]; + u8 reserved_at_a0[0x18]; u8 log_max_flow[0x8]; u8 reserved_at_c0[0x40]; @@ -9669,7 +9669,7 @@ struct mlx5_ifc_pbmc_reg_bits { struct mlx5_ifc_bufferx_reg_bits buffer[10]; - u8 reserved_at_2e0[0x40]; + u8 reserved_at_2e0[0x80]; }; struct mlx5_ifc_qtct_reg_bits { diff --git a/include/linux/mlx5/transobj.h b/include/linux/mlx5/transobj.h index dc6b1e7..3abefd4 100644 --- a/include/linux/mlx5/transobj.h +++ b/include/linux/mlx5/transobj.h @@ -92,4 +92,5 @@ mlx5_core_hairpin_create(struct mlx5_core_dev *func_mdev, struct mlx5_hairpin_params *params); void mlx5_core_hairpin_destroy(struct mlx5_hairpin *pair); +void mlx5_core_hairpin_clear_dead_peer(struct mlx5_hairpin *hp); #endif /* __TRANSOBJ_H__ */ diff --git a/include/linux/mm.h b/include/linux/mm.h index e5ae4fd..6ca1460 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1235,13 +1235,26 @@ static inline bool cpupid_match_pid(struct task_struct *task, int cpupid) #endif /* CONFIG_NUMA_BALANCING */ #ifdef CONFIG_KASAN_SW_TAGS + +/* + * KASAN per-page tags are stored xor'ed with 0xff. This allows to avoid + * setting tags for all pages to native kernel tag value 0xff, as the default + * value 0x00 maps to 0xff. + */ + static inline u8 page_kasan_tag(const struct page *page) { - return (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK; + u8 tag; + + tag = (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK; + tag ^= 0xff; + + return tag; } static inline void page_kasan_tag_set(struct page *page, u8 tag) { + tag ^= 0xff; page->flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT); page->flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT; } @@ -1455,6 +1468,7 @@ struct zap_details { struct address_space *check_mapping; /* Check page->mapping if set */ pgoff_t first_index; /* Lowest page->index to unmap */ pgoff_t last_index; /* Highest page->index to unmap */ + struct page *single_page; /* Locked page to be unmapped */ }; struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, @@ -1475,9 +1489,11 @@ void free_pgd_range(struct mmu_gather *tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma); -int follow_pte_pmd(struct mm_struct *mm, unsigned long address, - struct mmu_notifier_range *range, - pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp); +int follow_invalidate_pte(struct mm_struct *mm, unsigned long address, + struct mmu_notifier_range *range, pte_t **ptepp, + pmd_t **pmdpp, spinlock_t **ptlp); +int follow_pte(struct mm_struct *mm, unsigned long address, + pte_t **ptepp, spinlock_t **ptlp); int follow_pfn(struct vm_area_struct *vma, unsigned long address, unsigned long *pfn); int follow_phys(struct vm_area_struct *vma, unsigned long address, @@ -1499,6 +1515,7 @@ extern vm_fault_t handle_mm_fault(struct vm_area_struct *vma, extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, unsigned long address, unsigned int fault_flags, bool *unlocked); +void unmap_mapping_page(struct page *page); void unmap_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t nr, bool even_cows); void unmap_mapping_range(struct address_space *mapping, @@ -1519,6 +1536,7 @@ static inline int fixup_user_fault(struct task_struct *tsk, BUG(); return -EFAULT; } +static inline void unmap_mapping_page(struct page *page) { } static inline void unmap_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t nr, bool even_cows) { } static inline void unmap_mapping_range(struct address_space *mapping, @@ -2926,5 +2944,37 @@ static inline int pages_identical(struct page *page1, struct page *page2) return !memcmp_pages(page1, page2); } +/** + * seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it + * @seals: the seals to check + * @vma: the vma to operate on + * + * Check whether F_SEAL_FUTURE_WRITE is set; if so, do proper check/handling on + * the vma flags. Return 0 if check pass, or <0 for errors. + */ +static inline int seal_check_future_write(int seals, struct vm_area_struct *vma) +{ + if (seals & F_SEAL_FUTURE_WRITE) { + /* + * New PROT_WRITE and MAP_SHARED mmaps are not allowed when + * "future write" seal active. + */ + if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE)) + return -EPERM; + + /* + * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as + * MAP_SHARED and read-only, take care to not allow mprotect to + * revert protections on such mappings. Do this only for shared + * mappings. For private mappings, don't need to mask + * VM_MAYWRITE as we still want them to be COW-writable. + */ + if (vma->vm_flags & VM_SHARED) + vma->vm_flags &= ~(VM_MAYWRITE); + } + + return 0; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index c9fd16e..157eedb 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -96,10 +96,10 @@ struct page { }; struct { /* page_pool used by netstack */ /** - * @dma_addr: might require a 64-bit value even on + * @dma_addr: might require a 64-bit value on * 32-bit architectures. */ - dma_addr_t dma_addr; + unsigned long dma_addr[2]; }; struct { /* slab, slob and slub */ union { diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 4c5eb3a..a0e1cf1 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -281,9 +281,6 @@ struct mmc_host { u32 ocr_avail_sdio; /* SDIO-specific OCR */ u32 ocr_avail_sd; /* SD-specific OCR */ u32 ocr_avail_mmc; /* MMC-specific OCR */ -#ifdef CONFIG_PM_SLEEP - struct notifier_block pm_notify; -#endif u32 max_current_330; u32 max_current_300; u32 max_current_180; diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h index 2ad72d2..5d0767c 100644 --- a/include/linux/mmdebug.h +++ b/include/linux/mmdebug.h @@ -37,6 +37,18 @@ void dump_mm(const struct mm_struct *mm); BUG(); \ } \ } while (0) +#define VM_WARN_ON_ONCE_PAGE(cond, page) ({ \ + static bool __section(".data.once") __warned; \ + int __ret_warn_once = !!(cond); \ + \ + if (unlikely(__ret_warn_once && !__warned)) { \ + dump_page(page, "VM_WARN_ON_ONCE_PAGE(" __stringify(cond)")");\ + __warned = true; \ + WARN_ON(1); \ + } \ + unlikely(__ret_warn_once); \ +}) + #define VM_WARN_ON(cond) (void)WARN_ON(cond) #define VM_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond) #define VM_WARN_ONCE(cond, format...) (void)WARN_ONCE(cond, format) @@ -48,6 +60,7 @@ void dump_mm(const struct mm_struct *mm); #define VM_BUG_ON_MM(cond, mm) VM_BUG_ON(cond) #define VM_WARN_ON(cond) BUILD_BUG_ON_INVALID(cond) #define VM_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond) +#define VM_WARN_ON_ONCE_PAGE(cond, page) BUILD_BUG_ON_INVALID(cond) #define VM_WARN_ONCE(cond, format...) BUILD_BUG_ON_INVALID(cond) #define VM_WARN(cond, format...) BUILD_BUG_ON_INVALID(cond) #endif diff --git a/include/linux/module.h b/include/linux/module.h index 6d20895..3e01e01 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -376,6 +376,7 @@ struct module { unsigned int num_gpl_syms; const struct kernel_symbol *gpl_syms; const s32 *gpl_crcs; + bool using_gplonly_symbols; #ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ @@ -561,34 +562,14 @@ struct module *find_module(const char *name); struct symsearch { const struct kernel_symbol *start, *stop; const s32 *crcs; - enum { + enum mod_license { NOT_GPL_ONLY, GPL_ONLY, WILL_BE_GPL_ONLY, - } licence; + } license; bool unused; }; -/* - * Search for an exported symbol by name. - * - * Must be called with module_mutex held or preemption disabled. - */ -const struct kernel_symbol *find_symbol(const char *name, - struct module **owner, - const s32 **crc, - bool gplok, - bool warn); - -/* - * Walk the exported symbol table - * - * Must be called with module_mutex held or preemption disabled. - */ -bool each_symbol_section(bool (*fn)(const struct symsearch *arr, - struct module *owner, - void *data), void *data); - /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if symnum out of range. */ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, @@ -636,7 +617,6 @@ static inline void __module_get(struct module *module) #define symbol_put_addr(p) do { } while (0) #endif /* CONFIG_MODULE_UNLOAD */ -int ref_module(struct module *a, struct module *b); /* This is a #define so the string doesn't get put in every .o file */ #define module_name(mod) \ diff --git a/include/linux/msi.h b/include/linux/msi.h index 8ad679e..758e32f 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -139,6 +139,12 @@ struct msi_desc { list_for_each_entry((desc), dev_to_msi_list((dev)), list) #define for_each_msi_entry_safe(desc, tmp, dev) \ list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) +#define for_each_msi_vector(desc, __irq, dev) \ + for_each_msi_entry((desc), (dev)) \ + if ((desc)->irq) \ + for (__irq = (desc)->irq; \ + __irq < ((desc)->irq + (desc)->nvec_used); \ + __irq++) #ifdef CONFIG_IRQ_MSI_IOMMU static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) @@ -188,7 +194,7 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag); -u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag); +void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag); void pci_msi_mask_irq(struct irq_data *data); void pci_msi_unmask_irq(struct irq_data *data); diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 04ed797..1357fc5 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -178,7 +178,7 @@ extern void mutex_lock_io(struct mutex *lock); # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) # define mutex_lock_killable_nested(lock, subclass) mutex_lock_killable(lock) # define mutex_lock_nest_lock(lock, nest_lock) mutex_lock(lock) -# define mutex_lock_io_nested(lock, subclass) mutex_lock(lock) +# define mutex_lock_io_nested(lock, subclass) mutex_lock_io(lock) #endif /* diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 4b19c54..640e727 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -83,7 +83,7 @@ enum { /* * Add your fresh new feature above and remember to update - * netdev_features_strings[] in net/core/ethtool.c and maybe + * netdev_features_strings[] in net/ethtool/common.c and maybe * some feature mask #defines below. Please also describe it * in Documentation/networking/netdev-features.txt. */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b44eba8..82356fe 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1559,6 +1559,12 @@ enum netdev_priv_flags { #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK +/* Specifies the type of the struct net_device::ml_priv pointer */ +enum netdev_ml_priv_type { + ML_PRIV_NONE, + ML_PRIV_CAN, +}; + /** * struct net_device - The DEVICE structure. * @@ -1736,6 +1742,7 @@ enum netdev_priv_flags { * @nd_net: Network namespace this network device is inside * * @ml_priv: Mid-layer private + * @ml_priv_type: Mid-layer private type * @lstats: Loopback statistics * @tstats: Tunnel statistics * @dstats: Dummy statistics @@ -2023,8 +2030,10 @@ struct net_device { possible_net_t nd_net; /* mid-layer private */ + void *ml_priv; + enum netdev_ml_priv_type ml_priv_type; + union { - void *ml_priv; struct pcpu_lstats __percpu *lstats; struct pcpu_sw_netstats __percpu *tstats; struct pcpu_dstats __percpu *dstats; @@ -2178,6 +2187,29 @@ static inline void netdev_reset_rx_headroom(struct net_device *dev) netdev_set_rx_headroom(dev, -1); } +static inline void *netdev_get_ml_priv(struct net_device *dev, + enum netdev_ml_priv_type type) +{ + if (dev->ml_priv_type != type) + return NULL; + + return dev->ml_priv; +} + +static inline void netdev_set_ml_priv(struct net_device *dev, + void *ml_priv, + enum netdev_ml_priv_type type) +{ + WARN(dev->ml_priv_type && dev->ml_priv_type != type, + "Overwriting already set ml_priv_type (%u) with different ml_priv_type (%u)!\n", + dev->ml_priv_type, type); + WARN(!dev->ml_priv_type && dev->ml_priv, + "Overwriting already set ml_priv and ml_priv_type is ML_PRIV_NONE!\n"); + + dev->ml_priv = ml_priv; + dev->ml_priv_type = type; +} + /* * Net namespace inlines */ @@ -3691,6 +3723,9 @@ int dev_pre_changeaddr_notify(struct net_device *dev, const char *addr, struct netlink_ext_ack *extack); int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa, struct netlink_ext_ack *extack); +int dev_set_mac_address_user(struct net_device *dev, struct sockaddr *sa, + struct netlink_ext_ack *extack); +int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name); int dev_change_carrier(struct net_device *, bool new_carrier); int dev_get_phys_port_id(struct net_device *dev, struct netdev_phys_item_id *ppid); @@ -4064,6 +4099,7 @@ static inline void netif_tx_disable(struct net_device *dev) local_bh_disable(); cpu = smp_processor_id(); + spin_lock(&dev->tx_global_lock); for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *txq = netdev_get_tx_queue(dev, i); @@ -4071,6 +4107,7 @@ static inline void netif_tx_disable(struct net_device *dev) netif_tx_stop_queue(txq); __netif_tx_unlock(txq); } + spin_unlock(&dev->tx_global_lock); local_bh_enable(); } diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index f5c21b7..04e7f56 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -227,7 +227,7 @@ struct xt_table { unsigned int valid_hooks; /* Man behind the curtain... */ - struct xt_table_info __rcu *private; + struct xt_table_info *private; /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -376,7 +376,7 @@ static inline unsigned int xt_write_recseq_begin(void) * since addend is most likely 1 */ __this_cpu_add(xt_recseq.sequence, addend); - smp_wmb(); + smp_mb(); return addend; } @@ -448,9 +448,6 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu) struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *); -struct xt_table_info -*xt_table_get_private_protected(const struct xt_table *table); - #ifdef CONFIG_COMPAT #include diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index e98028f..6988cf9 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -52,8 +52,9 @@ extern void *arpt_alloc_initial_table(const struct xt_table *); int arpt_register_table(struct net *net, const struct xt_table *table, const struct arpt_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); -void arpt_unregister_table(struct net *net, struct xt_table *table, - const struct nf_hook_ops *ops); +void arpt_unregister_table(struct net *net, struct xt_table *table); +void arpt_unregister_table_pre_exit(struct net *net, struct xt_table *table, + const struct nf_hook_ops *ops); extern unsigned int arpt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct xt_table *table); diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 162f59d..db472c9 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -110,8 +110,9 @@ extern int ebt_register_table(struct net *net, const struct ebt_table *table, const struct nf_hook_ops *ops, struct ebt_table **res); -extern void ebt_unregister_table(struct net *net, struct ebt_table *table, - const struct nf_hook_ops *); +extern void ebt_unregister_table(struct net *net, struct ebt_table *table); +void ebt_unregister_table_pre_exit(struct net *net, const char *tablename, + const struct nf_hook_ops *ops); extern unsigned int ebt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct ebt_table *table); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index edb356e..da9e9dd 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -79,6 +79,7 @@ struct nfs_open_context { #define NFS_CONTEXT_RESEND_WRITES (1) #define NFS_CONTEXT_BAD (2) #define NFS_CONTEXT_UNLOCK (3) +#define NFS_CONTEXT_FILE_OPEN (4) int error; struct list_head list; diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 37a4d9e..8543b1a 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -397,7 +397,7 @@ static inline struct page *read_mapping_page(struct address_space *mapping, } /* - * Get index of the page with in radix-tree + * Get index of the page within radix-tree (but not for hugetlb pages). * (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE) */ static inline pgoff_t page_to_index(struct page *page) @@ -416,15 +416,16 @@ static inline pgoff_t page_to_index(struct page *page) return pgoff; } +extern pgoff_t hugetlb_basepage_index(struct page *page); + /* - * Get the offset in PAGE_SIZE. - * (TODO: hugepage should have ->index in PAGE_SIZE) + * Get the offset in PAGE_SIZE (even for hugetlb pages). + * (TODO: hugetlb pages should have ->index in PAGE_SIZE) */ static inline pgoff_t page_to_pgoff(struct page *page) { - if (unlikely(PageHeadHuge(page))) - return page->index << compound_order(page); - + if (unlikely(PageHuge(page))) + return hugetlb_basepage_index(page); return page_to_index(page); } diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 057d7dc..5d6e619 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -3135,6 +3135,7 @@ #define PCI_DEVICE_ID_MCST_I2CSPI 0x0002 #define PCI_DEVICE_ID_MCST_MPKM 0x504b #define PCI_DEVICE_ID_MCST_MPKM2 0x506b +#define PCI_DEVICE_ID_PAR_SER 0x8000 #define PCI_DEVICE_ID_MCST_VIRT_PCI_BRIDGE 0xe3e3 #define PCI_VENDOR_ID_MCST_PCIE_BRIDGE 0xe3e3 diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h index 8b30b14..f377817 100644 --- a/include/linux/platform_data/gpio-omap.h +++ b/include/linux/platform_data/gpio-omap.h @@ -85,6 +85,7 @@ * omap2+ specific GPIO registers */ #define OMAP24XX_GPIO_REVISION 0x0000 +#define OMAP24XX_GPIO_SYSCONFIG 0x0010 #define OMAP24XX_GPIO_IRQSTATUS1 0x0018 #define OMAP24XX_GPIO_IRQSTATUS2 0x0028 #define OMAP24XX_GPIO_IRQENABLE2 0x002c @@ -108,6 +109,7 @@ #define OMAP24XX_GPIO_SETDATAOUT 0x0094 #define OMAP4_GPIO_REVISION 0x0000 +#define OMAP4_GPIO_SYSCONFIG 0x0010 #define OMAP4_GPIO_EOI 0x0020 #define OMAP4_GPIO_IRQSTATUSRAW0 0x0024 #define OMAP4_GPIO_IRQSTATUSRAW1 0x0028 @@ -148,6 +150,7 @@ #ifndef __ASSEMBLER__ struct omap_gpio_reg_offs { u16 revision; + u16 sysconfig; u16 direction; u16 datain; u16 dataout; diff --git a/include/linux/pm.h b/include/linux/pm.h index c1d21e9..eb28c80 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -608,6 +608,7 @@ struct dev_pm_info { unsigned int idle_notification:1; unsigned int request_pending:1; unsigned int deferred_resume:1; + unsigned int needs_force_resume:1; unsigned int runtime_auto:1; bool ignore_children:1; unsigned int no_callbacks:1; diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index 507c5e2..7413779 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h @@ -50,7 +50,6 @@ struct bq27xxx_reg_cache { int capacity; int energy; int flags; - int power_avg; int health; }; diff --git a/include/linux/prandom.h b/include/linux/prandom.h index cc1e713..e20339c 100644 --- a/include/linux/prandom.h +++ b/include/linux/prandom.h @@ -93,7 +93,7 @@ static inline u32 __seed(u32 x, u32 m) */ static inline void prandom_seed_state(struct rnd_state *state, u64 seed) { - u32 i = (seed >> 32) ^ (seed << 10) ^ seed; + u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL; state->s1 = __seed(i, 2U); state->s2 = __seed(i, 8U); diff --git a/include/linux/preempt.h b/include/linux/preempt.h index 1006647..0f9e8f0 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -191,9 +191,9 @@ extern void preempt_count_sub(int val); # ifdef CONFIG_DEBUG_PREEMPT_COUNT # define preempt_count_sub(val) \ do { \ - WARN_ONCE((val > *preempt_count_ptr()), \ + WARN_ONCE((val > preempt_count()), \ "preempt count(0x%08x) < val(%d)\n", \ - *preempt_count_ptr(), val); \ + preempt_count(), val); \ if (unlikely(do_watch_preempt_disable)) \ chck_tm_prmtdsbl(val); \ __preempt_count_sub(val); \ diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index 93cc4f1..874f7e7 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -218,7 +218,7 @@ extern int ptp_clock_index(struct ptp_clock *ptp); * @ppm: Parts per million, but with a 16 bit binary fractional field */ -extern s32 scaled_ppm_to_ppb(long ppm); +extern long scaled_ppm_to_ppb(long ppm); /** * ptp_find_pin() - obtain the pin index of a given auxiliary function diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 4b7c521..4b1d058 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -104,8 +104,10 @@ static inline void rcu_user_exit(void) { } #ifdef CONFIG_RCU_NOCB_CPU void rcu_init_nohz(void); +void rcu_nocb_flush_deferred_wakeup(void); #else /* #ifdef CONFIG_RCU_NOCB_CPU */ static inline void rcu_init_nohz(void) { } +static inline void rcu_nocb_flush_deferred_wakeup(void) { } #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ /** diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 988d176..91ccae9 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -98,7 +98,8 @@ enum ttu_flags { * do a final flush if necessary */ TTU_RMAP_LOCKED = 0x80, /* do not grab rmap lock: * caller holds it */ - TTU_SPLIT_FREEZE = 0x100, /* freeze pte under splitting thp */ + TTU_SPLIT_FREEZE = 0x100, /* freeze pte under splitting thp */ + TTU_SYNC = 0x200, /* avoid racy checks with PVMW_SYNC */ }; #ifdef CONFIG_MMU @@ -214,7 +215,8 @@ struct page_vma_mapped_walk { static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw) { - if (pvmw->pte) + /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */ + if (pvmw->pte && !PageHuge(pvmw->page)) pte_unmap(pvmw->pte); if (pvmw->ptl) spin_unlock(pvmw->ptl); diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h index af8d898..aaf64d5 100644 --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -177,7 +177,8 @@ static inline bool in_vfork(struct task_struct *tsk) * another oom-unkillable task does this it should blame itself. */ rcu_read_lock(); - ret = tsk->vfork_done && tsk->real_parent->mm == tsk->mm; + ret = tsk->vfork_done && + rcu_dereference(tsk->real_parent)->mm == tsk->mm; rcu_read_unlock(); return ret; diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index baf58f4..b3f8847 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -509,6 +509,17 @@ static inline int kill_cad_pid(int sig, int priv) #define SEND_SIG_NOINFO ((struct kernel_siginfo *) 0) #define SEND_SIG_PRIV ((struct kernel_siginfo *) 1) +static inline int __on_sig_stack(unsigned long sp) +{ +#ifdef CONFIG_STACK_GROWSUP + return sp >= current->sas_ss_sp && + sp - current->sas_ss_sp < current->sas_ss_size; +#else + return sp > current->sas_ss_sp && + sp - current->sas_ss_sp <= current->sas_ss_size; +#endif +} + /* * True if we are on the alternate signal stack. */ @@ -526,13 +537,7 @@ static inline int on_sig_stack(unsigned long sp) if (current->sas_ss_flags & SS_AUTODISARM) return 0; -#ifdef CONFIG_STACK_GROWSUP - return sp >= current->sas_ss_sp && - sp - current->sas_ss_sp < current->sas_ss_size; -#else - return sp > current->sas_ss_sp && - sp - current->sas_ss_sp <= current->sas_ss_size; -#endif + return __on_sig_stack(sp); } static inline int sas_ss_flags(unsigned long sp) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ab18a60..eaf9f5e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1484,6 +1484,11 @@ static inline void skb_mark_not_on_list(struct sk_buff *skb) skb->next = NULL; } +/* Iterate through singly-linked GSO fragments of an skb. */ +#define skb_list_walk_safe(first, skb, next_skb) \ + for ((skb) = (first), (next_skb) = (skb) ? (skb)->next : NULL; (skb); \ + (skb) = (next_skb), (next_skb) = (skb) ? (skb)->next : NULL) + static inline void skb_list_del_init(struct sk_buff *skb) { __list_del_entry(&skb->list); diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 20f3550..613d045 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -355,13 +355,17 @@ static inline void sk_psock_update_proto(struct sock *sk, static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { - sk->sk_prot->unhash = psock->saved_unhash; - if (psock->sk_proto) { struct inet_connection_sock *icsk = inet_csk(sk); bool has_ulp = !!icsk->icsk_ulp_data; if (has_ulp) { + /* TLS does not have an unhash proto in SW cases, but we need + * to ensure we stop using the sock_map unhash routine because + * the associated psock is being removed. So use the original + * unhash handler. + */ + WRITE_ONCE(sk->sk_prot->unhash, psock->saved_unhash); tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); } else { diff --git a/include/linux/smp.h b/include/linux/smp.h index 01ff6ed..4f7e8f0 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -56,7 +56,7 @@ void on_each_cpu_cond(smp_cond_func_t cond_func, smp_call_func_t func, void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func, void *info, bool wait, const struct cpumask *mask); -int smp_call_function_single_async(int cpu, call_single_data_t *csd); +int smp_call_function_single_async(int cpu, struct __call_single_data *csd); #ifdef CONFIG_SMP diff --git a/include/linux/socket.h b/include/linux/socket.h index 4049d97..a465c6a 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -406,6 +406,4 @@ extern int __sys_getpeername(int fd, struct sockaddr __user *usockaddr, extern int __sys_socketpair(int family, int type, int protocol, int __user *usockvec); extern int __sys_shutdown(int fd, int how); - -extern struct ns_common *get_net_ns(struct ns_common *ns); #endif /* _LINUX_SOCKET_H */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index acd9130..7067f85 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -466,6 +466,9 @@ struct spi_controller { #define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */ + /* flag indicating this is a non-devres managed controller */ + bool devm_allocated; + /* flag indicating this is an SPI slave controller */ bool slave; diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index 27d3288..5190c8b 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -141,7 +141,7 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus); #else /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */ -static inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, +static __always_inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus) { unsigned long flags; @@ -152,14 +152,15 @@ static inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, return ret; } -static inline int stop_machine(cpu_stop_fn_t fn, void *data, - const struct cpumask *cpus) +static __always_inline int +stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus) { return stop_machine_cpuslocked(fn, data, cpus); } -static inline int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, - const struct cpumask *cpus) +static __always_inline int +stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, + const struct cpumask *cpus) { return stop_machine(fn, data, cpus); } diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 9db6097..a8d68c5 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -27,8 +27,7 @@ struct rpc_rqst; #define XDR_QUADLEN(l) (((l) + 3) >> 2) /* - * Generic opaque `network object.' At the kernel level, this type - * is used only by lockd. + * Generic opaque `network object.' */ #define XDR_MAX_NETOBJ 1024 struct xdr_netobj { diff --git a/include/linux/swap.h b/include/linux/swap.h index 7870725..8239310 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -523,6 +523,7 @@ struct backing_dev_info; extern int init_swap_address_space(unsigned int type, unsigned long nr_pages); extern void exit_swap_address_space(unsigned int type); extern struct swap_info_struct *get_swap_device(swp_entry_t entry); +sector_t swap_page_sector(struct page *page); static inline void put_swap_device(struct swap_info_struct *si) { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index fa7ee50..428707a 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -310,6 +310,11 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) return kernfs_enable_ns(kn); } +__printf(2, 3) +int sysfs_emit(char *buf, const char *fmt, ...); +__printf(3, 4) +int sysfs_emit_at(char *buf, int at, const char *fmt, ...); + #else /* CONFIG_SYSFS */ static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) @@ -522,6 +527,17 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) { } +__printf(2, 3) +static inline int sysfs_emit(char *buf, const char *fmt, ...) +{ + return 0; +} + +__printf(3, 4) +static inline int sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + return 0; +} #endif /* CONFIG_SYSFS */ static inline int __must_check sysfs_create_file(struct kobject *kobj, diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 7a03f68..cd15c1b 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -26,6 +26,7 @@ #define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */ #define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */ #define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */ +#define TEE_SHM_PRIV BIT(7) /* Memory private to TEE driver */ struct device; struct tee_device; @@ -317,6 +318,7 @@ void *tee_get_drvdata(struct tee_device *teedev); * @returns a pointer to 'struct tee_shm' */ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); +struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size); /** * tee_shm_priv_alloc() - Allocate shared memory privately diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index c88b9ce..3cb02ce 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_THREAD_INFO_IN_TASK /* @@ -39,6 +40,18 @@ enum { #ifdef __KERNEL__ +#ifndef arch_set_restart_data +#define arch_set_restart_data(restart) do { } while (0) +#endif + +static inline long set_restart_fn(struct restart_block *restart, + long (*fn)(struct restart_block *)) +{ + restart->fn = fn; + arch_set_restart_data(restart); + return -ERESTART_RESTARTBLOCK; +} + #ifndef THREAD_ALIGN #define THREAD_ALIGN THREAD_SIZE #endif diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 57ce5af..eede1a7 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -40,7 +40,17 @@ extern int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data, int prio); extern int +tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, void *data, + int prio); +extern int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data); +static inline int +tracepoint_probe_register_may_exist(struct tracepoint *tp, void *probe, + void *data) +{ + return tracepoint_probe_register_prio_may_exist(tp, probe, data, + TRACEPOINT_DEFAULT_PRIO); +} extern void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), void *priv); diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 3584462..7186d77 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -236,7 +236,7 @@ * * Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel * structure to complete. This method is optional and will only be called - * if provided (otherwise EINVAL will be returned). + * if provided (otherwise ENOTTY will be returned). */ #include diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h index a27604f..11096b5 100644 --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h @@ -69,12 +69,13 @@ struct u64_stats_sync { }; +#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) +#define u64_stats_init(syncp) seqcount_init(&(syncp)->seq) +#else static inline void u64_stats_init(struct u64_stats_sync *syncp) { -#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) - seqcount_init(&syncp->seq); -#endif } +#endif static inline void u64_stats_update_begin(struct u64_stats_sync *syncp) { diff --git a/include/linux/uio.h b/include/linux/uio.h index ab5f523..b74d292 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -261,7 +261,13 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) { i->count = count; } -size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csump, struct iov_iter *i); + +struct csum_state { + __wsum csum; + size_t off; +}; + +size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csstate, struct iov_iter *i); size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp, diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h index e78eb57..8ef7d14 100644 --- a/include/linux/usb/otg-fsm.h +++ b/include/linux/usb/otg-fsm.h @@ -196,6 +196,7 @@ struct otg_fsm { struct mutex lock; u8 *host_req_flag; struct delayed_work hnp_polling_work; + bool hnp_work_inited; bool state_changed; }; diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index 6655ce3..696230b 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -425,7 +425,7 @@ static inline unsigned int rdo_max_power(u32 rdo) #define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */ #define PD_T_SOURCE_ACTIVITY 45 #define PD_T_SINK_ACTIVITY 135 -#define PD_T_SINK_WAIT_CAP 240 +#define PD_T_SINK_WAIT_CAP 310 /* 310 - 620 ms */ #define PD_T_PS_TRANSITION 500 #define PD_T_SRC_TRANSITION 35 #define PD_T_DRP_SNK 40 diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index d8860f2..fc6ed13 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -83,6 +83,8 @@ struct usbnet { # define EVENT_LINK_CHANGE 11 # define EVENT_SET_RX_MODE 12 # define EVENT_NO_IP_ALIGN 13 + u32 rx_speed; /* in bps - NOT Mbps */ + u32 tx_speed; /* in bps - NOT Mbps */ }; static inline struct usb_driver *driver_of(struct usb_interface *intf) diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index a7f7ebd..0a958c7 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -86,6 +86,8 @@ /* lies about caching, so always sync */ \ US_FLAG(NO_SAME, 0x40000000) \ /* Cannot handle WRITE_SAME */ \ + US_FLAG(SENSE_AFTER_SYNC, 0x80000000) \ + /* Do REQUEST_SENSE after SYNCHRONIZE_CACHE */ \ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 15f906e..7c07546 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -111,6 +111,7 @@ struct virtio_device { bool config_enabled; bool config_change_pending; spinlock_t config_lock; + spinlock_t vqs_list_lock; /* Protects VQs list access */ struct device dev; struct virtio_device_id id; const struct virtio_config_ops *config; diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index e8a924e..b465f8f 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -62,15 +62,21 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, return -EINVAL; } + skb_reset_mac_header(skb); + if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); - u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + u32 start = __virtio16_to_cpu(little_endian, hdr->csum_start); + u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); + + if (!pskb_may_pull(skb, needed)) + return -EINVAL; if (!skb_partial_csum_set(skb, start, off)) return -EINVAL; p_off = skb_transport_offset(skb) + thlen; - if (p_off > skb_headlen(skb)) + if (!pskb_may_pull(skb, p_off)) return -EINVAL; } else { /* gso packets without NEEDS_CSUM do not set transport_offset. @@ -79,8 +85,13 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, if (gso_type && skb->network_header) { struct flow_keys_basic keys; - if (!skb->protocol) + if (!skb->protocol) { + __be16 protocol = dev_parse_header_protocol(skb); + virtio_net_hdr_set_proto(skb, hdr); + if (protocol && protocol != skb->protocol) + return -EINVAL; + } retry: if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys, NULL, 0, 0, 0, @@ -95,14 +106,14 @@ retry: } p_off = keys.control.thoff + thlen; - if (p_off > skb_headlen(skb) || + if (!pskb_may_pull(skb, p_off) || keys.basic.ip_proto != ip_proto) return -EINVAL; skb_set_transport_header(skb, keys.control.thoff); } else if (gso_type) { p_off = thlen; - if (p_off > skb_headlen(skb)) + if (!pskb_may_pull(skb, p_off)) return -EINVAL; } } diff --git a/include/linux/wait.h b/include/linux/wait.h index 1781c47..f6c36e6 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -1123,7 +1123,7 @@ do { \ * Waitqueues which are removed from the waitqueue_head at wakeup time */ void prepare_to_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); -void prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); +bool prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); long prepare_to_wait_event(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); void finish_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); long wait_woken(struct wait_queue_entry *wq_entry, unsigned mode, long timeout); diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 3b257c9..2903f25 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h @@ -1470,6 +1470,28 @@ void xas_pause(struct xa_state *); void xas_create_range(struct xa_state *); +#ifdef CONFIG_XARRAY_MULTI +int xa_get_order(struct xarray *, unsigned long index); +void xas_split(struct xa_state *, void *entry, unsigned int order); +void xas_split_alloc(struct xa_state *, void *entry, unsigned int order, gfp_t); +#else +static inline int xa_get_order(struct xarray *xa, unsigned long index) +{ + return 0; +} + +static inline void xas_split(struct xa_state *xas, void *entry, + unsigned int order) +{ + xas_store(xas, entry); +} + +static inline void xas_split_alloc(struct xa_state *xas, void *entry, + unsigned int order, gfp_t gfp) +{ +} +#endif + /** * xas_reload() - Refetch an entry from the xarray. * @xas: XArray operation state. diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h index 4807ca4..2a430e7 100644 --- a/include/linux/zsmalloc.h +++ b/include/linux/zsmalloc.h @@ -35,7 +35,7 @@ enum zs_mapmode { struct zs_pool_stats { /* How many pages were migrated (freed) */ - unsigned long pages_compacted; + atomic_long_t pages_compacted; }; struct zs_pool; diff --git a/include/media/media-dev-allocator.h b/include/media/media-dev-allocator.h index b35ea60..2ab54d4 100644 --- a/include/media/media-dev-allocator.h +++ b/include/media/media-dev-allocator.h @@ -19,7 +19,7 @@ struct usb_device; -#if defined(CONFIG_MEDIA_CONTROLLER) && defined(CONFIG_USB) +#if defined(CONFIG_MEDIA_CONTROLLER) && IS_ENABLED(CONFIG_USB) /** * media_device_usb_allocate() - Allocate and return struct &media device * diff --git a/include/media/rc-map.h b/include/media/rc-map.h index c2ef390..a358c87 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -126,6 +126,13 @@ struct rc_map_list { struct rc_map map; }; +#ifdef CONFIG_MEDIA_CEC_RC +/* + * rc_map_list from rc-cec.c + */ +extern struct rc_map_list cec_map; +#endif + /* Routines from rc-map.c */ /** diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 71f1f2f..d4ac251 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -162,6 +162,9 @@ struct v4l2_subdev_io_pin_config { * @s_gpio: set GPIO pins. Very simple right now, might need to be extended with * a direction argument if needed. * + * @command: called by in-kernel drivers in order to call functions internal + * to subdev drivers driver that have a separate callback. + * * @ioctl: called at the end of ioctl() syscall handler at the V4L2 core. * used to provide support for private ioctls used on the driver. * @@ -193,6 +196,7 @@ struct v4l2_subdev_core_ops { int (*load_fw)(struct v4l2_subdev *sd); int (*reset)(struct v4l2_subdev *sd, u32 val); int (*s_gpio)(struct v4l2_subdev *sd, u32 val); + long (*command)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); #ifdef CONFIG_COMPAT long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd, diff --git a/include/net/act_api.h b/include/net/act_api.h index 05b568b..4dabe47 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -156,6 +156,7 @@ int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index); int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, struct tc_action **a, const struct tc_action_ops *ops, int bind, bool cpustats); +void tcf_idr_insert_many(struct tc_action *actions[]); void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index, struct tc_action **a, int bind); diff --git a/include/net/addrconf.h b/include/net/addrconf.h index ab8b3eb..8d90fb9 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -229,7 +229,6 @@ void ipv6_mc_unmap(struct inet6_dev *idev); void ipv6_mc_remap(struct inet6_dev *idev); void ipv6_mc_init_dev(struct inet6_dev *idev); void ipv6_mc_destroy_dev(struct inet6_dev *idev); -int ipv6_mc_check_icmpv6(struct sk_buff *skb); int ipv6_mc_check_mld(struct sk_buff *skb); void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp); diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3cd232c..14d00cc 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -540,6 +540,7 @@ struct hci_chan { struct sk_buff_head data_q; unsigned int sent; __u8 state; + bool amp; }; struct hci_conn_params { @@ -1055,6 +1056,7 @@ struct hci_dev *hci_alloc_dev(void); void hci_free_dev(struct hci_dev *hdev); int hci_register_dev(struct hci_dev *hdev); void hci_unregister_dev(struct hci_dev *hdev); +void hci_cleanup_dev(struct hci_dev *hdev); int hci_suspend_dev(struct hci_dev *hdev); int hci_resume_dev(struct hci_dev *hdev); int hci_reset_dev(struct hci_dev *hdev); diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index 86e0283..9899b9a 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h @@ -36,7 +36,7 @@ static inline bool net_busy_loop_on(void) static inline bool sk_can_busy_loop(const struct sock *sk) { - return sk->sk_ll_usec && !signal_pending(current); + return READ_ONCE(sk->sk_ll_usec) && !signal_pending(current); } bool sk_busy_loop_end(void *p, unsigned long start_time); diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h index 48ecca8..b655d86 100644 --- a/include/net/caif/caif_dev.h +++ b/include/net/caif/caif_dev.h @@ -119,7 +119,7 @@ void caif_free_client(struct cflayer *adap_layer); * The link_support layer is used to add any Link Layer specific * framing. */ -void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, +int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, struct cflayer *link_support, int head_room, struct cflayer **layer, int (**rcv_func)( struct sk_buff *, struct net_device *, diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h index 2aa5e91..8819ff4 100644 --- a/include/net/caif/cfcnfg.h +++ b/include/net/caif/cfcnfg.h @@ -62,7 +62,7 @@ void cfcnfg_remove(struct cfcnfg *cfg); * @fcs: Specify if checksum is used in CAIF Framing Layer. * @head_room: Head space needed by link specific protocol. */ -void +int cfcnfg_add_phy_layer(struct cfcnfg *cnfg, struct net_device *dev, struct cflayer *phy_layer, enum cfcnfg_phy_preference pref, diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h index 14a55e0..67cce87 100644 --- a/include/net/caif/cfserl.h +++ b/include/net/caif/cfserl.h @@ -9,4 +9,5 @@ #include struct cflayer *cfserl_create(int instance, bool use_stx); +void cfserl_release(struct cflayer *layer); #endif diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 68782ba..69b9ccb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5194,7 +5194,7 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); */ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, const u8 *addr, enum nl80211_iftype iftype, - u8 data_offset); + u8 data_offset, bool is_amsdu); /** * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 @@ -5206,7 +5206,7 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype) { - return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0); + return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0, false); } /** diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h index 56cb3c3..14efa0d 100644 --- a/include/net/dst_metadata.h +++ b/include/net/dst_metadata.h @@ -45,7 +45,9 @@ skb_tunnel_info(const struct sk_buff *skb) return &md_dst->u.tun_info; dst = skb_dst(skb); - if (dst && dst->lwtstate) + if (dst && dst->lwtstate && + (dst->lwtstate->type == LWTUNNEL_ENCAP_IP || + dst->lwtstate->type == LWTUNNEL_ENCAP_IP6)) return lwt_tun_info(dst->lwtstate); return NULL; diff --git a/include/net/icmp.h b/include/net/icmp.h index 5d4bfdb..fd84adc 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -43,6 +43,16 @@ static inline void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 __icmp_send(skb_in, type, code, info, &IPCB(skb_in)->opt); } +#if IS_ENABLED(CONFIG_NF_NAT) +void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info); +#else +static inline void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info) +{ + struct ip_options opts = { 0 }; + __icmp_send(skb_in, type, code, info, &opts); +} +#endif + int icmp_rcv(struct sk_buff *skb); int icmp_err(struct sk_buff *skb, u32 info); int icmp_init(void); diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index c71eb29..13792c0 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -83,6 +83,8 @@ struct inet_connection_sock_af_ops { * @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options) * @icsk_ack: Delayed ACK control data * @icsk_mtup; MTU probing control data + * @icsk_probes_tstamp: Probe timestamp (cleared by non-zero window ack) + * @icsk_user_timeout: TCP_USER_TIMEOUT value */ struct inet_connection_sock { /* inet_sock has to be the first member! */ @@ -133,6 +135,7 @@ struct inet_connection_sock { u32 probe_timestamp; } icsk_mtup; + u32 icsk_probes_tstamp; u32 icsk_user_timeout; u64 icsk_ca_priv[104 / sizeof(u64)]; @@ -284,7 +287,7 @@ static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk) return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog; } -void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req); +bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req); void inet_csk_reqsk_queue_drop_and_put(struct sock *sk, struct request_sock *req); void inet_csk_destroy_sock(struct sock *sk); diff --git a/include/net/ip.h b/include/net/ip.h index 0278d63..52abfc0 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -30,6 +30,7 @@ #include #include #include +#include #define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */ #define IPV4_MIN_MTU 68 /* RFC 791 */ @@ -448,22 +449,25 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, /* 'forwarding = true' case should always honour route mtu */ mtu = dst_metric_raw(dst, RTAX_MTU); - if (mtu) - return mtu; + if (!mtu) + mtu = min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU); - return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU); + return mtu - lwtunnel_headroom(dst->lwtstate, mtu); } static inline unsigned int ip_skb_dst_mtu(struct sock *sk, const struct sk_buff *skb) { + unsigned int mtu; + if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) { bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); } - return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); + mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); + return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); } struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx, diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 2d0d910..2c739fc 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -261,13 +261,20 @@ static inline bool ipv6_anycast_destination(const struct dst_entry *dst, int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, int (*output)(struct net *, struct sock *, struct sk_buff *)); -static inline int ip6_skb_dst_mtu(struct sk_buff *skb) +static inline unsigned int ip6_skb_dst_mtu(struct sk_buff *skb) { + unsigned int mtu; + struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? inet6_sk(skb->sk) : NULL; - return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ? - skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); + if (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) { + mtu = READ_ONCE(skb_dst(skb)->dev->mtu); + mtu -= lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); + } else + mtu = dst_mtu(skb_dst(skb)); + + return mtu; } static inline bool ip6_sk_accept_pmtu(const struct sock *sk) @@ -315,7 +322,7 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) if (dst_metric_locked(dst, RTAX_MTU)) { mtu = dst_metric_raw(dst, RTAX_MTU); if (mtu) - return mtu; + goto out; } mtu = IPV6_MIN_MTU; @@ -325,7 +332,8 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) mtu = idev->cnf.mtu6; rcu_read_unlock(); - return mtu; +out: + return mtu - lwtunnel_headroom(dst->lwtstate, mtu); } u32 ip6_mtu_from_fib6(const struct fib6_result *res, diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h index c0f0a13..49aa79c 100644 --- a/include/net/llc_pdu.h +++ b/include/net/llc_pdu.h @@ -15,9 +15,11 @@ #include /* Lengths of frame formats */ -#define LLC_PDU_LEN_I 4 /* header and 2 control bytes */ -#define LLC_PDU_LEN_S 4 -#define LLC_PDU_LEN_U 3 /* header and 1 control byte */ +#define LLC_PDU_LEN_I 4 /* header and 2 control bytes */ +#define LLC_PDU_LEN_S 4 +#define LLC_PDU_LEN_U 3 /* header and 1 control byte */ +/* header and 1 control byte and XID info */ +#define LLC_PDU_LEN_U_XID (LLC_PDU_LEN_U + sizeof(struct llc_xid_info)) /* Known SAP addresses */ #define LLC_GLOBAL_SAP 0xFF #define LLC_NULL_SAP 0x00 /* not network-layer visible */ @@ -50,9 +52,10 @@ #define LLC_PDU_TYPE_U_MASK 0x03 /* 8-bit control field */ #define LLC_PDU_TYPE_MASK 0x03 -#define LLC_PDU_TYPE_I 0 /* first bit */ -#define LLC_PDU_TYPE_S 1 /* first two bits */ -#define LLC_PDU_TYPE_U 3 /* first two bits */ +#define LLC_PDU_TYPE_I 0 /* first bit */ +#define LLC_PDU_TYPE_S 1 /* first two bits */ +#define LLC_PDU_TYPE_U 3 /* first two bits */ +#define LLC_PDU_TYPE_U_XID 4 /* private type for detecting XID commands */ #define LLC_PDU_TYPE_IS_I(pdu) \ ((!(pdu->ctrl_1 & LLC_PDU_TYPE_I_MASK)) ? 1 : 0) @@ -230,9 +233,18 @@ static inline struct llc_pdu_un *llc_pdu_un_hdr(struct sk_buff *skb) static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type, u8 ssap, u8 dsap, u8 cr) { - const int hlen = type == LLC_PDU_TYPE_U ? 3 : 4; + int hlen = 4; /* default value for I and S types */ struct llc_pdu_un *pdu; + switch (type) { + case LLC_PDU_TYPE_U: + hlen = 3; + break; + case LLC_PDU_TYPE_U_XID: + hlen = 6; + break; + } + skb_push(skb, hlen); skb_reset_network_header(skb); pdu = llc_pdu_un_hdr(skb); @@ -374,7 +386,10 @@ static inline void llc_pdu_init_as_xid_cmd(struct sk_buff *skb, xid_info->fmt_id = LLC_XID_FMT_ID; /* 0x81 */ xid_info->type = svcs_supported; xid_info->rw = rx_window << 1; /* size of receive window */ - skb_put(skb, sizeof(struct llc_xid_info)); + + /* no need to push/put since llc_pdu_header_init() has already + * pushed 3 + 3 bytes + */ } /** diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 0fca98a..167e390 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -195,6 +195,8 @@ struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns, void net_ns_get_ownership(const struct net *net, kuid_t *uid, kgid_t *gid); void net_ns_barrier(void); + +struct ns_common *get_net_ns(struct ns_common *ns); #else /* CONFIG_NET_NS */ #include #include @@ -214,6 +216,11 @@ static inline void net_ns_get_ownership(const struct net *net, } static inline void net_ns_barrier(void) {} + +static inline struct ns_common *get_net_ns(struct ns_common *ns) +{ + return ERR_PTR(-EINVAL); +} #endif /* CONFIG_NET_NS */ diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index c0c0791..676349b 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -168,6 +168,8 @@ struct netns_ipv4 { int sysctl_tcp_wmem[3]; int sysctl_tcp_rmem[3]; int sysctl_tcp_comp_sack_nr; + int sysctl_tcp_no_delayed_ack; + int sysctl_tcp_fast_tlp; unsigned long sysctl_tcp_comp_sack_delay_ns; struct inet_timewait_death_row tcp_death_row; int sysctl_max_syn_backlog; diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 59f45b1..b59d73d 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -72,7 +72,9 @@ struct netns_xfrm { #if IS_ENABLED(CONFIG_IPV6) struct dst_ops xfrm6_dst_ops; #endif - spinlock_t xfrm_state_lock; + spinlock_t xfrm_state_lock; + seqcount_t xfrm_state_hash_generation; + spinlock_t xfrm_policy_lock; struct mutex xfrm_cfg_mutex; }; diff --git a/include/net/nexthop.h b/include/net/nexthop.h index 3bb618e..18a5aca 100644 --- a/include/net/nexthop.h +++ b/include/net/nexthop.h @@ -291,6 +291,7 @@ static inline struct fib_nh *fib_info_nh(struct fib_info *fi, int nhsel) int fib6_check_nexthop(struct nexthop *nh, struct fib6_config *cfg, struct netlink_ext_ack *extack); +/* Caller should either hold rcu_read_lock(), or RTNL. */ static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh) { struct nh_info *nhi; @@ -311,6 +312,29 @@ static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh) return NULL; } +/* Variant of nexthop_fib6_nh(). + * Caller should either hold rcu_read_lock_bh(), or RTNL. + */ +static inline struct fib6_nh *nexthop_fib6_nh_bh(struct nexthop *nh) +{ + struct nh_info *nhi; + + if (nh->is_group) { + struct nh_group *nh_grp; + + nh_grp = rcu_dereference_bh_rtnl(nh->nh_grp); + nh = nexthop_mpath_select(nh_grp, 0); + if (!nh) + return NULL; + } + + nhi = rcu_dereference_bh_rtnl(nh->nh_info); + if (nhi->family == AF_INET6) + return &nhi->fib6_nh; + + return NULL; +} + static inline struct net_device *fib6_info_nh_dev(struct fib6_info *f6i) { struct fib6_nh *fib6_nh; diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 43c9c5d..3397901 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -298,6 +298,7 @@ int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len, struct sk_buff **resp); struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev); +void nci_hci_deallocate(struct nci_dev *ndev); int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event, const u8 *param, size_t param_len); int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, diff --git a/include/net/page_pool.h b/include/net/page_pool.h index 1121faa..cf086e1 100644 --- a/include/net/page_pool.h +++ b/include/net/page_pool.h @@ -185,7 +185,17 @@ static inline void page_pool_release_page(struct page_pool *pool, static inline dma_addr_t page_pool_get_dma_addr(struct page *page) { - return page->dma_addr; + dma_addr_t ret = page->dma_addr[0]; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16; + return ret; +} + +static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr) +{ + page->dma_addr[0] = addr; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + page->dma_addr[1] = upper_32_bits(addr); } static inline bool is_page_pool_compiled_in(void) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index cee1c08..b16f923 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -118,12 +118,7 @@ void __qdisc_run(struct Qdisc *q); static inline void qdisc_run(struct Qdisc *q) { if (qdisc_run_begin(q)) { - /* NOLOCK qdisc must check 'state' under the qdisc seqlock - * to avoid racing with dev_qdisc_reset() - */ - if (!(q->flags & TCQ_F_NOLOCK) || - likely(!test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) - __qdisc_run(q); + __qdisc_run(q); qdisc_run_end(q); } } diff --git a/include/net/psample.h b/include/net/psample.h index 68ae16b..20a1755 100644 --- a/include/net/psample.h +++ b/include/net/psample.h @@ -18,6 +18,8 @@ struct psample_group *psample_group_get(struct net *net, u32 group_num); void psample_group_take(struct psample_group *group); void psample_group_put(struct psample_group *group); +struct sk_buff; + #if IS_ENABLED(CONFIG_PSAMPLE) void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, diff --git a/include/net/red.h b/include/net/red.h index e21e7fd..ff07a7c 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -168,16 +168,24 @@ static inline void red_set_vars(struct red_vars *v) v->qcount = -1; } -static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, u8 Scell_log) +static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, + u8 Scell_log, u8 *stab) { - if (fls(qth_min) + Wlog > 32) + if (fls(qth_min) + Wlog >= 32) return false; - if (fls(qth_max) + Wlog > 32) + if (fls(qth_max) + Wlog >= 32) return false; if (Scell_log >= 32) return false; if (qth_max < qth_min) return false; + if (stab) { + int i; + + for (i = 0; i < RED_STAB_SIZE; i++) + if (stab[i] >= 32) + return false; + } return true; } diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index e2091bb..4da61c9 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -33,6 +33,7 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) * * @list: Used internally * @kind: Identifier + * @netns_refund: Physical device, move to init_net on netns exit * @maxtype: Highest device specific netlink attribute number * @policy: Netlink policy for device specific attribute validation * @validate: Optional validation function for netlink/changelink parameters @@ -64,6 +65,7 @@ struct rtnl_link_ops { size_t priv_size; void (*setup)(struct net_device *dev); + bool netns_refund; unsigned int maxtype; const struct nla_policy *policy; int (*validate)(struct nlattr *tb[], diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index e6afb4b..b47b5b9 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -37,6 +37,7 @@ struct qdisc_rate_table { enum qdisc_state_t { __QDISC_STATE_SCHED, __QDISC_STATE_DEACTIVATED, + __QDISC_STATE_MISSED, }; struct qdisc_size_table { @@ -161,8 +162,45 @@ static inline bool qdisc_is_empty(const struct Qdisc *qdisc) static inline bool qdisc_run_begin(struct Qdisc *qdisc) { if (qdisc->flags & TCQ_F_NOLOCK) { + if (spin_trylock(&qdisc->seqlock)) + goto nolock_empty; + + /* Paired with smp_mb__after_atomic() to make sure + * STATE_MISSED checking is synchronized with clearing + * in pfifo_fast_dequeue(). + */ + smp_mb__before_atomic(); + + /* If the MISSED flag is set, it means other thread has + * set the MISSED flag before second spin_trylock(), so + * we can return false here to avoid multi cpus doing + * the set_bit() and second spin_trylock() concurrently. + */ + if (test_bit(__QDISC_STATE_MISSED, &qdisc->state)) + return false; + + /* Set the MISSED flag before the second spin_trylock(), + * if the second spin_trylock() return false, it means + * other cpu holding the lock will do dequeuing for us + * or it will see the MISSED flag set after releasing + * lock and reschedule the net_tx_action() to do the + * dequeuing. + */ + set_bit(__QDISC_STATE_MISSED, &qdisc->state); + + /* spin_trylock() only has load-acquire semantic, so use + * smp_mb__after_atomic() to ensure STATE_MISSED is set + * before doing the second spin_trylock(). + */ + smp_mb__after_atomic(); + + /* Retry again in case other CPU may not see the new flag + * after it releases the lock at the end of qdisc_run_end(). + */ if (!spin_trylock(&qdisc->seqlock)) return false; + +nolock_empty: WRITE_ONCE(qdisc->empty, false); } else if (qdisc_is_running(qdisc)) { return false; @@ -188,8 +226,15 @@ static inline void qdisc_run_end(struct Qdisc *qdisc) #else write_seqcount_end(&qdisc->running); #endif - if (qdisc->flags & TCQ_F_NOLOCK) + if (qdisc->flags & TCQ_F_NOLOCK) { spin_unlock(&qdisc->seqlock); + + if (unlikely(test_bit(__QDISC_STATE_MISSED, + &qdisc->state))) { + clear_bit(__QDISC_STATE_MISSED, &qdisc->state); + __netif_schedule(qdisc); + } + } } static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) @@ -1173,7 +1218,7 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, old = *pold; *pold = new; if (old != NULL) - qdisc_tree_flush_backlog(old); + qdisc_purge_queue(old); sch_tree_unlock(sch); return old; diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 06e1dee..8c6b04f 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -328,8 +328,7 @@ enum { #define SCTP_SCOPE_POLICY_MAX SCTP_SCOPE_POLICY_LINK /* Based on IPv4 scoping , - * SCTP IPv4 unusable addresses: 0.0.0.0/8, 224.0.0.0/4, 198.18.0.0/24, - * 192.88.99.0/24. + * SCTP IPv4 unusable addresses: 0.0.0.0/8, 224.0.0.0/4, 192.88.99.0/24. * Also, RFC 8.4, non-unicast addresses are not considered valid SCTP * addresses. */ @@ -337,7 +336,6 @@ enum { ((htonl(INADDR_BROADCAST) == a) || \ ipv4_is_multicast(a) || \ ipv4_is_zeronet(a) || \ - ipv4_is_test_198(a) || \ ipv4_is_anycast_6to4(a)) /* Flags used for the bind address copy functions. */ diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 3e8f87a..fd7c3f7 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -466,7 +466,7 @@ struct sctp_af { int saddr); void (*from_sk) (union sctp_addr *, struct sock *sk); - void (*from_addr_param) (union sctp_addr *, + bool (*from_addr_param) (union sctp_addr *, union sctp_addr_param *, __be16 port, int iif); int (*to_addr_param) (const union sctp_addr *, diff --git a/include/net/sock.h b/include/net/sock.h index b2b374b..5f58ffa 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1865,7 +1865,8 @@ static inline u32 net_tx_rndhash(void) static inline void sk_set_txhash(struct sock *sk) { - sk->sk_txhash = net_tx_rndhash(); + /* This pairs with READ_ONCE() in skb_set_hash_from_sk() */ + WRITE_ONCE(sk->sk_txhash, net_tx_rndhash()); } static inline void sk_rethink_txhash(struct sock *sk) @@ -2130,9 +2131,12 @@ static inline void sock_poll_wait(struct file *filp, struct socket *sock, static inline void skb_set_hash_from_sk(struct sk_buff *skb, struct sock *sk) { - if (sk->sk_txhash) { + /* This pairs with WRITE_ONCE() in sk_set_txhash() */ + u32 txhash = READ_ONCE(sk->sk_txhash); + + if (txhash) { skb->l4_hash = 1; - skb->hash = sk->sk_txhash; + skb->hash = txhash; } } @@ -2155,6 +2159,17 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) sk_mem_charge(sk, skb->truesize); } +static inline __must_check bool skb_set_owner_sk_safe(struct sk_buff *skb, struct sock *sk) +{ + if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { + skb_orphan(skb); + skb->destructor = sock_efree; + skb->sk = sk; + return true; + } + return false; +} + void sk_reset_timer(struct sock *sk, struct timer_list *timer, unsigned long expires); diff --git a/include/net/tc_act/tc_vlan.h b/include/net/tc_act/tc_vlan.h index 4e25024..add6fb5 100644 --- a/include/net/tc_act/tc_vlan.h +++ b/include/net/tc_act/tc_vlan.h @@ -14,6 +14,7 @@ struct tcf_vlan_params { u16 tcfv_push_vid; __be16 tcfv_push_proto; u8 tcfv_push_prio; + bool tcfv_push_prio_exists; struct rcu_head rcu; }; diff --git a/include/net/tcp.h b/include/net/tcp.h index 3771792..b914959 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -619,6 +619,7 @@ static inline void tcp_clear_xmit_timers(struct sock *sk) unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu); unsigned int tcp_current_mss(struct sock *sk); +u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when); /* Bound MSS / TSO packet size with the half of the window */ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) @@ -1408,8 +1409,13 @@ static inline int tcp_full_space(const struct sock *sk) */ static inline bool tcp_rmem_pressure(const struct sock *sk) { - int rcvbuf = READ_ONCE(sk->sk_rcvbuf); - int threshold = rcvbuf - (rcvbuf >> 3); + int rcvbuf, threshold; + + if (tcp_under_memory_pressure(sk)) + return true; + + rcvbuf = READ_ONCE(sk->sk_rcvbuf); + threshold = rcvbuf - (rcvbuf >> 3); return atomic_read(&sk->sk_rmem_alloc) > threshold; } @@ -2030,7 +2036,7 @@ void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb); void tcp_newreno_mark_lost(struct sock *sk, bool snd_una_advanced); extern s32 tcp_rack_skb_timeout(struct tcp_sock *tp, struct sk_buff *skb, u32 reo_wnd); -extern void tcp_rack_mark_lost(struct sock *sk); +extern bool tcp_rack_mark_lost(struct sock *sk); extern void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq, u64 xmit_time); extern void tcp_rack_reo_timeout(struct sock *sk); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index c00b9ae..8ce6385 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1098,7 +1098,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir, return __xfrm_policy_check(sk, ndir, skb, family); return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) || - (skb_dst(skb)->flags & DST_NOPOLICY) || + (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || __xfrm_policy_check(sk, ndir, skb, family); } @@ -1543,6 +1543,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); int xfrm_init_replay(struct xfrm_state *x); +u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu); u32 xfrm_state_mtu(struct xfrm_state *x, int mtu); int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload); int xfrm_init_state(struct xfrm_state *x); diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 2568cb0..fac8e89 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -249,7 +249,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *, struct fc_frame *); /* libfcoe funcs */ -u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); +u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], unsigned int, unsigned int); int fcoe_libfc_config(struct fc_lport *, struct fcoe_ctlr *, const struct libfc_function_template *, int init_fcp); u32 fcoe_fc_crc(struct fc_frame *fp); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index b3bbd10..2b5f972 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -195,12 +195,6 @@ struct iscsi_conn { unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */ - /* abort */ - wait_queue_head_t ehwait; /* used in eh_abort() */ - struct iscsi_tm tmhdr; - struct timer_list tmf_timer; - int tmf_state; /* see TMF_INITIAL, etc.*/ - /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ unsigned max_xmit_dlength; /* target_max_recv_dsl */ @@ -270,6 +264,11 @@ struct iscsi_session { * and recv lock. */ struct mutex eh_mutex; + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/ /* iSCSI session-wide sequencing */ uint32_t cmdsn; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 325ae73..71c7841 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -423,6 +423,8 @@ extern void iscsi_remove_session(struct iscsi_cls_session *session); extern void iscsi_free_session(struct iscsi_cls_session *session); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, int dd_size, uint32_t cid); +extern void iscsi_put_conn(struct iscsi_cls_conn *conn); +extern void iscsi_get_conn(struct iscsi_cls_conn *conn); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index f657fd8..f38947b 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -112,6 +112,11 @@ struct nhlt_vendor_dmic_array_config { /* TODO add vendor mic config */ } __packed; +enum { + NHLT_CONFIG_TYPE_GENERIC = 0, + NHLT_CONFIG_TYPE_MIC_ARRAY = 1 +}; + enum { NHLT_MIC_ARRAY_2CH_SMALL = 0xa, NHLT_MIC_ARRAY_2CH_BIG = 0xb, diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 51b6f50..0deeff9 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -69,6 +69,7 @@ int transport_backend_register(const struct target_backend_ops *); void target_backend_unregister(const struct target_backend_ops *); void target_complete_cmd(struct se_cmd *, u8); +void target_set_cmd_data_length(struct se_cmd *, int); void target_complete_cmd_with_length(struct se_cmd *, u8, int); void transport_copy_sense_to_cmd(struct se_cmd *, unsigned char *); diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index c612cab..61af4af 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -111,6 +111,34 @@ enum afs_vl_operation { afs_VL_GetCapabilities = 65537, /* AFS Get VL server capabilities */ }; +enum afs_cm_operation { + afs_CB_CallBack = 204, /* AFS break callback promises */ + afs_CB_InitCallBackState = 205, /* AFS initialise callback state */ + afs_CB_Probe = 206, /* AFS probe client */ + afs_CB_GetLock = 207, /* AFS get contents of CM lock table */ + afs_CB_GetCE = 208, /* AFS get cache file description */ + afs_CB_GetXStatsVersion = 209, /* AFS get version of extended statistics */ + afs_CB_GetXStats = 210, /* AFS get contents of extended statistics data */ + afs_CB_InitCallBackState3 = 213, /* AFS initialise callback state, version 3 */ + afs_CB_ProbeUuid = 214, /* AFS check the client hasn't rebooted */ +}; + +enum yfs_cm_operation { + yfs_CB_Probe = 206, /* YFS probe client */ + yfs_CB_GetLock = 207, /* YFS get contents of CM lock table */ + yfs_CB_XStatsVersion = 209, /* YFS get version of extended statistics */ + yfs_CB_GetXStats = 210, /* YFS get contents of extended statistics data */ + yfs_CB_InitCallBackState3 = 213, /* YFS initialise callback state, version 3 */ + yfs_CB_ProbeUuid = 214, /* YFS check the client hasn't rebooted */ + yfs_CB_GetServerPrefs = 215, + yfs_CB_GetCellServDV = 216, + yfs_CB_GetLocalCell = 217, + yfs_CB_GetCacheConfig = 218, + yfs_CB_GetCellByNum = 65537, + yfs_CB_TellMeAboutYourself = 65538, /* get client capabilities */ + yfs_CB_CallBack = 64204, +}; + enum afs_edit_dir_op { afs_edit_dir_create, afs_edit_dir_create_error, @@ -312,6 +340,32 @@ enum afs_cb_break_reason { EM(afs_YFSVL_GetEndpoints, "YFSVL.GetEndpoints") \ E_(afs_VL_GetCapabilities, "VL.GetCapabilities") +#define afs_cm_operations \ + EM(afs_CB_CallBack, "CB.CallBack") \ + EM(afs_CB_InitCallBackState, "CB.InitCallBackState") \ + EM(afs_CB_Probe, "CB.Probe") \ + EM(afs_CB_GetLock, "CB.GetLock") \ + EM(afs_CB_GetCE, "CB.GetCE") \ + EM(afs_CB_GetXStatsVersion, "CB.GetXStatsVersion") \ + EM(afs_CB_GetXStats, "CB.GetXStats") \ + EM(afs_CB_InitCallBackState3, "CB.InitCallBackState3") \ + E_(afs_CB_ProbeUuid, "CB.ProbeUuid") + +#define yfs_cm_operations \ + EM(yfs_CB_Probe, "YFSCB.Probe") \ + EM(yfs_CB_GetLock, "YFSCB.GetLock") \ + EM(yfs_CB_XStatsVersion, "YFSCB.XStatsVersion") \ + EM(yfs_CB_GetXStats, "YFSCB.GetXStats") \ + EM(yfs_CB_InitCallBackState3, "YFSCB.InitCallBackState3") \ + EM(yfs_CB_ProbeUuid, "YFSCB.ProbeUuid") \ + EM(yfs_CB_GetServerPrefs, "YFSCB.GetServerPrefs") \ + EM(yfs_CB_GetCellServDV, "YFSCB.GetCellServDV") \ + EM(yfs_CB_GetLocalCell, "YFSCB.GetLocalCell") \ + EM(yfs_CB_GetCacheConfig, "YFSCB.GetCacheConfig") \ + EM(yfs_CB_GetCellByNum, "YFSCB.GetCellByNum") \ + EM(yfs_CB_TellMeAboutYourself, "YFSCB.TellMeAboutYourself") \ + E_(yfs_CB_CallBack, "YFSCB.CallBack") + #define afs_edit_dir_ops \ EM(afs_edit_dir_create, "create") \ EM(afs_edit_dir_create_error, "c_fail") \ @@ -442,6 +496,8 @@ afs_call_traces; afs_server_traces; afs_fs_operations; afs_vl_operations; +afs_cm_operations; +yfs_cm_operations; afs_edit_dir_ops; afs_edit_dir_reasons; afs_eproto_causes; @@ -522,20 +578,21 @@ TRACE_EVENT(afs_cb_call, TP_STRUCT__entry( __field(unsigned int, call ) - __field(const char *, name ) __field(u32, op ) + __field(u16, service_id ) ), TP_fast_assign( __entry->call = call->debug_id; - __entry->name = call->type->name; __entry->op = call->operation_ID; + __entry->service_id = call->service_id; ), - TP_printk("c=%08x %s o=%u", + TP_printk("c=%08x %s", __entry->call, - __entry->name, - __entry->op) + __entry->service_id == 2501 ? + __print_symbolic(__entry->op, yfs_cm_operations) : + __print_symbolic(__entry->op, afs_cm_operations)) ); TRACE_EVENT(afs_call, diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index a8af22e..011e8fa 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -20,7 +20,6 @@ {I_CLEAR, "I_CLEAR"}, \ {I_SYNC, "I_SYNC"}, \ {I_DIRTY_TIME, "I_DIRTY_TIME"}, \ - {I_DIRTY_TIME_EXPIRED, "I_DIRTY_TIME_EXPIRED"}, \ {I_REFERENCED, "I_REFERENCED"} \ ) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 7857aa4..8d465e5 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -223,7 +223,7 @@ enum tunable_id { ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ /* * Add your fresh new tunable attribute above and remember to update - * tunable_strings[] in net/core/ethtool.c + * tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_TUNABLE_COUNT, }; @@ -287,7 +287,7 @@ enum phy_tunable_id { ETHTOOL_PHY_EDPD, /* * Add your fresh new phy tunable attribute above and remember to update - * phy_tunable_strings[] in net/core/ethtool.c + * phy_tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_PHY_TUNABLE_COUNT, }; diff --git a/include/uapi/linux/icmpv6.h b/include/uapi/linux/icmpv6.h index 2622b5a..9a31ea2 100644 --- a/include/uapi/linux/icmpv6.h +++ b/include/uapi/linux/icmpv6.h @@ -137,6 +137,7 @@ struct icmp6hdr { #define ICMPV6_HDR_FIELD 0 #define ICMPV6_UNK_NEXTHDR 1 #define ICMPV6_UNK_OPTION 2 +#define ICMPV6_HDR_INCOMP 3 /* * constants for (set|get)sockopt diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h index e7ad9d3..60e1241 100644 --- a/include/uapi/linux/in.h +++ b/include/uapi/linux/in.h @@ -284,6 +284,9 @@ struct sockaddr_in { /* Address indicating an error return. */ #define INADDR_NONE ((unsigned long int) 0xffffffff) +/* Dummy address for src of ICMP replies if no real address is set (RFC7600). */ +#define INADDR_DUMMY ((unsigned long int) 0xc0000008) + /* Network number for local host loopback. */ #define IN_LOOPBACKNET 127 diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 472cd5b..311a57f 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -607,6 +607,7 @@ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */ +#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ diff --git a/include/uapi/linux/netfilter/nfnetlink_cthelper.h b/include/uapi/linux/netfilter/nfnetlink_cthelper.h index a13137a..70af020 100644 --- a/include/uapi/linux/netfilter/nfnetlink_cthelper.h +++ b/include/uapi/linux/netfilter/nfnetlink_cthelper.h @@ -5,7 +5,7 @@ #define NFCT_HELPER_STATUS_DISABLED 0 #define NFCT_HELPER_STATUS_ENABLED 1 -enum nfnl_acct_msg_types { +enum nfnl_cthelper_msg_types { NFNL_MSG_CTHELPER_NEW, NFNL_MSG_CTHELPER_GET, NFNL_MSG_CTHELPER_DEL, diff --git a/include/uapi/linux/netfilter/xt_SECMARK.h b/include/uapi/linux/netfilter/xt_SECMARK.h index 1f2a708..beb2cad 100644 --- a/include/uapi/linux/netfilter/xt_SECMARK.h +++ b/include/uapi/linux/netfilter/xt_SECMARK.h @@ -20,4 +20,10 @@ struct xt_secmark_target_info { char secctx[SECMARK_SECCTX_MAX]; }; +struct xt_secmark_target_info_v1 { + __u8 mode; + char secctx[SECMARK_SECCTX_MAX]; + __u32 secid; +}; + #endif /*_XT_SECMARK_H_target */ diff --git a/include/uapi/linux/tty_flags.h b/include/uapi/linux/tty_flags.h index 900a32e..6a3ac49 100644 --- a/include/uapi/linux/tty_flags.h +++ b/include/uapi/linux/tty_flags.h @@ -39,7 +39,7 @@ * WARNING: These flags are no longer used and have been superceded by the * TTY_PORT_ flags in the iflags field (and not userspace-visible) */ -#ifndef _KERNEL_ +#ifndef __KERNEL__ #define ASYNCB_INITIALIZED 31 /* Serial port was initialized */ #define ASYNCB_SUSPENDED 30 /* Serial port is suspended */ #define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */ @@ -81,7 +81,7 @@ #define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI) #define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI) -#ifndef _KERNEL_ +#ifndef __KERNEL__ /* These flags are no longer used (and were always masked from userspace) */ #define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED) #define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE) diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 2b623f3..5633c80 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -364,6 +364,9 @@ struct usb_config_descriptor { /*-------------------------------------------------------------------------*/ +/* USB String descriptors can contain at most 126 characters. */ +#define USB_MAX_STRING_LEN 126 + /* USB_DT_STRING: String descriptor */ struct usb_string_descriptor { __u8 bLength; diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h index d854cb1..bfdae12 100644 --- a/include/uapi/linux/usb/video.h +++ b/include/uapi/linux/usb/video.h @@ -302,9 +302,10 @@ struct uvc_processing_unit_descriptor { __u8 bControlSize; __u8 bmControls[2]; __u8 iProcessing; + __u8 bmVideoStandards; } __attribute__((__packed__)); -#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n)) +#define UVC_DT_PROCESSING_UNIT_SIZE(n) (10+(n)) /* 3.7.2.6. Extension Unit Descriptor */ struct uvc_extension_unit_descriptor { diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 9bc5bc0..a997835 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -157,6 +157,7 @@ gnttab_set_map_op(struct gnttab_map_grant_ref *map, phys_addr_t addr, map->flags = flags; map->ref = ref; map->dom = domid; + map->status = 1; /* arbitrary positive value */ } static inline void diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index eba01ab..14d47ed 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -187,8 +187,6 @@ void xs_suspend_cancel(void); struct work_struct; -void xenbus_probe(struct work_struct *); - #define XENBUS_IS_ERR_READ(str) ({ \ if (!IS_ERR(str) && strlen(str) == 0) { \ kfree(str); \