mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge tag 'ASB-2020-12-05_4.19-stable' of https://android.googlesource.com/kernel/common
https://source.android.com/security/bulletin/2020-12-01 CVE-2020-0444 CVE-2020-0465 CVE-2020-0466 * tag 'ASB-2020-12-05_4.19-stable': (636 commits) ANDROID: kbuild: use grep -F instead of fgrep ANDROID: GKI: usb: gadget: support claiming indexed endpoints by name UPSTREAM: arm64: sysreg: Clean up instructions for modifying PSTATE fields Revert "Revert "ANDROID: clang: update to 11.0.5"" ANDROID: kbuild: speed up ksym_dep_filter Revert "drm/atomic_helper: Stop modesets on unregistered connectors harder" Linux 4.19.161 USB: core: Fix regression in Hercules audio card x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb usb: gadget: Fix memleak in gadgetfs_fill_super USB: quirks: Add USB_QUIRK_DISCONNECT_SUSPEND quirk for Lenovo A630Z TIO built-in usb-audio card usb: gadget: f_midi: Fix memleak in f_midi_alloc USB: core: Change %pK for __user pointers to %px perf probe: Fix to die_entrypc() returns error correctly can: m_can: fix nominal bitiming tseg2 min for version >= 3.1 platform/x86: toshiba_acpi: Fix the wrong variable assignment platform/x86: thinkpad_acpi: Send tablet mode switch at wakeup time can: gs_usb: fix endianess problem with candleLight firmware ... Change-Id: I82ccfc3d6561d3ef3b1b06ac98d48fac997c8fb6 Conflicts: drivers/pinctrl/pinctrl-rockchip.c drivers/usb/dwc3/gadget.c drivers/usb/host/xhci.c drivers/usb/host/xhci.h
This commit is contained in:
@@ -2577,6 +2577,8 @@
|
||||
mds=off [X86]
|
||||
tsx_async_abort=off [X86]
|
||||
kvm.nx_huge_pages=off [X86]
|
||||
no_entry_flush [PPC]
|
||||
no_uaccess_flush [PPC]
|
||||
|
||||
Exceptions:
|
||||
This does not have any effect on
|
||||
@@ -2887,6 +2889,8 @@
|
||||
|
||||
noefi Disable EFI runtime services support.
|
||||
|
||||
no_entry_flush [PPC] Don't flush the L1-D cache when entering the kernel.
|
||||
|
||||
noexec [IA-64]
|
||||
|
||||
noexec [X86]
|
||||
@@ -2936,6 +2940,9 @@
|
||||
nospec_store_bypass_disable
|
||||
[HW] Disable all mitigations for the Speculative Store Bypass vulnerability
|
||||
|
||||
no_uaccess_flush
|
||||
[PPC] Don't flush the L1-D cache after accessing user data.
|
||||
|
||||
noxsave [BUGS=X86] Disables x86 extended register state save
|
||||
and restore using xsave. The kernel will fallback to
|
||||
enabling legacy floating-point and sse state.
|
||||
@@ -5299,6 +5306,14 @@
|
||||
with /sys/devices/system/xen_memory/xen_memory0/scrub_pages.
|
||||
Default value controlled with CONFIG_XEN_SCRUB_PAGES_DEFAULT.
|
||||
|
||||
xen.event_eoi_delay= [XEN]
|
||||
How long to delay EOI handling in case of event
|
||||
storms (jiffies). Default is 10.
|
||||
|
||||
xen.event_loop_timeout= [XEN]
|
||||
After which time (jiffies) the event handling loop
|
||||
should start to delay EOI handling. Default is 2.
|
||||
|
||||
xirc2ps_cs= [NET,PCMCIA]
|
||||
Format:
|
||||
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
|
||||
|
||||
@@ -29,8 +29,7 @@ whole range, 0-255, dividing the angular value by 1.41. The enum
|
||||
:c:type:`v4l2_hsv_encoding` specifies which encoding is used.
|
||||
|
||||
.. note:: The default R'G'B' quantization is full range for all
|
||||
colorspaces except for BT.2020 which uses limited range R'G'B'
|
||||
quantization.
|
||||
colorspaces. HSV formats are always full range.
|
||||
|
||||
.. tabularcolumns:: |p{6.0cm}|p{11.5cm}|
|
||||
|
||||
@@ -162,8 +161,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum
|
||||
- Details
|
||||
* - ``V4L2_QUANTIZATION_DEFAULT``
|
||||
- Use the default quantization encoding as defined by the
|
||||
colorspace. This is always full range for R'G'B' (except for the
|
||||
BT.2020 colorspace) and HSV. It is usually limited range for Y'CbCr.
|
||||
colorspace. This is always full range for R'G'B' and HSV.
|
||||
It is usually limited range for Y'CbCr.
|
||||
* - ``V4L2_QUANTIZATION_FULL_RANGE``
|
||||
- Use the full range quantization encoding. I.e. the range [0…1] is
|
||||
mapped to [0…255] (with possible clipping to [1…254] to avoid the
|
||||
@@ -173,4 +172,4 @@ whole range, 0-255, dividing the angular value by 1.41. The enum
|
||||
* - ``V4L2_QUANTIZATION_LIM_RANGE``
|
||||
- Use the limited range quantization encoding. I.e. the range [0…1]
|
||||
is mapped to [16…235]. Cb and Cr are mapped from [-0.5…0.5] to
|
||||
[16…240].
|
||||
[16…240]. Limited Range cannot be used with HSV.
|
||||
|
||||
@@ -370,9 +370,8 @@ Colorspace BT.2020 (V4L2_COLORSPACE_BT2020)
|
||||
The :ref:`itu2020` standard defines the colorspace used by Ultra-high
|
||||
definition television (UHDTV). The default transfer function is
|
||||
``V4L2_XFER_FUNC_709``. The default Y'CbCr encoding is
|
||||
``V4L2_YCBCR_ENC_BT2020``. The default R'G'B' quantization is limited
|
||||
range (!), and so is the default Y'CbCr quantization. The chromaticities
|
||||
of the primary colors and the white reference are:
|
||||
``V4L2_YCBCR_ENC_BT2020``. The default Y'CbCr quantization is limited range.
|
||||
The chromaticities of the primary colors and the white reference are:
|
||||
|
||||
|
||||
|
||||
|
||||
8
Makefile
8
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 19
|
||||
SUBLEVEL = 154
|
||||
SUBLEVEL = 161
|
||||
EXTRAVERSION =
|
||||
NAME = "People's Front"
|
||||
|
||||
@@ -525,11 +525,7 @@ endif
|
||||
|
||||
ifeq ($(cc-name),clang)
|
||||
ifneq ($(CROSS_COMPILE),)
|
||||
CLANG_TRIPLE ?= $(CROSS_COMPILE)
|
||||
CLANG_FLAGS += --target=$(notdir $(CLANG_TRIPLE:%-=%))
|
||||
ifeq ($(shell $(srctree)/scripts/clang-android.sh $(CC) $(CLANG_FLAGS)), y)
|
||||
$(error "Clang with Android --target detected. Did you specify CLANG_TRIPLE?")
|
||||
endif
|
||||
CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
|
||||
GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
|
||||
CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
|
||||
GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,7 @@
|
||||
bus_for_each_dev
|
||||
bus_register
|
||||
bus_unregister
|
||||
call_rcu
|
||||
cancel_delayed_work
|
||||
cancel_delayed_work_sync
|
||||
cancel_work_sync
|
||||
@@ -287,7 +288,6 @@
|
||||
get_cpu_device
|
||||
get_device
|
||||
__get_free_pages
|
||||
get_next_event_cpu
|
||||
get_pid_task
|
||||
get_random_bytes
|
||||
__get_task_comm
|
||||
@@ -467,6 +467,7 @@
|
||||
__ll_sc_atomic64_fetch_or
|
||||
__ll_sc_atomic64_or
|
||||
__ll_sc_atomic64_sub
|
||||
__ll_sc_atomic64_sub_return
|
||||
__ll_sc_atomic_add
|
||||
__ll_sc_atomic_add_return
|
||||
__ll_sc_atomic_sub
|
||||
@@ -491,6 +492,10 @@
|
||||
__memcpy_toio
|
||||
memdup_user
|
||||
memmove
|
||||
mempool_alloc
|
||||
mempool_free
|
||||
mempool_kfree
|
||||
mempool_kmalloc
|
||||
memremap
|
||||
memset
|
||||
__memset_io
|
||||
@@ -506,6 +511,7 @@
|
||||
module_put
|
||||
__msecs_to_jiffies
|
||||
msleep
|
||||
msleep_interruptible
|
||||
__mutex_init
|
||||
mutex_lock
|
||||
mutex_lock_interruptible
|
||||
@@ -1210,15 +1216,24 @@
|
||||
crc_ccitt_table
|
||||
kernel_restart
|
||||
kernel_setsockopt
|
||||
mempool_alloc
|
||||
mempool_create
|
||||
mempool_destroy
|
||||
mempool_free
|
||||
mempool_kfree
|
||||
mempool_kmalloc
|
||||
send_sig_info
|
||||
time64_to_tm
|
||||
|
||||
# required by dm-user.ko
|
||||
bio_advance
|
||||
bio_endio
|
||||
bio_put
|
||||
_copy_from_iter
|
||||
copy_page_from_iter
|
||||
copy_page_to_iter
|
||||
_copy_to_iter
|
||||
dm_register_target
|
||||
dm_unregister_target
|
||||
mempool_exit
|
||||
mempool_init
|
||||
|
||||
# required by dwc3-haps.ko
|
||||
pcim_enable_device
|
||||
__pci_register_driver
|
||||
@@ -1315,9 +1330,6 @@
|
||||
proc_create
|
||||
seq_write
|
||||
|
||||
# required by google-battery.ko
|
||||
simple_strtoull
|
||||
|
||||
# required by google-bms.ko
|
||||
full_name_hash
|
||||
|
||||
@@ -1362,7 +1374,6 @@
|
||||
__break_lease
|
||||
clear_inode
|
||||
__close_fd
|
||||
crc32_le
|
||||
d_add
|
||||
d_drop
|
||||
deactivate_locked_super
|
||||
@@ -1370,6 +1381,8 @@
|
||||
dget_parent
|
||||
d_instantiate
|
||||
d_make_root
|
||||
down_read_killable
|
||||
down_write_killable
|
||||
dput
|
||||
flush_dcache_page
|
||||
fs_kobj
|
||||
@@ -1419,6 +1432,7 @@
|
||||
user_path_at_empty
|
||||
vfs_create
|
||||
vfs_fallocate
|
||||
vfs_fsync
|
||||
vfs_getattr
|
||||
vfs_getxattr
|
||||
vfs_link
|
||||
@@ -1428,19 +1442,19 @@
|
||||
vfs_rmdir
|
||||
vfs_setxattr
|
||||
vfs_unlink
|
||||
ZSTD_decompressStream
|
||||
ZSTD_DStreamWorkspaceBound
|
||||
ZSTD_initDStream
|
||||
|
||||
# required by ion-alloc.ko
|
||||
dma_buf_export
|
||||
dma_get_device_base
|
||||
dma_get_size
|
||||
__ll_sc_atomic64_sub_return
|
||||
mm_event_count
|
||||
__next_zones_zonelist
|
||||
ptr_to_hashval
|
||||
sched_setattr
|
||||
split_page
|
||||
vm_map_ram
|
||||
vm_unmap_ram
|
||||
zone_watermark_ok_safe
|
||||
|
||||
# required by ipa3.ko
|
||||
@@ -2223,7 +2237,6 @@
|
||||
# required by sctp.ko
|
||||
__bitmap_shift_right
|
||||
__bitmap_weight
|
||||
call_rcu
|
||||
compat_ip_getsockopt
|
||||
compat_ip_setsockopt
|
||||
compat_ipv6_getsockopt
|
||||
@@ -2518,100 +2531,6 @@
|
||||
trace_output_call
|
||||
utf16s_to_utf8s
|
||||
|
||||
# required by wlan.ko
|
||||
bitmap_print_to_pagebuf
|
||||
__cfg80211_alloc_event_skb
|
||||
__cfg80211_alloc_reply_skb
|
||||
cfg80211_ap_stopped
|
||||
cfg80211_calculate_bitrate
|
||||
cfg80211_chandef_create
|
||||
cfg80211_ch_switch_notify
|
||||
cfg80211_connect_done
|
||||
cfg80211_del_sta_sinfo
|
||||
cfg80211_disconnected
|
||||
cfg80211_external_auth_request
|
||||
cfg80211_ft_event
|
||||
cfg80211_get_bss
|
||||
cfg80211_gtk_rekey_notify
|
||||
cfg80211_ibss_joined
|
||||
cfg80211_inform_bss_frame_data
|
||||
cfg80211_mgmt_tx_status
|
||||
cfg80211_michael_mic_failure
|
||||
cfg80211_new_sta
|
||||
cfg80211_pmksa_candidate_notify
|
||||
cfg80211_put_bss
|
||||
cfg80211_ready_on_channel
|
||||
cfg80211_remain_on_channel_expired
|
||||
cfg80211_roamed
|
||||
cfg80211_rx_mgmt
|
||||
cfg80211_rx_unprot_mlme_mgmt
|
||||
cfg80211_scan_done
|
||||
cfg80211_sched_scan_results
|
||||
__cfg80211_send_event_skb
|
||||
cfg80211_tdls_oper_request
|
||||
cfg80211_unlink_bss
|
||||
cfg80211_update_owe_info_event
|
||||
cfg80211_vendor_cmd_reply
|
||||
complete_and_exit
|
||||
cpufreq_quick_get_max
|
||||
__cpuhp_remove_state
|
||||
cpu_topology
|
||||
crypto_aead_setauthsize
|
||||
crypto_aead_setkey
|
||||
crypto_alloc_aead
|
||||
crypto_alloc_base
|
||||
crypto_alloc_skcipher
|
||||
crypto_shash_final
|
||||
crypto_shash_update
|
||||
dev_alloc_name
|
||||
dump_stack
|
||||
hex2bin
|
||||
hex_to_bin
|
||||
ieee80211_channel_to_frequency
|
||||
ieee80211_frequency_to_channel
|
||||
ieee80211_get_channel
|
||||
ieee80211_hdrlen
|
||||
iommu_iova_to_phys
|
||||
irq_set_affinity_hint
|
||||
mac_pton
|
||||
msleep_interruptible
|
||||
netif_tx_stop_all_queues
|
||||
netlink_broadcast
|
||||
__netlink_kernel_create
|
||||
netlink_kernel_release
|
||||
nla_put_64bit
|
||||
nla_strlcpy
|
||||
param_get_string
|
||||
param_ops_byte
|
||||
param_set_copystring
|
||||
pci_read_config_dword
|
||||
pci_read_config_word
|
||||
pci_write_config_dword
|
||||
pci_write_config_word
|
||||
PDE_DATA
|
||||
pm_freezing
|
||||
pm_system_wakeup
|
||||
proc_create_data
|
||||
proc_mkdir
|
||||
register_netevent_notifier
|
||||
register_sysctl_table
|
||||
regulatory_set_wiphy_regd
|
||||
rtnl_lock
|
||||
save_stack_trace_tsk
|
||||
schedule_timeout_interruptible
|
||||
seq_vprintf
|
||||
set_cpus_allowed_ptr
|
||||
skip_spaces
|
||||
strchrnul
|
||||
unregister_netevent_notifier
|
||||
unregister_sysctl_table
|
||||
vprintk
|
||||
wiphy_free
|
||||
wiphy_new_nm
|
||||
wiphy_register
|
||||
wiphy_unregister
|
||||
wireless_send_event
|
||||
|
||||
# required by usb-audio-qmi.ko
|
||||
find_snd_usb_substream
|
||||
snd_usb_enable_audio_stream
|
||||
@@ -2684,6 +2603,99 @@
|
||||
irq_create_mapping
|
||||
regmap_irq_get_virq
|
||||
|
||||
# required by wlan.ko
|
||||
bitmap_print_to_pagebuf
|
||||
__cfg80211_alloc_event_skb
|
||||
__cfg80211_alloc_reply_skb
|
||||
cfg80211_ap_stopped
|
||||
cfg80211_calculate_bitrate
|
||||
cfg80211_chandef_create
|
||||
cfg80211_ch_switch_notify
|
||||
cfg80211_connect_done
|
||||
cfg80211_del_sta_sinfo
|
||||
cfg80211_disconnected
|
||||
cfg80211_external_auth_request
|
||||
cfg80211_ft_event
|
||||
cfg80211_get_bss
|
||||
cfg80211_gtk_rekey_notify
|
||||
cfg80211_ibss_joined
|
||||
cfg80211_inform_bss_frame_data
|
||||
cfg80211_mgmt_tx_status
|
||||
cfg80211_michael_mic_failure
|
||||
cfg80211_new_sta
|
||||
cfg80211_pmksa_candidate_notify
|
||||
cfg80211_put_bss
|
||||
cfg80211_ready_on_channel
|
||||
cfg80211_remain_on_channel_expired
|
||||
cfg80211_roamed
|
||||
cfg80211_rx_mgmt
|
||||
cfg80211_rx_unprot_mlme_mgmt
|
||||
cfg80211_scan_done
|
||||
cfg80211_sched_scan_results
|
||||
__cfg80211_send_event_skb
|
||||
cfg80211_tdls_oper_request
|
||||
cfg80211_unlink_bss
|
||||
cfg80211_update_owe_info_event
|
||||
cfg80211_vendor_cmd_reply
|
||||
complete_and_exit
|
||||
cpufreq_quick_get_max
|
||||
__cpuhp_remove_state
|
||||
cpu_topology
|
||||
crypto_aead_setauthsize
|
||||
crypto_aead_setkey
|
||||
crypto_alloc_aead
|
||||
crypto_alloc_base
|
||||
crypto_alloc_skcipher
|
||||
crypto_shash_final
|
||||
crypto_shash_update
|
||||
dev_alloc_name
|
||||
dump_stack
|
||||
hex2bin
|
||||
hex_to_bin
|
||||
ieee80211_channel_to_frequency
|
||||
ieee80211_frequency_to_channel
|
||||
ieee80211_get_channel
|
||||
ieee80211_hdrlen
|
||||
iommu_iova_to_phys
|
||||
irq_set_affinity_hint
|
||||
mac_pton
|
||||
netif_tx_stop_all_queues
|
||||
netlink_broadcast
|
||||
__netlink_kernel_create
|
||||
netlink_kernel_release
|
||||
nla_put_64bit
|
||||
nla_strlcpy
|
||||
param_get_string
|
||||
param_ops_byte
|
||||
param_set_copystring
|
||||
pci_read_config_dword
|
||||
pci_read_config_word
|
||||
pci_write_config_dword
|
||||
pci_write_config_word
|
||||
PDE_DATA
|
||||
pm_freezing
|
||||
pm_system_wakeup
|
||||
proc_create_data
|
||||
proc_mkdir
|
||||
register_netevent_notifier
|
||||
register_sysctl_table
|
||||
regulatory_set_wiphy_regd
|
||||
rtnl_lock
|
||||
save_stack_trace_tsk
|
||||
schedule_timeout_interruptible
|
||||
seq_vprintf
|
||||
set_cpus_allowed_ptr
|
||||
skip_spaces
|
||||
strchrnul
|
||||
unregister_netevent_notifier
|
||||
unregister_sysctl_table
|
||||
vprintk
|
||||
wiphy_free
|
||||
wiphy_new_nm
|
||||
wiphy_register
|
||||
wiphy_unregister
|
||||
wireless_send_event
|
||||
|
||||
# required by wsa883x_dlkm.ko
|
||||
snd_info_create_module_entry
|
||||
snd_soc_component_exit_regmap
|
||||
@@ -2702,3 +2714,10 @@
|
||||
xhci_resume
|
||||
xhci_run
|
||||
xhci_suspend
|
||||
|
||||
# preserved by --additions-only
|
||||
crc32_le
|
||||
get_next_event_cpu
|
||||
simple_strtoull
|
||||
vm_map_ram
|
||||
vm_unmap_ram
|
||||
|
||||
@@ -366,6 +366,13 @@ config HAVE_RCU_TABLE_FREE
|
||||
config HAVE_RCU_TABLE_INVALIDATE
|
||||
bool
|
||||
|
||||
config ARCH_WANT_IRQS_OFF_ACTIVATE_MM
|
||||
bool
|
||||
help
|
||||
Temporary select until all architectures can be converted to have
|
||||
irqs disabled over activate_mm. Architectures that do IPI based TLB
|
||||
shootdowns should enable this.
|
||||
|
||||
config ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
bool
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ END(EV_Extension)
|
||||
tracesys:
|
||||
; save EFA in case tracer wants the PC of traced task
|
||||
; using ERET won't work since next-PC has already committed
|
||||
lr r12, [efa]
|
||||
GET_CURR_TASK_FIELD_PTR TASK_THREAD, r11
|
||||
st r12, [r11, THREAD_FAULT_ADDR] ; thread.fault_address
|
||||
|
||||
@@ -198,9 +199,15 @@ tracesys_exit:
|
||||
; Breakpoint TRAP
|
||||
; ---------------------------------------------
|
||||
trap_with_param:
|
||||
mov r0, r12 ; EFA in case ptracer/gdb wants stop_pc
|
||||
|
||||
; stop_pc info by gdb needs this info
|
||||
lr r0, [efa]
|
||||
mov r1, sp
|
||||
|
||||
; Now that we have read EFA, it is safe to do "fake" rtie
|
||||
; and get out of CPU exception mode
|
||||
FAKE_RET_FROM_EXCPN
|
||||
|
||||
; Save callee regs in case gdb wants to have a look
|
||||
; SP will grow up by size of CALLEE Reg-File
|
||||
; NOTE: clobbers r12
|
||||
@@ -227,10 +234,6 @@ ENTRY(EV_Trap)
|
||||
|
||||
EXCEPTION_PROLOGUE
|
||||
|
||||
lr r12, [efa]
|
||||
|
||||
FAKE_RET_FROM_EXCPN
|
||||
|
||||
;============ TRAP 1 :breakpoints
|
||||
; Check ECR for trap with arg (PROLOGUE ensures r9 has ECR)
|
||||
bmsk.f 0, r9, 7
|
||||
@@ -238,6 +241,9 @@ ENTRY(EV_Trap)
|
||||
|
||||
;============ TRAP (no param): syscall top level
|
||||
|
||||
; First return from Exception to pure K mode (Exception/IRQs renabled)
|
||||
FAKE_RET_FROM_EXCPN
|
||||
|
||||
; If syscall tracing ongoing, invoke pre-post-hooks
|
||||
GET_CURR_THR_INFO_FLAGS r10
|
||||
btst r10, TIF_SYSCALL_TRACE
|
||||
|
||||
@@ -115,7 +115,7 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
|
||||
int (*consumer_fn) (unsigned int, void *), void *arg)
|
||||
{
|
||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||
int ret = 0;
|
||||
int ret = 0, cnt = 0;
|
||||
unsigned int address;
|
||||
struct unwind_frame_info frame_info;
|
||||
|
||||
@@ -135,6 +135,11 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
|
||||
break;
|
||||
|
||||
frame_info.regs.r63 = frame_info.regs.r31;
|
||||
|
||||
if (cnt++ > 128) {
|
||||
printk("unwinder looping too long, aborting !\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return address; /* return the last address it saw */
|
||||
|
||||
@@ -592,8 +592,10 @@ config ARCH_S3C24XX
|
||||
select HAVE_S3C2410_WATCHDOG if WATCHDOG
|
||||
select HAVE_S3C_RTC if RTC_CLASS
|
||||
select NEED_MACH_IO_H
|
||||
select S3C2410_WATCHDOG
|
||||
select SAMSUNG_ATAGS
|
||||
select USE_OF
|
||||
select WATCHDOG
|
||||
help
|
||||
Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443
|
||||
and S3C2450 SoCs based systems, such as the Simtec Electronics BAST
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "int0", "int1";
|
||||
clocks = <&mcan_clk>, <&l3_iclk_div>;
|
||||
clock-names = "cclk", "hclk";
|
||||
clocks = <&l3_iclk_div>, <&mcan_clk>;
|
||||
clock-names = "hclk", "cclk";
|
||||
bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
MX50_PAD_CSPI_MISO__CSPI_MISO 0x00
|
||||
MX50_PAD_CSPI_MOSI__CSPI_MOSI 0x00
|
||||
MX50_PAD_CSPI_SS0__GPIO4_11 0xc4
|
||||
MX50_PAD_ECSPI1_MOSI__CSPI_SS1 0xf4
|
||||
MX50_PAD_ECSPI1_MOSI__GPIO4_13 0x84
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
&fec {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_enet>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
target-module@56000000 {
|
||||
sgx_module: target-module@56000000 {
|
||||
compatible = "ti,sysc-omap4", "ti,sysc";
|
||||
ti,hwmods = "gpu";
|
||||
reg = <0x5601fc00 0x4>,
|
||||
|
||||
@@ -74,3 +74,13 @@
|
||||
};
|
||||
|
||||
/include/ "omap443x-clocks.dtsi"
|
||||
|
||||
/*
|
||||
* Use dpll_per for sgx at 153.6MHz like droid4 stock v3.0.8 Android kernel
|
||||
*/
|
||||
&sgx_module {
|
||||
assigned-clocks = <&l3_gfx_clkctrl OMAP4_GPU_CLKCTRL 24>,
|
||||
<&dpll_per_m7x2_ck>;
|
||||
assigned-clock-rates = <0>, <153600000>;
|
||||
assigned-clock-parents = <&dpll_per_m7x2_ck>;
|
||||
};
|
||||
|
||||
@@ -98,19 +98,16 @@
|
||||
};
|
||||
|
||||
clocks: clock-controller@e0100000 {
|
||||
compatible = "samsung,s5pv210-clock", "simple-bus";
|
||||
compatible = "samsung,s5pv210-clock";
|
||||
reg = <0xe0100000 0x10000>;
|
||||
clock-names = "xxti", "xusbxti";
|
||||
clocks = <&xxti>, <&xusbxti>;
|
||||
#clock-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
pmu_syscon: syscon@e0108000 {
|
||||
compatible = "samsung-s5pv210-pmu", "syscon";
|
||||
reg = <0xe0108000 0x8000>;
|
||||
};
|
||||
pmu_syscon: syscon@e0108000 {
|
||||
compatible = "samsung-s5pv210-pmu", "syscon";
|
||||
reg = <0xe0108000 0x8000>;
|
||||
};
|
||||
|
||||
pinctrl0: pinctrl@e0200000 {
|
||||
@@ -126,35 +123,28 @@
|
||||
};
|
||||
};
|
||||
|
||||
amba {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
ranges;
|
||||
pdma0: dma@e0900000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
||||
reg = <0xe0900000 0x1000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <19>;
|
||||
clocks = <&clocks CLK_PDMA0>;
|
||||
clock-names = "apb_pclk";
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <8>;
|
||||
#dma-requests = <32>;
|
||||
};
|
||||
|
||||
pdma0: dma@e0900000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
||||
reg = <0xe0900000 0x1000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <19>;
|
||||
clocks = <&clocks CLK_PDMA0>;
|
||||
clock-names = "apb_pclk";
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <8>;
|
||||
#dma-requests = <32>;
|
||||
};
|
||||
|
||||
pdma1: dma@e0a00000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
||||
reg = <0xe0a00000 0x1000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <20>;
|
||||
clocks = <&clocks CLK_PDMA1>;
|
||||
clock-names = "apb_pclk";
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <8>;
|
||||
#dma-requests = <32>;
|
||||
};
|
||||
pdma1: dma@e0a00000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
||||
reg = <0xe0a00000 0x1000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <20>;
|
||||
clocks = <&clocks CLK_PDMA1>;
|
||||
clock-names = "apb_pclk";
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <8>;
|
||||
#dma-requests = <32>;
|
||||
};
|
||||
|
||||
spi0: spi@e1300000 {
|
||||
@@ -227,43 +217,36 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
audio-subsystem {
|
||||
compatible = "samsung,s5pv210-audss", "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
clk_audss: clock-controller@eee10000 {
|
||||
compatible = "samsung,s5pv210-audss-clock";
|
||||
reg = <0xeee10000 0x1000>;
|
||||
clock-names = "hclk", "xxti",
|
||||
"fout_epll",
|
||||
"sclk_audio0";
|
||||
clocks = <&clocks DOUT_HCLKP>, <&xxti>,
|
||||
<&clocks FOUT_EPLL>,
|
||||
<&clocks SCLK_AUDIO0>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
clk_audss: clock-controller@eee10000 {
|
||||
compatible = "samsung,s5pv210-audss-clock";
|
||||
reg = <0xeee10000 0x1000>;
|
||||
clock-names = "hclk", "xxti",
|
||||
"fout_epll",
|
||||
"sclk_audio0";
|
||||
clocks = <&clocks DOUT_HCLKP>, <&xxti>,
|
||||
<&clocks FOUT_EPLL>,
|
||||
<&clocks SCLK_AUDIO0>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
i2s0: i2s@eee30000 {
|
||||
compatible = "samsung,s5pv210-i2s";
|
||||
reg = <0xeee30000 0x1000>;
|
||||
interrupt-parent = <&vic2>;
|
||||
interrupts = <16>;
|
||||
dma-names = "rx", "tx", "tx-sec";
|
||||
dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>;
|
||||
clock-names = "iis",
|
||||
"i2s_opclk0",
|
||||
"i2s_opclk1";
|
||||
clocks = <&clk_audss CLK_I2S>,
|
||||
<&clk_audss CLK_I2S>,
|
||||
<&clk_audss CLK_DOUT_AUD_BUS>;
|
||||
samsung,idma-addr = <0xc0010000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s0_bus>;
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
i2s0: i2s@eee30000 {
|
||||
compatible = "samsung,s5pv210-i2s";
|
||||
reg = <0xeee30000 0x1000>;
|
||||
interrupt-parent = <&vic2>;
|
||||
interrupts = <16>;
|
||||
dma-names = "rx", "tx", "tx-sec";
|
||||
dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>;
|
||||
clock-names = "iis",
|
||||
"i2s_opclk0",
|
||||
"i2s_opclk1";
|
||||
clocks = <&clk_audss CLK_I2S>,
|
||||
<&clk_audss CLK_I2S>,
|
||||
<&clk_audss CLK_DOUT_AUD_BUS>;
|
||||
samsung,idma-addr = <0xc0010000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s0_bus>;
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s1: i2s@e2100000 {
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
trips {
|
||||
cpu_alert0: cpu-alert0 {
|
||||
/* milliCelsius */
|
||||
temperature = <850000>;
|
||||
temperature = <85000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
pinctrl-0 = <&emac_rgmii_pins>;
|
||||
phy-supply = <®_sw>;
|
||||
phy-handle = <&rgmii_phy>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
allwinner,rx-delay-ps = <700>;
|
||||
allwinner,tx-delay-ps = <700>;
|
||||
status = "okay";
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
pinctrl-0 = <&emac_rgmii_pins>;
|
||||
phy-supply = <®_dldo4>;
|
||||
phy-handle = <&rgmii_phy>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -53,11 +53,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
&emac {
|
||||
/* LEDs changed to active high on the plus */
|
||||
/delete-property/ allwinner,leds-active-low;
|
||||
};
|
||||
|
||||
&mmc1 {
|
||||
vmmc-supply = <®_vcc3v3>;
|
||||
bus-width = <4>;
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
pinctrl-0 = <&emac_rgmii_pins>;
|
||||
phy-supply = <®_gmac_3v3>;
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gmac_rgmii_pins>;
|
||||
phy-handle = <&phy1>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
phy-supply = <®_dc1sw>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -167,6 +167,7 @@ CONFIG_SCHED_TRACER=y
|
||||
CONFIG_STACK_TRACER=y
|
||||
CONFIG_FUNCTION_PROFILER=y
|
||||
CONFIG_TEST_KSTRTOX=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_KGDB=y
|
||||
CONFIG_KGDB_KDB=y
|
||||
CONFIG_STRICT_DEVMEM=y
|
||||
|
||||
@@ -159,6 +159,7 @@ CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
|
||||
@@ -52,20 +52,20 @@ int kprobe_exceptions_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data);
|
||||
|
||||
/* optinsn template addresses */
|
||||
extern __visible kprobe_opcode_t optprobe_template_entry;
|
||||
extern __visible kprobe_opcode_t optprobe_template_val;
|
||||
extern __visible kprobe_opcode_t optprobe_template_call;
|
||||
extern __visible kprobe_opcode_t optprobe_template_end;
|
||||
extern __visible kprobe_opcode_t optprobe_template_sub_sp;
|
||||
extern __visible kprobe_opcode_t optprobe_template_add_sp;
|
||||
extern __visible kprobe_opcode_t optprobe_template_restore_begin;
|
||||
extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn;
|
||||
extern __visible kprobe_opcode_t optprobe_template_restore_end;
|
||||
extern __visible kprobe_opcode_t optprobe_template_entry[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_val[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_call[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_end[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_sub_sp[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_add_sp[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_restore_begin[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn[];
|
||||
extern __visible kprobe_opcode_t optprobe_template_restore_end[];
|
||||
|
||||
#define MAX_OPTIMIZED_LENGTH 4
|
||||
#define MAX_OPTINSN_SIZE \
|
||||
((unsigned long)&optprobe_template_end - \
|
||||
(unsigned long)&optprobe_template_entry)
|
||||
((unsigned long)optprobe_template_end - \
|
||||
(unsigned long)optprobe_template_entry)
|
||||
#define RELATIVEJUMP_SIZE 4
|
||||
|
||||
struct arch_optimized_insn {
|
||||
|
||||
@@ -688,6 +688,40 @@ static void disable_single_step(struct perf_event *bp)
|
||||
arch_install_hw_breakpoint(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arm32 hardware does not always report a watchpoint hit address that matches
|
||||
* one of the watchpoints set. It can also report an address "near" the
|
||||
* watchpoint if a single instruction access both watched and unwatched
|
||||
* addresses. There is no straight-forward way, short of disassembling the
|
||||
* offending instruction, to map that address back to the watchpoint. This
|
||||
* function computes the distance of the memory access from the watchpoint as a
|
||||
* heuristic for the likelyhood that a given access triggered the watchpoint.
|
||||
*
|
||||
* See this same function in the arm64 platform code, which has the same
|
||||
* problem.
|
||||
*
|
||||
* The function returns the distance of the address from the bytes watched by
|
||||
* the watchpoint. In case of an exact match, it returns 0.
|
||||
*/
|
||||
static u32 get_distance_from_watchpoint(unsigned long addr, u32 val,
|
||||
struct arch_hw_breakpoint_ctrl *ctrl)
|
||||
{
|
||||
u32 wp_low, wp_high;
|
||||
u32 lens, lene;
|
||||
|
||||
lens = __ffs(ctrl->len);
|
||||
lene = __fls(ctrl->len);
|
||||
|
||||
wp_low = val + lens;
|
||||
wp_high = val + lene;
|
||||
if (addr < wp_low)
|
||||
return wp_low - addr;
|
||||
else if (addr > wp_high)
|
||||
return addr - wp_high;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
|
||||
struct arch_hw_breakpoint *info)
|
||||
{
|
||||
@@ -697,23 +731,25 @@ static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
|
||||
static void watchpoint_handler(unsigned long addr, unsigned int fsr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int i, access;
|
||||
u32 val, ctrl_reg, alignment_mask;
|
||||
int i, access, closest_match = 0;
|
||||
u32 min_dist = -1, dist;
|
||||
u32 val, ctrl_reg;
|
||||
struct perf_event *wp, **slots;
|
||||
struct arch_hw_breakpoint *info;
|
||||
struct arch_hw_breakpoint_ctrl ctrl;
|
||||
|
||||
slots = this_cpu_ptr(wp_on_reg);
|
||||
|
||||
/*
|
||||
* Find all watchpoints that match the reported address. If no exact
|
||||
* match is found. Attribute the hit to the closest watchpoint.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < core_num_wrps; ++i) {
|
||||
rcu_read_lock();
|
||||
|
||||
wp = slots[i];
|
||||
|
||||
if (wp == NULL)
|
||||
goto unlock;
|
||||
continue;
|
||||
|
||||
info = counter_arch_bp(wp);
|
||||
/*
|
||||
* The DFAR is an unknown value on debug architectures prior
|
||||
* to 7.1. Since we only allow a single watchpoint on these
|
||||
@@ -722,33 +758,31 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
|
||||
*/
|
||||
if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
|
||||
BUG_ON(i > 0);
|
||||
info = counter_arch_bp(wp);
|
||||
info->trigger = wp->attr.bp_addr;
|
||||
} else {
|
||||
if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
|
||||
alignment_mask = 0x7;
|
||||
else
|
||||
alignment_mask = 0x3;
|
||||
|
||||
/* Check if the watchpoint value matches. */
|
||||
val = read_wb_reg(ARM_BASE_WVR + i);
|
||||
if (val != (addr & ~alignment_mask))
|
||||
goto unlock;
|
||||
|
||||
/* Possible match, check the byte address select. */
|
||||
ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
|
||||
decode_ctrl_reg(ctrl_reg, &ctrl);
|
||||
if (!((1 << (addr & alignment_mask)) & ctrl.len))
|
||||
goto unlock;
|
||||
|
||||
/* Check that the access type matches. */
|
||||
if (debug_exception_updates_fsr()) {
|
||||
access = (fsr & ARM_FSR_ACCESS_MASK) ?
|
||||
HW_BREAKPOINT_W : HW_BREAKPOINT_R;
|
||||
if (!(access & hw_breakpoint_type(wp)))
|
||||
goto unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
val = read_wb_reg(ARM_BASE_WVR + i);
|
||||
ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
|
||||
decode_ctrl_reg(ctrl_reg, &ctrl);
|
||||
dist = get_distance_from_watchpoint(addr, val, &ctrl);
|
||||
if (dist < min_dist) {
|
||||
min_dist = dist;
|
||||
closest_match = i;
|
||||
}
|
||||
/* Is this an exact match? */
|
||||
if (dist != 0)
|
||||
continue;
|
||||
|
||||
/* We have a winner. */
|
||||
info = counter_arch_bp(wp);
|
||||
info->trigger = addr;
|
||||
}
|
||||
|
||||
@@ -770,13 +804,23 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
|
||||
* we can single-step over the watchpoint trigger.
|
||||
*/
|
||||
if (!is_default_overflow_handler(wp))
|
||||
goto unlock;
|
||||
|
||||
continue;
|
||||
step:
|
||||
enable_single_step(wp, instruction_pointer(regs));
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (min_dist > 0 && min_dist != -1) {
|
||||
/* No exact match found. */
|
||||
wp = slots[closest_match];
|
||||
info = counter_arch_bp(wp);
|
||||
info->trigger = addr;
|
||||
pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
|
||||
perf_bp_event(wp, regs);
|
||||
if (is_default_overflow_handler(wp))
|
||||
enable_single_step(wp, instruction_pointer(regs));
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void watchpoint_single_step_handler(unsigned long pc)
|
||||
|
||||
@@ -240,6 +240,7 @@ config SAMSUNG_PM_DEBUG
|
||||
bool "Samsung PM Suspend debug"
|
||||
depends on PM && DEBUG_KERNEL
|
||||
depends on DEBUG_EXYNOS_UART || DEBUG_S3C24XX_UART || DEBUG_S3C2410_UART
|
||||
depends on DEBUG_LL && MMU
|
||||
help
|
||||
Say Y here if you want verbose debugging from the PM Suspend and
|
||||
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
|
||||
@@ -98,21 +98,21 @@ asm (
|
||||
"optprobe_template_end:\n");
|
||||
|
||||
#define TMPL_VAL_IDX \
|
||||
((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_val - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_CALL_IDX \
|
||||
((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_call - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_END_IDX \
|
||||
((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_end - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_ADD_SP \
|
||||
((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_add_sp - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_SUB_SP \
|
||||
((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_sub_sp - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_RESTORE_BEGIN \
|
||||
((unsigned long *)&optprobe_template_restore_begin - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_restore_begin - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_RESTORE_ORIGN_INSN \
|
||||
((unsigned long *)&optprobe_template_restore_orig_insn - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_restore_orig_insn - (unsigned long *)optprobe_template_entry)
|
||||
#define TMPL_RESTORE_END \
|
||||
((unsigned long *)&optprobe_template_restore_end - (unsigned long *)&optprobe_template_entry)
|
||||
((unsigned long *)optprobe_template_restore_end - (unsigned long *)optprobe_template_entry)
|
||||
|
||||
/*
|
||||
* ARM can always optimize an instruction when using ARM ISA, except
|
||||
@@ -247,7 +247,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or
|
||||
}
|
||||
|
||||
/* Copy arch-dep-instance from template. */
|
||||
memcpy(code, (unsigned long *)&optprobe_template_entry,
|
||||
memcpy(code, (unsigned long *)optprobe_template_entry,
|
||||
TMPL_END_IDX * sizeof(kprobe_opcode_t));
|
||||
|
||||
/* Adjust buffer according to instruction. */
|
||||
|
||||
@@ -46,6 +46,7 @@ config ARCH_BCM_IPROC
|
||||
config ARCH_BERLIN
|
||||
bool "Marvell Berlin SoC Family"
|
||||
select DW_APB_ICTL
|
||||
select DW_APB_TIMER_OF
|
||||
select GPIOLIB
|
||||
select PINCTRL
|
||||
help
|
||||
|
||||
@@ -155,6 +155,7 @@ dtbs_install:
|
||||
PHONY += vdso_install
|
||||
vdso_install:
|
||||
$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@
|
||||
$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@
|
||||
|
||||
# We use MRPROPER_FILES and CLEAN_FILES now
|
||||
archclean:
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
&emac {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rgmii_pins>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
phy-supply = <®_dc1sw>;
|
||||
status = "okay";
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
&emac {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rgmii_pins>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-txid";
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
pinctrl-0 = <&emac_rgmii_pins>;
|
||||
phy-supply = <®_gmac_3v3>;
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
pinctrl-0 = <&emac_rgmii_pins>;
|
||||
phy-supply = <®_gmac_3v3>;
|
||||
phy-handle = <&ext_rgmii_phy>;
|
||||
phy-mode = "rgmii";
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
aliases {
|
||||
ethernet0 = ð0;
|
||||
/* for dsa slave device */
|
||||
ethernet1 = &switch0port1;
|
||||
ethernet2 = &switch0port2;
|
||||
ethernet3 = &switch0port3;
|
||||
serial0 = &uart0;
|
||||
serial1 = &uart1;
|
||||
};
|
||||
@@ -136,25 +140,25 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
switch0port0: port@0 {
|
||||
reg = <0>;
|
||||
label = "cpu";
|
||||
ethernet = <ð0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
switch0port1: port@1 {
|
||||
reg = <1>;
|
||||
label = "wan";
|
||||
phy-handle = <&switch0phy0>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
switch0port2: port@2 {
|
||||
reg = <2>;
|
||||
label = "lan0";
|
||||
phy-handle = <&switch0phy1>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
switch0port3: port@3 {
|
||||
reg = <3>;
|
||||
label = "lan1";
|
||||
phy-handle = <&switch0phy2>;
|
||||
|
||||
@@ -430,6 +430,7 @@
|
||||
bus-width = <8>;
|
||||
mmc-hs200-1_8v;
|
||||
non-removable;
|
||||
full-pwr-cycle-in-suspend;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -232,17 +232,19 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
bmi .Lctr1x
|
||||
cmn w6, #4 /* 32 bit overflow? */
|
||||
bcs .Lctr1x
|
||||
ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */
|
||||
dup v7.4s, w6
|
||||
add w7, w6, #1
|
||||
mov v0.16b, v4.16b
|
||||
add v7.4s, v7.4s, v8.4s
|
||||
add w8, w6, #2
|
||||
mov v1.16b, v4.16b
|
||||
rev32 v8.16b, v7.16b
|
||||
add w9, w6, #3
|
||||
mov v2.16b, v4.16b
|
||||
rev w7, w7
|
||||
mov v3.16b, v4.16b
|
||||
mov v1.s[3], v8.s[0]
|
||||
mov v2.s[3], v8.s[1]
|
||||
mov v3.s[3], v8.s[2]
|
||||
rev w8, w8
|
||||
mov v1.s[3], w7
|
||||
rev w9, w9
|
||||
mov v2.s[3], w8
|
||||
mov v3.s[3], w9
|
||||
ld1 {v5.16b-v7.16b}, [x20], #48 /* get 3 input blocks */
|
||||
bl aes_encrypt_block4x
|
||||
eor v0.16b, v5.16b, v0.16b
|
||||
|
||||
@@ -192,6 +192,7 @@ enum vcpu_sysreg {
|
||||
#define cp14_DBGWCR0 (DBGWCR0_EL1 * 2)
|
||||
#define cp14_DBGWVR0 (DBGWVR0_EL1 * 2)
|
||||
#define cp14_DBGDCCINT (MDCCINT_EL1 * 2)
|
||||
#define cp14_DBGVCR (DBGVCR32_EL2 * 2)
|
||||
|
||||
#define NR_COPRO_REGS (NR_SYS_REGS * 2)
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ const struct cpumask *cpumask_of_node(int node);
|
||||
/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
|
||||
static inline const struct cpumask *cpumask_of_node(int node)
|
||||
{
|
||||
if (node == NUMA_NO_NODE)
|
||||
return cpu_all_mask;
|
||||
|
||||
return node_to_cpumask_map[node];
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -107,8 +107,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
|
||||
#define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID))
|
||||
#define pte_valid_not_user(pte) \
|
||||
((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
|
||||
#define pte_valid_young(pte) \
|
||||
((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
|
||||
#define pte_valid_user(pte) \
|
||||
((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
|
||||
|
||||
@@ -116,9 +114,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
|
||||
* Could the pte be present in the TLB? We must check mm_tlb_flush_pending
|
||||
* so that we don't erroneously return false for pages that have been
|
||||
* remapped as PROT_NONE but are yet to be flushed from the TLB.
|
||||
* Note that we can't make any assumptions based on the state of the access
|
||||
* flag, since ptep_clear_flush_young() elides a DSB when invalidating the
|
||||
* TLB.
|
||||
*/
|
||||
#define pte_accessible(mm, pte) \
|
||||
(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte))
|
||||
(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
|
||||
|
||||
/*
|
||||
* p??_access_permitted() is true for valid user mappings (subject to the
|
||||
@@ -144,13 +145,6 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
|
||||
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkwrite(pte_t pte)
|
||||
{
|
||||
pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
|
||||
@@ -176,6 +170,20 @@ static inline pte_t pte_mkdirty(pte_t pte)
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
/*
|
||||
* If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
|
||||
* clear), set the PTE_DIRTY bit.
|
||||
*/
|
||||
if (pte_hw_dirty(pte))
|
||||
pte = pte_mkdirty(pte);
|
||||
|
||||
pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
|
||||
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkold(pte_t pte)
|
||||
{
|
||||
return clear_pte_bit(pte, __pgprot(PTE_AF));
|
||||
@@ -668,12 +676,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
|
||||
pte = READ_ONCE(*ptep);
|
||||
do {
|
||||
old_pte = pte;
|
||||
/*
|
||||
* If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
|
||||
* clear), set the PTE_DIRTY bit.
|
||||
*/
|
||||
if (pte_hw_dirty(pte))
|
||||
pte = pte_mkdirty(pte);
|
||||
pte = pte_wrprotect(pte);
|
||||
pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep),
|
||||
pte_val(old_pte), pte_val(pte));
|
||||
|
||||
@@ -86,16 +86,26 @@
|
||||
|
||||
#endif /* CONFIG_BROKEN_GAS_INST */
|
||||
|
||||
#define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4)
|
||||
#define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3)
|
||||
#define REG_PSTATE_SSBS_IMM sys_reg(0, 3, 4, 0, 1)
|
||||
/*
|
||||
* Instructions for modifying PSTATE fields.
|
||||
* As per Arm ARM for v8-A, Section "C.5.1.3 op0 == 0b00, architectural hints,
|
||||
* barriers and CLREX, and PSTATE access", ARM DDI 0487 C.a, system instructions
|
||||
* for accessing PSTATE fields have the following encoding:
|
||||
* Op0 = 0, CRn = 4
|
||||
* Op1, Op2 encodes the PSTATE field modified and defines the constraints.
|
||||
* CRm = Imm4 for the instruction.
|
||||
* Rt = 0x1f
|
||||
*/
|
||||
#define pstate_field(op1, op2) ((op1) << Op1_shift | (op2) << Op2_shift)
|
||||
#define PSTATE_Imm_shift CRm_shift
|
||||
|
||||
#define SET_PSTATE_PAN(x) __emit_inst(0xd5000000 | REG_PSTATE_PAN_IMM | \
|
||||
(!!x)<<8 | 0x1f)
|
||||
#define SET_PSTATE_UAO(x) __emit_inst(0xd5000000 | REG_PSTATE_UAO_IMM | \
|
||||
(!!x)<<8 | 0x1f)
|
||||
#define SET_PSTATE_SSBS(x) __emit_inst(0xd5000000 | REG_PSTATE_SSBS_IMM | \
|
||||
(!!x)<<8 | 0x1f)
|
||||
#define PSTATE_PAN pstate_field(0, 4)
|
||||
#define PSTATE_UAO pstate_field(0, 3)
|
||||
#define PSTATE_SSBS pstate_field(3, 1)
|
||||
|
||||
#define SET_PSTATE_PAN(x) __emit_inst(0xd500401f | PSTATE_PAN | ((!!x) << PSTATE_Imm_shift))
|
||||
#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift))
|
||||
#define SET_PSTATE_SSBS(x) __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift))
|
||||
|
||||
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
|
||||
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
|
||||
|
||||
@@ -32,9 +32,10 @@
|
||||
#include <generated/vdso32-offsets.h>
|
||||
#endif
|
||||
|
||||
#define VDSO_SYMBOL(base, name) \
|
||||
({ \
|
||||
(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
|
||||
#define VDSO_SYMBOL(base, name) \
|
||||
({ \
|
||||
(void *)((vdso_offset_##name & ~1UL) - VDSO_LBASE + \
|
||||
(unsigned long)(base)); \
|
||||
})
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -18,14 +18,7 @@
|
||||
#undef dmb
|
||||
#endif
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 7
|
||||
#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory")
|
||||
#elif __LINUX_ARM_ARCH__ == 6
|
||||
#define dmb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
|
||||
: : "r" (0) : "memory")
|
||||
#else
|
||||
#define dmb(x) __asm__ __volatile__ ("" : : : "memory")
|
||||
#endif
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 8 && defined(CONFIG_AS_DMB_ISHLD)
|
||||
#define aarch32_smp_mb() dmb(ish)
|
||||
|
||||
@@ -606,6 +606,12 @@ check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
return (need_wa > 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cpu_enable_branch_predictor_hardening(const struct arm64_cpu_capabilities *cap)
|
||||
{
|
||||
cap->matches(cap, SCOPE_LOCAL_CPU);
|
||||
}
|
||||
|
||||
static const __maybe_unused struct midr_range tx2_family_cpus[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
|
||||
MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
|
||||
@@ -800,9 +806,11 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.desc = "Branch predictor hardening",
|
||||
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.matches = check_branch_predictor,
|
||||
.cpu_enable = cpu_enable_branch_predictor_hardening,
|
||||
},
|
||||
#ifdef CONFIG_HARDEN_EL2_VECTORS
|
||||
{
|
||||
|
||||
@@ -1098,7 +1098,7 @@ static int ssbs_emulation_handler(struct pt_regs *regs, u32 instr)
|
||||
if (user_mode(regs))
|
||||
return 1;
|
||||
|
||||
if (instr & BIT(CRm_shift))
|
||||
if (instr & BIT(PSTATE_Imm_shift))
|
||||
regs->pstate |= PSR_SSBS_BIT;
|
||||
else
|
||||
regs->pstate &= ~PSR_SSBS_BIT;
|
||||
@@ -1108,8 +1108,8 @@ static int ssbs_emulation_handler(struct pt_regs *regs, u32 instr)
|
||||
}
|
||||
|
||||
static struct undef_hook ssbs_emulation_hook = {
|
||||
.instr_mask = ~(1U << CRm_shift),
|
||||
.instr_val = 0xd500001f | REG_PSTATE_SSBS_IMM,
|
||||
.instr_mask = ~(1U << PSTATE_Imm_shift),
|
||||
.instr_val = 0xd500401f | PSTATE_SSBS,
|
||||
.fn = ssbs_emulation_handler,
|
||||
};
|
||||
|
||||
|
||||
@@ -70,7 +70,6 @@ static int cpu_psci_cpu_disable(unsigned int cpu)
|
||||
|
||||
static void cpu_psci_cpu_die(unsigned int cpu)
|
||||
{
|
||||
int ret;
|
||||
/*
|
||||
* There are no known implementations of PSCI actually using the
|
||||
* power state field, pass a sensible default for now.
|
||||
@@ -78,9 +77,7 @@ static void cpu_psci_cpu_die(unsigned int cpu)
|
||||
u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN <<
|
||||
PSCI_0_2_POWER_STATE_TYPE_SHIFT;
|
||||
|
||||
ret = psci_ops.cpu_off(state);
|
||||
|
||||
pr_crit("unable to power off CPU%u (%d)\n", cpu, ret);
|
||||
psci_ops.cpu_off(state);
|
||||
}
|
||||
|
||||
static int cpu_psci_cpu_kill(unsigned int cpu)
|
||||
|
||||
@@ -272,21 +272,23 @@ void store_cpu_topology(unsigned int cpuid)
|
||||
if (mpidr & MPIDR_UP_BITMASK)
|
||||
return;
|
||||
|
||||
/* Create cpu topology mapping based on MPIDR. */
|
||||
if (mpidr & MPIDR_MT_BITMASK) {
|
||||
/* Multiprocessor system : Multi-threads per core */
|
||||
cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
|
||||
cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2) |
|
||||
MPIDR_AFFINITY_LEVEL(mpidr, 3) << 8;
|
||||
} else {
|
||||
/* Multiprocessor system : Single-thread per core */
|
||||
cpuid_topo->thread_id = -1;
|
||||
cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
|
||||
cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1) |
|
||||
MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8 |
|
||||
MPIDR_AFFINITY_LEVEL(mpidr, 3) << 16;
|
||||
}
|
||||
/*
|
||||
* This would be the place to create cpu topology based on MPIDR.
|
||||
*
|
||||
* However, it cannot be trusted to depict the actual topology; some
|
||||
* pieces of the architecture enforce an artificial cap on Aff0 values
|
||||
* (e.g. GICv3's ICC_SGI1R_EL1 limits it to 15), leading to an
|
||||
* artificial cycling of Aff1, Aff2 and Aff3 values. IOW, these end up
|
||||
* having absolutely no relationship to the actual underlying system
|
||||
* topology, and cannot be reasonably used as core / package ID.
|
||||
*
|
||||
* If the MT bit is set, Aff0 *could* be used to define a thread ID, but
|
||||
* we still wouldn't be able to obtain a sane core ID. This means we
|
||||
* need to entirely ignore MPIDR for any topology deduction.
|
||||
*/
|
||||
cpuid_topo->thread_id = -1;
|
||||
cpuid_topo->core_id = cpuid;
|
||||
cpuid_topo->package_id = cpu_to_node(cpuid);
|
||||
|
||||
pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
|
||||
cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
|
||||
|
||||
@@ -271,18 +271,7 @@ static int __aarch32_alloc_vdso_pages(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = aarch32_alloc_kuser_vdso_page();
|
||||
if (ret) {
|
||||
unsigned long c_vvar =
|
||||
(unsigned long)page_to_virt(aarch32_vdso_pages[C_VVAR]);
|
||||
unsigned long c_vdso =
|
||||
(unsigned long)page_to_virt(aarch32_vdso_pages[C_VDSO]);
|
||||
|
||||
free_page(c_vvar);
|
||||
free_page(c_vdso);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return aarch32_alloc_kuser_vdso_page();
|
||||
}
|
||||
#else
|
||||
static int __aarch32_alloc_vdso_pages(void)
|
||||
|
||||
@@ -33,7 +33,7 @@ UBSAN_SANITIZE := n
|
||||
OBJECT_FILES_NON_STANDARD := y
|
||||
KCOV_INSTRUMENT := n
|
||||
|
||||
CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny
|
||||
CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny -fasynchronous-unwind-tables
|
||||
|
||||
ifneq ($(c-gettimeofday-y),)
|
||||
CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
|
||||
|
||||
@@ -202,7 +202,7 @@ quiet_cmd_vdsosym = VDSOSYM $@
|
||||
cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
|
||||
|
||||
# Install commands for the unstripped file
|
||||
quiet_cmd_vdso_install = INSTALL $@
|
||||
quiet_cmd_vdso_install = INSTALL32 $@
|
||||
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/vdso32.so
|
||||
|
||||
vdso.so: $(obj)/vdso.so.dbg
|
||||
|
||||
@@ -1555,9 +1555,9 @@ static const struct sys_reg_desc cp14_regs[] = {
|
||||
{ Op1( 0), CRn( 0), CRm( 1), Op2( 0), trap_raz_wi },
|
||||
DBG_BCR_BVR_WCR_WVR(1),
|
||||
/* DBGDCCINT */
|
||||
{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32 },
|
||||
{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32, NULL, cp14_DBGDCCINT },
|
||||
/* DBGDSCRext */
|
||||
{ Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32 },
|
||||
{ Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32, NULL, cp14_DBGDSCRext },
|
||||
DBG_BCR_BVR_WCR_WVR(2),
|
||||
/* DBGDTR[RT]Xint */
|
||||
{ Op1( 0), CRn( 0), CRm( 3), Op2( 0), trap_raz_wi },
|
||||
@@ -1572,7 +1572,7 @@ static const struct sys_reg_desc cp14_regs[] = {
|
||||
{ Op1( 0), CRn( 0), CRm( 6), Op2( 2), trap_raz_wi },
|
||||
DBG_BCR_BVR_WCR_WVR(6),
|
||||
/* DBGVCR */
|
||||
{ Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32 },
|
||||
{ Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32, NULL, cp14_DBGVCR },
|
||||
DBG_BCR_BVR_WCR_WVR(7),
|
||||
DBG_BCR_BVR_WCR_WVR(8),
|
||||
DBG_BCR_BVR_WCR_WVR(9),
|
||||
|
||||
@@ -58,7 +58,11 @@ EXPORT_SYMBOL(node_to_cpumask_map);
|
||||
*/
|
||||
const struct cpumask *cpumask_of_node(int node)
|
||||
{
|
||||
if (WARN_ON(node >= nr_node_ids))
|
||||
|
||||
if (node == NUMA_NO_NODE)
|
||||
return cpu_all_mask;
|
||||
|
||||
if (WARN_ON(node < 0 || node >= nr_node_ids))
|
||||
return cpu_none_mask;
|
||||
|
||||
if (WARN_ON(node_to_cpumask_map[node] == NULL))
|
||||
|
||||
@@ -42,7 +42,7 @@ obj-y += esi_stub.o # must be in kernel proper
|
||||
endif
|
||||
obj-$(CONFIG_INTEL_IOMMU) += pci-dma.o
|
||||
|
||||
obj-$(CONFIG_BINFMT_ELF) += elfcore.o
|
||||
obj-$(CONFIG_ELF_CORE) += elfcore.o
|
||||
|
||||
# fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
|
||||
CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31
|
||||
|
||||
@@ -409,83 +409,9 @@ static void kretprobe_trampoline(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point the target function has been tricked into
|
||||
* returning into our trampoline. Lookup the associated instance
|
||||
* and then:
|
||||
* - call the handler function
|
||||
* - cleanup by marking the instance as unused
|
||||
* - long jump back to the original return address
|
||||
*/
|
||||
int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
struct kretprobe_instance *ri = NULL;
|
||||
struct hlist_head *head, empty_rp;
|
||||
struct hlist_node *tmp;
|
||||
unsigned long flags, orig_ret_address = 0;
|
||||
unsigned long trampoline_address =
|
||||
((struct fnptr *)kretprobe_trampoline)->ip;
|
||||
|
||||
INIT_HLIST_HEAD(&empty_rp);
|
||||
kretprobe_hash_lock(current, &head, &flags);
|
||||
|
||||
/*
|
||||
* It is possible to have multiple instances associated with a given
|
||||
* task either because an multiple functions in the call path
|
||||
* have a return probe installed on them, and/or more than one return
|
||||
* return probe was registered for a target function.
|
||||
*
|
||||
* We can handle this because:
|
||||
* - instances are always inserted at the head of the list
|
||||
* - when multiple return probes are registered for the same
|
||||
* function, the first instance's ret_addr will point to the
|
||||
* real return address, and all the rest will point to
|
||||
* kretprobe_trampoline
|
||||
*/
|
||||
hlist_for_each_entry_safe(ri, tmp, head, hlist) {
|
||||
if (ri->task != current)
|
||||
/* another task is sharing our hash bucket */
|
||||
continue;
|
||||
|
||||
orig_ret_address = (unsigned long)ri->ret_addr;
|
||||
if (orig_ret_address != trampoline_address)
|
||||
/*
|
||||
* This is the real return address. Any other
|
||||
* instances associated with this task are for
|
||||
* other calls deeper on the call stack
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
regs->cr_iip = orig_ret_address;
|
||||
|
||||
hlist_for_each_entry_safe(ri, tmp, head, hlist) {
|
||||
if (ri->task != current)
|
||||
/* another task is sharing our hash bucket */
|
||||
continue;
|
||||
|
||||
if (ri->rp && ri->rp->handler)
|
||||
ri->rp->handler(ri, regs);
|
||||
|
||||
orig_ret_address = (unsigned long)ri->ret_addr;
|
||||
recycle_rp_inst(ri, &empty_rp);
|
||||
|
||||
if (orig_ret_address != trampoline_address)
|
||||
/*
|
||||
* This is the real return address. Any other
|
||||
* instances associated with this task are for
|
||||
* other calls deeper on the call stack
|
||||
*/
|
||||
break;
|
||||
}
|
||||
kretprobe_assert(ri, orig_ret_address, trampoline_address);
|
||||
|
||||
kretprobe_hash_unlock(current, &flags);
|
||||
|
||||
hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
|
||||
hlist_del(&ri->hlist);
|
||||
kfree(ri);
|
||||
}
|
||||
regs->cr_iip = __kretprobe_trampoline_handler(regs, kretprobe_trampoline, NULL);
|
||||
/*
|
||||
* By returning a non-zero value, we are telling
|
||||
* kprobe_handler() that we don't want the post_handler
|
||||
@@ -498,6 +424,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
ri->ret_addr = (kprobe_opcode_t *)regs->b0;
|
||||
ri->fp = NULL;
|
||||
|
||||
/* Replace the return addr with trampoline addr */
|
||||
regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
|
||||
|
||||
@@ -152,6 +152,7 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
|
||||
{
|
||||
struct clk_init_data id;
|
||||
struct clk_hw *h;
|
||||
struct clk *clk;
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
@@ -164,7 +165,13 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
|
||||
id.ops = &alchemy_clkops_cpu;
|
||||
h->init = &id;
|
||||
|
||||
return clk_register(NULL, h);
|
||||
clk = clk_register(NULL, h);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("failed to register clock\n");
|
||||
kfree(h);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
/* AUXPLLs ************************************************************/
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
|
||||
|
||||
/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
|
||||
#define BUILD_VDSO32_64
|
||||
#undef CONFIG_64BIT
|
||||
#define CONFIG_32BIT 1
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@@ -424,6 +424,7 @@ int has_transparent_hugepage(void)
|
||||
}
|
||||
return mask == PM_HUGE_MASK;
|
||||
}
|
||||
EXPORT_SYMBOL(has_transparent_hugepage);
|
||||
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
|
||||
ifndef CONFIG_CPU_MIPSR6
|
||||
ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
|
||||
$(warning MIPS VDSO requires binutils >= 2.25)
|
||||
obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
|
||||
obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
|
||||
ccflags-vdso += -DDISABLE_MIPS_VDSO
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -35,6 +35,7 @@ config PARISC
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select ARCH_DISCARD_MEMBLOCK
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select VIRT_TO_BUS
|
||||
select MODULES_USE_ELF_RELA
|
||||
@@ -311,21 +312,16 @@ config ARCH_SELECT_MEMORY_MODEL
|
||||
def_bool y
|
||||
depends on 64BIT
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
def_bool y
|
||||
depends on 64BIT
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
|
||||
config ARCH_DISCONTIGMEM_DEFAULT
|
||||
config ARCH_SPARSEMEM_DEFAULT
|
||||
def_bool y
|
||||
depends on ARCH_DISCONTIGMEM_ENABLE
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "3"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on ARCH_SPARSEMEM_ENABLE
|
||||
|
||||
source "kernel/Kconfig.hz"
|
||||
|
||||
|
||||
@@ -2,62 +2,6 @@
|
||||
#ifndef _PARISC_MMZONE_H
|
||||
#define _PARISC_MMZONE_H
|
||||
|
||||
#define MAX_PHYSMEM_RANGES 8 /* Fix the size for now (current known max is 3) */
|
||||
#define MAX_PHYSMEM_RANGES 4 /* Fix the size for now (current known max is 3) */
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
|
||||
extern int npmem_ranges;
|
||||
|
||||
struct node_map_data {
|
||||
pg_data_t pg_data;
|
||||
};
|
||||
|
||||
extern struct node_map_data node_data[];
|
||||
|
||||
#define NODE_DATA(nid) (&node_data[nid].pg_data)
|
||||
|
||||
/* We have these possible memory map layouts:
|
||||
* Astro: 0-3.75, 67.75-68, 4-64
|
||||
* zx1: 0-1, 257-260, 4-256
|
||||
* Stretch (N-class): 0-2, 4-32, 34-xxx
|
||||
*/
|
||||
|
||||
/* Since each 1GB can only belong to one region (node), we can create
|
||||
* an index table for pfn to nid lookup; each entry in pfnnid_map
|
||||
* represents 1GB, and contains the node that the memory belongs to. */
|
||||
|
||||
#define PFNNID_SHIFT (30 - PAGE_SHIFT)
|
||||
#define PFNNID_MAP_MAX 512 /* support 512GB */
|
||||
extern signed char pfnnid_map[PFNNID_MAP_MAX];
|
||||
|
||||
#ifndef CONFIG_64BIT
|
||||
#define pfn_is_io(pfn) ((pfn & (0xf0000000UL >> PAGE_SHIFT)) == (0xf0000000UL >> PAGE_SHIFT))
|
||||
#else
|
||||
/* io can be 0xf0f0f0f0f0xxxxxx or 0xfffffffff0000000 */
|
||||
#define pfn_is_io(pfn) ((pfn & (0xf000000000000000UL >> PAGE_SHIFT)) == (0xf000000000000000UL >> PAGE_SHIFT))
|
||||
#endif
|
||||
|
||||
static inline int pfn_to_nid(unsigned long pfn)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (unlikely(pfn_is_io(pfn)))
|
||||
return 0;
|
||||
|
||||
i = pfn >> PFNNID_SHIFT;
|
||||
BUG_ON(i >= ARRAY_SIZE(pfnnid_map));
|
||||
|
||||
return pfnnid_map[i];
|
||||
}
|
||||
|
||||
static inline int pfn_valid(int pfn)
|
||||
{
|
||||
int nid = pfn_to_nid(pfn);
|
||||
|
||||
if (nid >= 0)
|
||||
return (pfn < node_end_pfn(nid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* _PARISC_MMZONE_H */
|
||||
|
||||
@@ -145,9 +145,9 @@ extern int npmem_ranges;
|
||||
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
|
||||
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#ifndef CONFIG_SPARSEMEM
|
||||
#define pfn_valid(pfn) ((pfn) < max_mapnr)
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
#define HPAGE_SHIFT PMD_SHIFT /* fixed for transparent huge pages */
|
||||
|
||||
14
arch/parisc/include/asm/sparsemem.h
Normal file
14
arch/parisc/include/asm/sparsemem.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef ASM_PARISC_SPARSEMEM_H
|
||||
#define ASM_PARISC_SPARSEMEM_H
|
||||
|
||||
/* We have these possible memory map layouts:
|
||||
* Astro: 0-3.75, 67.75-68, 4-64
|
||||
* zx1: 0-1, 257-260, 4-256
|
||||
* Stretch (N-class): 0-2, 4-32, 34-xxx
|
||||
*/
|
||||
|
||||
#define MAX_PHYSMEM_BITS 39 /* 512 GB */
|
||||
#define SECTION_SIZE_BITS 27 /* 128 MB */
|
||||
|
||||
#endif
|
||||
@@ -138,12 +138,6 @@ extern void $$dyncall(void);
|
||||
EXPORT_SYMBOL($$dyncall);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
#include <asm/mmzone.h>
|
||||
EXPORT_SYMBOL(node_data);
|
||||
EXPORT_SYMBOL(pfnnid_map);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
extern void _mcount(void);
|
||||
EXPORT_SYMBOL(_mcount);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <asm/mmzone.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/msgbuf.h>
|
||||
#include <asm/sparsemem.h>
|
||||
|
||||
extern int data_start;
|
||||
extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
|
||||
@@ -49,11 +50,6 @@ pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data..vm0.pmd"), aligned
|
||||
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE)));
|
||||
pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE)));
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
|
||||
signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
|
||||
#endif
|
||||
|
||||
static struct resource data_resource = {
|
||||
.name = "Kernel data",
|
||||
.flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
|
||||
@@ -77,8 +73,8 @@ static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly;
|
||||
* information retrieved in kernel/inventory.c.
|
||||
*/
|
||||
|
||||
physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly;
|
||||
int npmem_ranges __read_mostly;
|
||||
physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __initdata;
|
||||
int npmem_ranges __initdata;
|
||||
|
||||
/*
|
||||
* get_memblock() allocates pages via memblock.
|
||||
@@ -111,7 +107,7 @@ static void * __init get_memblock(unsigned long size)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define MAX_MEM (~0UL)
|
||||
#define MAX_MEM (1UL << MAX_PHYSMEM_BITS)
|
||||
#else /* !CONFIG_64BIT */
|
||||
#define MAX_MEM (3584U*1024U*1024U)
|
||||
#endif /* !CONFIG_64BIT */
|
||||
@@ -150,7 +146,7 @@ static void __init mem_limit_func(void)
|
||||
static void __init setup_bootmem(void)
|
||||
{
|
||||
unsigned long mem_max;
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#ifndef CONFIG_SPARSEMEM
|
||||
physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1];
|
||||
int npmem_holes;
|
||||
#endif
|
||||
@@ -168,23 +164,20 @@ static void __init setup_bootmem(void)
|
||||
int j;
|
||||
|
||||
for (j = i; j > 0; j--) {
|
||||
unsigned long tmp;
|
||||
physmem_range_t tmp;
|
||||
|
||||
if (pmem_ranges[j-1].start_pfn <
|
||||
pmem_ranges[j].start_pfn) {
|
||||
|
||||
break;
|
||||
}
|
||||
tmp = pmem_ranges[j-1].start_pfn;
|
||||
pmem_ranges[j-1].start_pfn = pmem_ranges[j].start_pfn;
|
||||
pmem_ranges[j].start_pfn = tmp;
|
||||
tmp = pmem_ranges[j-1].pages;
|
||||
pmem_ranges[j-1].pages = pmem_ranges[j].pages;
|
||||
pmem_ranges[j].pages = tmp;
|
||||
tmp = pmem_ranges[j-1];
|
||||
pmem_ranges[j-1] = pmem_ranges[j];
|
||||
pmem_ranges[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#ifndef CONFIG_SPARSEMEM
|
||||
/*
|
||||
* Throw out ranges that are too far apart (controlled by
|
||||
* MAX_GAP).
|
||||
@@ -196,7 +189,7 @@ static void __init setup_bootmem(void)
|
||||
pmem_ranges[i-1].pages) > MAX_GAP) {
|
||||
npmem_ranges = i;
|
||||
printk("Large gap in memory detected (%ld pages). "
|
||||
"Consider turning on CONFIG_DISCONTIGMEM\n",
|
||||
"Consider turning on CONFIG_SPARSEMEM\n",
|
||||
pmem_ranges[i].start_pfn -
|
||||
(pmem_ranges[i-1].start_pfn +
|
||||
pmem_ranges[i-1].pages));
|
||||
@@ -261,9 +254,8 @@ static void __init setup_bootmem(void)
|
||||
|
||||
printk(KERN_INFO "Total Memory: %ld MB\n",mem_max >> 20);
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#ifndef CONFIG_SPARSEMEM
|
||||
/* Merge the ranges, keeping track of the holes */
|
||||
|
||||
{
|
||||
unsigned long end_pfn;
|
||||
unsigned long hole_pages;
|
||||
@@ -286,18 +278,6 @@ static void __init setup_bootmem(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
for (i = 0; i < MAX_PHYSMEM_RANGES; i++) {
|
||||
memset(NODE_DATA(i), 0, sizeof(pg_data_t));
|
||||
}
|
||||
memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
|
||||
|
||||
for (i = 0; i < npmem_ranges; i++) {
|
||||
node_set_state(i, N_NORMAL_MEMORY);
|
||||
node_set_online(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize and free the full range of memory in each range.
|
||||
*/
|
||||
@@ -338,7 +318,7 @@ static void __init setup_bootmem(void)
|
||||
memblock_reserve(__pa(KERNEL_BINARY_TEXT_START),
|
||||
(unsigned long)(_end - KERNEL_BINARY_TEXT_START));
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#ifndef CONFIG_SPARSEMEM
|
||||
|
||||
/* reserve the holes */
|
||||
|
||||
@@ -384,6 +364,9 @@ static void __init setup_bootmem(void)
|
||||
|
||||
/* Initialize Page Deallocation Table (PDT) and check for bad memory. */
|
||||
pdc_pdt_init();
|
||||
|
||||
memblock_allow_resize();
|
||||
memblock_dump_all();
|
||||
}
|
||||
|
||||
static int __init parisc_text_address(unsigned long vaddr)
|
||||
@@ -711,37 +694,46 @@ static void __init gateway_init(void)
|
||||
PAGE_SIZE, PAGE_GATEWAY, 1);
|
||||
}
|
||||
|
||||
void __init paging_init(void)
|
||||
static void __init parisc_bootmem_free(void)
|
||||
{
|
||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
||||
unsigned long holes_size[MAX_NR_ZONES] = { 0, };
|
||||
unsigned long mem_start_pfn = ~0UL, mem_end_pfn = 0, mem_size_pfn = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < npmem_ranges; i++) {
|
||||
unsigned long start = pmem_ranges[i].start_pfn;
|
||||
unsigned long size = pmem_ranges[i].pages;
|
||||
unsigned long end = start + size;
|
||||
|
||||
if (mem_start_pfn > start)
|
||||
mem_start_pfn = start;
|
||||
if (mem_end_pfn < end)
|
||||
mem_end_pfn = end;
|
||||
mem_size_pfn += size;
|
||||
}
|
||||
|
||||
zones_size[0] = mem_end_pfn - mem_start_pfn;
|
||||
holes_size[0] = zones_size[0] - mem_size_pfn;
|
||||
|
||||
free_area_init_node(0, zones_size, mem_start_pfn, holes_size);
|
||||
}
|
||||
|
||||
void __init paging_init(void)
|
||||
{
|
||||
setup_bootmem();
|
||||
pagetable_init();
|
||||
gateway_init();
|
||||
flush_cache_all_local(); /* start with known state */
|
||||
flush_tlb_all_local(NULL);
|
||||
|
||||
for (i = 0; i < npmem_ranges; i++) {
|
||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
||||
|
||||
zones_size[ZONE_NORMAL] = pmem_ranges[i].pages;
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
/* Need to initialize the pfnnid_map before we can initialize
|
||||
the zone */
|
||||
{
|
||||
int j;
|
||||
for (j = (pmem_ranges[i].start_pfn >> PFNNID_SHIFT);
|
||||
j <= ((pmem_ranges[i].start_pfn + pmem_ranges[i].pages) >> PFNNID_SHIFT);
|
||||
j++) {
|
||||
pfnnid_map[j] = i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
free_area_init_node(i, zones_size,
|
||||
pmem_ranges[i].start_pfn, NULL);
|
||||
}
|
||||
/*
|
||||
* Mark all memblocks as present for sparsemem using
|
||||
* memory_present() and then initialize sparsemem.
|
||||
*/
|
||||
memblocks_present();
|
||||
sparse_init();
|
||||
parisc_bootmem_free();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PA20
|
||||
|
||||
@@ -152,6 +152,7 @@ config PPC
|
||||
select ARCH_USE_BUILTIN_BSWAP
|
||||
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
|
||||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
|
||||
select ARCH_WEAK_RELEASE_ACQUIRE
|
||||
select BINFMT_ELF
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
@@ -1009,6 +1010,19 @@ config FSL_RIO
|
||||
|
||||
source "drivers/rapidio/Kconfig"
|
||||
|
||||
config PPC_RTAS_FILTER
|
||||
bool "Enable filtering of RTAS syscalls"
|
||||
default y
|
||||
depends on PPC_RTAS
|
||||
help
|
||||
The RTAS syscall API has security issues that could be used to
|
||||
compromise system integrity. This option enforces restrictions on the
|
||||
RTAS calls and arguments passed by userspace programs to mitigate
|
||||
these issues.
|
||||
|
||||
Say Y unless you know what you are doing and the filter is causing
|
||||
problems for you.
|
||||
|
||||
endmenu
|
||||
|
||||
config NONSTATIC_KERNEL
|
||||
|
||||
22
arch/powerpc/include/asm/book3s/64/kup-radix.h
Normal file
22
arch/powerpc/include/asm/book3s/64/kup-radix.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
|
||||
|
||||
/* Prototype for function defined in exceptions-64s.S */
|
||||
void do_uaccess_flush(void);
|
||||
|
||||
static __always_inline void allow_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void prevent_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size)
|
||||
{
|
||||
if (static_branch_unlikely(&uaccess_flush_key))
|
||||
do_uaccess_flush();
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */
|
||||
@@ -24,7 +24,7 @@ struct drmem_lmb {
|
||||
struct drmem_lmb_info {
|
||||
struct drmem_lmb *lmbs;
|
||||
int n_lmbs;
|
||||
u32 lmb_size;
|
||||
u64 lmb_size;
|
||||
};
|
||||
|
||||
extern struct drmem_lmb_info *drmem_info;
|
||||
@@ -83,7 +83,7 @@ struct of_drconf_cell_v2 {
|
||||
#define DRCONF_MEM_AI_INVALID 0x00000040
|
||||
#define DRCONF_MEM_RESERVED 0x00000080
|
||||
|
||||
static inline u32 drmem_lmb_size(void)
|
||||
static inline u64 drmem_lmb_size(void)
|
||||
{
|
||||
return drmem_info->lmb_size;
|
||||
}
|
||||
|
||||
@@ -90,11 +90,18 @@
|
||||
nop; \
|
||||
nop
|
||||
|
||||
#define ENTRY_FLUSH_SLOT \
|
||||
ENTRY_FLUSH_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop;
|
||||
|
||||
/*
|
||||
* r10 must be free to use, r13 must be paca
|
||||
*/
|
||||
#define INTERRUPT_TO_KERNEL \
|
||||
STF_ENTRY_BARRIER_SLOT
|
||||
STF_ENTRY_BARRIER_SLOT; \
|
||||
ENTRY_FLUSH_SLOT
|
||||
|
||||
/*
|
||||
* Macros for annotating the expected destination of (h)rfid
|
||||
|
||||
@@ -205,6 +205,22 @@ label##3: \
|
||||
FTR_ENTRY_OFFSET 955b-956b; \
|
||||
.popsection;
|
||||
|
||||
#define UACCESS_FLUSH_FIXUP_SECTION \
|
||||
959: \
|
||||
.pushsection __uaccess_flush_fixup,"a"; \
|
||||
.align 2; \
|
||||
960: \
|
||||
FTR_ENTRY_OFFSET 959b-960b; \
|
||||
.popsection;
|
||||
|
||||
#define ENTRY_FLUSH_FIXUP_SECTION \
|
||||
957: \
|
||||
.pushsection __entry_flush_fixup,"a"; \
|
||||
.align 2; \
|
||||
958: \
|
||||
FTR_ENTRY_OFFSET 957b-958b; \
|
||||
.popsection;
|
||||
|
||||
#define RFI_FLUSH_FIXUP_SECTION \
|
||||
951: \
|
||||
.pushsection __rfi_flush_fixup,"a"; \
|
||||
@@ -237,8 +253,11 @@ label##3: \
|
||||
#include <linux/types.h>
|
||||
|
||||
extern long stf_barrier_fallback;
|
||||
extern long entry_flush_fallback;
|
||||
extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
|
||||
extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
|
||||
extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;
|
||||
extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;
|
||||
extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
|
||||
extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
|
||||
extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
|
||||
|
||||
@@ -35,6 +35,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
{
|
||||
int oldval = 0, ret;
|
||||
|
||||
allow_write_to_user(uaddr, sizeof(*uaddr));
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
@@ -61,6 +62,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||
|
||||
*oval = oldval;
|
||||
|
||||
prevent_write_to_user(uaddr, sizeof(*uaddr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -74,6 +76,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
allow_write_to_user(uaddr, sizeof(*uaddr));
|
||||
__asm__ __volatile__ (
|
||||
PPC_ATOMIC_ENTRY_BARRIER
|
||||
"1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
|
||||
@@ -94,6 +97,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
: "cc", "memory");
|
||||
|
||||
*uval = prev;
|
||||
prevent_write_to_user(uaddr, sizeof(*uaddr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
40
arch/powerpc/include/asm/kup.h
Normal file
40
arch/powerpc/include/asm/kup.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_KUP_H_
|
||||
#define _ASM_POWERPC_KUP_H_
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
#include <asm/book3s/64/kup-radix.h>
|
||||
#else
|
||||
static inline void allow_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size) { }
|
||||
static inline void prevent_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size) { }
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
static inline void allow_read_from_user(const void __user *from, unsigned long size)
|
||||
{
|
||||
allow_user_access(NULL, from, size);
|
||||
}
|
||||
|
||||
static inline void allow_write_to_user(void __user *to, unsigned long size)
|
||||
{
|
||||
allow_user_access(to, NULL, size);
|
||||
}
|
||||
|
||||
static inline void prevent_read_from_user(const void __user *from, unsigned long size)
|
||||
{
|
||||
prevent_user_access(NULL, from, size);
|
||||
}
|
||||
|
||||
static inline void prevent_write_to_user(void __user *to, unsigned long size)
|
||||
{
|
||||
prevent_user_access(to, NULL, size);
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_KUP_H_ */
|
||||
@@ -204,7 +204,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
*/
|
||||
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
||||
{
|
||||
switch_mm(prev, next, current);
|
||||
switch_mm_irqs_off(prev, next, current);
|
||||
}
|
||||
|
||||
/* We don't currently use enter_lazy_tlb() for anything */
|
||||
|
||||
@@ -84,12 +84,19 @@ static inline bool security_ftr_enabled(unsigned long feature)
|
||||
// Software required to flush link stack on context switch
|
||||
#define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull
|
||||
|
||||
// The L1-D cache should be flushed when entering the kernel
|
||||
#define SEC_FTR_L1D_FLUSH_ENTRY 0x0000000000004000ull
|
||||
|
||||
// The L1-D cache should be flushed after user accesses from the kernel
|
||||
#define SEC_FTR_L1D_FLUSH_UACCESS 0x0000000000008000ull
|
||||
|
||||
// Features enabled by default
|
||||
#define SEC_FTR_DEFAULT \
|
||||
(SEC_FTR_L1D_FLUSH_HV | \
|
||||
SEC_FTR_L1D_FLUSH_PR | \
|
||||
SEC_FTR_BNDS_CHK_SPEC_BAR | \
|
||||
SEC_FTR_L1D_FLUSH_ENTRY | \
|
||||
SEC_FTR_L1D_FLUSH_UACCESS | \
|
||||
SEC_FTR_FAVOUR_SECURITY)
|
||||
|
||||
#endif /* _ASM_POWERPC_SECURITY_FEATURES_H */
|
||||
|
||||
@@ -52,12 +52,16 @@ enum l1d_flush_type {
|
||||
};
|
||||
|
||||
void setup_rfi_flush(enum l1d_flush_type, bool enable);
|
||||
void setup_entry_flush(bool enable);
|
||||
void setup_uaccess_flush(bool enable);
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types);
|
||||
#ifdef CONFIG_PPC_BARRIER_NOSPEC
|
||||
void setup_barrier_nospec(void);
|
||||
#else
|
||||
static inline void setup_barrier_nospec(void) { };
|
||||
#endif
|
||||
void do_uaccess_flush_fixups(enum l1d_flush_type types);
|
||||
void do_entry_flush_fixups(enum l1d_flush_type types);
|
||||
void do_barrier_nospec_fixups(bool enable);
|
||||
extern bool barrier_nospec_enabled;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/extable.h>
|
||||
#include <asm/kup.h>
|
||||
|
||||
/*
|
||||
* The fs value determines whether argument validity checking should be
|
||||
@@ -91,9 +92,14 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
|
||||
__put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
|
||||
__get_user_nocheck((x), (ptr), sizeof(*(ptr)), true)
|
||||
#define __put_user(x, ptr) \
|
||||
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
|
||||
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), true)
|
||||
|
||||
#define __get_user_allowed(x, ptr) \
|
||||
__get_user_nocheck((x), (ptr), sizeof(*(ptr)), false)
|
||||
#define __put_user_allowed(x, ptr) \
|
||||
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), false)
|
||||
|
||||
#define __get_user_inatomic(x, ptr) \
|
||||
__get_user_nosleep((x), (ptr), sizeof(*(ptr)))
|
||||
@@ -138,7 +144,7 @@ extern long __put_user_bad(void);
|
||||
: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
#define __put_user_size(x, ptr, size, retval) \
|
||||
#define __put_user_size_allowed(x, ptr, size, retval) \
|
||||
do { \
|
||||
retval = 0; \
|
||||
switch (size) { \
|
||||
@@ -150,14 +156,28 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __put_user_nocheck(x, ptr, size) \
|
||||
#define __put_user_size(x, ptr, size, retval) \
|
||||
do { \
|
||||
allow_write_to_user(ptr, size); \
|
||||
__put_user_size_allowed(x, ptr, size, retval); \
|
||||
prevent_write_to_user(ptr, size); \
|
||||
} while (0)
|
||||
|
||||
#define __put_user_nocheck(x, ptr, size, do_allow) \
|
||||
({ \
|
||||
long __pu_err; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__typeof__(size) __pu_size = (size); \
|
||||
\
|
||||
if (!is_kernel_addr((unsigned long)__pu_addr)) \
|
||||
might_fault(); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
__chk_user_ptr(__pu_addr); \
|
||||
if (do_allow) \
|
||||
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
else \
|
||||
__put_user_size_allowed(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
\
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
@@ -165,9 +185,13 @@ do { \
|
||||
({ \
|
||||
long __pu_err = -EFAULT; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__typeof__(size) __pu_size = (size); \
|
||||
\
|
||||
might_fault(); \
|
||||
if (access_ok(VERIFY_WRITE, __pu_addr, size)) \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
if (access_ok(VERIFY_WRITE, __pu_addr, __pu_size)) \
|
||||
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
\
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
@@ -175,8 +199,12 @@ do { \
|
||||
({ \
|
||||
long __pu_err; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__typeof__(size) __pu_size = (size); \
|
||||
\
|
||||
__chk_user_ptr(__pu_addr); \
|
||||
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
\
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
@@ -234,7 +262,7 @@ extern long __get_user_bad(void);
|
||||
: "b" (addr), "i" (-EFAULT), "0" (err))
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
#define __get_user_size(x, ptr, size, retval) \
|
||||
#define __get_user_size_allowed(x, ptr, size, retval) \
|
||||
do { \
|
||||
retval = 0; \
|
||||
__chk_user_ptr(ptr); \
|
||||
@@ -249,6 +277,13 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __get_user_size(x, ptr, size, retval) \
|
||||
do { \
|
||||
allow_read_from_user(ptr, size); \
|
||||
__get_user_size_allowed(x, ptr, size, retval); \
|
||||
prevent_read_from_user(ptr, size); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is a type: either unsigned long, if the argument fits into
|
||||
* that type, or otherwise unsigned long long.
|
||||
@@ -256,17 +291,23 @@ do { \
|
||||
#define __long_type(x) \
|
||||
__typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
|
||||
|
||||
#define __get_user_nocheck(x, ptr, size) \
|
||||
#define __get_user_nocheck(x, ptr, size, do_allow) \
|
||||
({ \
|
||||
long __gu_err; \
|
||||
__long_type(*(ptr)) __gu_val; \
|
||||
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__typeof__(size) __gu_size = (size); \
|
||||
\
|
||||
__chk_user_ptr(__gu_addr); \
|
||||
if (!is_kernel_addr((unsigned long)__gu_addr)) \
|
||||
might_fault(); \
|
||||
barrier_nospec(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
if (do_allow) \
|
||||
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
else \
|
||||
__get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
(x) = (__typeof__(*(ptr)))__gu_val; \
|
||||
\
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@@ -275,12 +316,15 @@ do { \
|
||||
long __gu_err = -EFAULT; \
|
||||
__long_type(*(ptr)) __gu_val = 0; \
|
||||
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__typeof__(size) __gu_size = (size); \
|
||||
\
|
||||
might_fault(); \
|
||||
if (access_ok(VERIFY_READ, __gu_addr, (size))) { \
|
||||
if (access_ok(VERIFY_READ, __gu_addr, __gu_size)) { \
|
||||
barrier_nospec(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
} \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
\
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@@ -289,10 +333,13 @@ do { \
|
||||
long __gu_err; \
|
||||
__long_type(*(ptr)) __gu_val; \
|
||||
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__typeof__(size) __gu_size = (size); \
|
||||
\
|
||||
__chk_user_ptr(__gu_addr); \
|
||||
barrier_nospec(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
\
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@@ -306,16 +353,22 @@ extern unsigned long __copy_tofrom_user(void __user *to,
|
||||
static inline unsigned long
|
||||
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
barrier_nospec();
|
||||
return __copy_tofrom_user(to, from, n);
|
||||
allow_user_access(to, from, n);
|
||||
ret = __copy_tofrom_user(to, from, n);
|
||||
prevent_user_access(to, from, n);
|
||||
return ret;
|
||||
}
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
static inline unsigned long raw_copy_from_user(void *to,
|
||||
const void __user *from, unsigned long n)
|
||||
{
|
||||
unsigned long ret;
|
||||
if (__builtin_constant_p(n) && (n <= 8)) {
|
||||
unsigned long ret = 1;
|
||||
ret = 1;
|
||||
|
||||
switch (n) {
|
||||
case 1:
|
||||
@@ -340,27 +393,30 @@ static inline unsigned long raw_copy_from_user(void *to,
|
||||
}
|
||||
|
||||
barrier_nospec();
|
||||
return __copy_tofrom_user((__force void __user *)to, from, n);
|
||||
allow_read_from_user(from, n);
|
||||
ret = __copy_tofrom_user((__force void __user *)to, from, n);
|
||||
prevent_read_from_user(from, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long raw_copy_to_user(void __user *to,
|
||||
const void *from, unsigned long n)
|
||||
static inline unsigned long
|
||||
raw_copy_to_user_allowed(void __user *to, const void *from, unsigned long n)
|
||||
{
|
||||
if (__builtin_constant_p(n) && (n <= 8)) {
|
||||
unsigned long ret = 1;
|
||||
|
||||
switch (n) {
|
||||
case 1:
|
||||
__put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret);
|
||||
__put_user_size_allowed(*(u8 *)from, (u8 __user *)to, 1, ret);
|
||||
break;
|
||||
case 2:
|
||||
__put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret);
|
||||
__put_user_size_allowed(*(u16 *)from, (u16 __user *)to, 2, ret);
|
||||
break;
|
||||
case 4:
|
||||
__put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret);
|
||||
__put_user_size_allowed(*(u32 *)from, (u32 __user *)to, 4, ret);
|
||||
break;
|
||||
case 8:
|
||||
__put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret);
|
||||
__put_user_size_allowed(*(u64 *)from, (u64 __user *)to, 8, ret);
|
||||
break;
|
||||
}
|
||||
if (ret == 0)
|
||||
@@ -370,14 +426,34 @@ static inline unsigned long raw_copy_to_user(void __user *to,
|
||||
return __copy_tofrom_user(to, (__force const void __user *)from, n);
|
||||
}
|
||||
|
||||
extern unsigned long __clear_user(void __user *addr, unsigned long size);
|
||||
static inline unsigned long
|
||||
raw_copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
allow_write_to_user(to, n);
|
||||
ret = raw_copy_to_user_allowed(to, from, n);
|
||||
prevent_write_to_user(to, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned long __arch_clear_user(void __user *addr, unsigned long size);
|
||||
|
||||
static inline unsigned long clear_user(void __user *addr, unsigned long size)
|
||||
{
|
||||
unsigned long ret = size;
|
||||
might_fault();
|
||||
if (likely(access_ok(VERIFY_WRITE, addr, size)))
|
||||
return __clear_user(addr, size);
|
||||
return size;
|
||||
if (likely(access_ok(VERIFY_WRITE, addr, size))) {
|
||||
allow_write_to_user(addr, size);
|
||||
ret = __arch_clear_user(addr, size);
|
||||
prevent_write_to_user(addr, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long __clear_user(void __user *addr, unsigned long size)
|
||||
{
|
||||
return clear_user(addr, size);
|
||||
}
|
||||
|
||||
extern long strncpy_from_user(char *dst, const char __user *src, long count);
|
||||
@@ -388,4 +464,13 @@ extern long __copy_from_user_flushcache(void *dst, const void __user *src,
|
||||
extern void memcpy_page_flushcache(char *to, struct page *page, size_t offset,
|
||||
size_t len);
|
||||
|
||||
#define user_access_begin(type, ptr, len) access_ok(type, ptr, len)
|
||||
#define user_access_end() prevent_user_access(NULL, NULL, ~0ul)
|
||||
|
||||
#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0)
|
||||
#define unsafe_get_user(x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e)
|
||||
#define unsafe_put_user(x, p, e) unsafe_op_wrap(__put_user_allowed(x, p), e)
|
||||
#define unsafe_copy_to_user(d, s, l, e) \
|
||||
unsafe_op_wrap(raw_copy_to_user_allowed(d, s, l), e)
|
||||
|
||||
#endif /* _ARCH_POWERPC_UACCESS_H */
|
||||
|
||||
@@ -540,7 +540,7 @@ EXC_COMMON_BEGIN(unrecover_mce)
|
||||
b 1b
|
||||
|
||||
|
||||
EXC_REAL(data_access, 0x300, 0x80)
|
||||
EXC_REAL_OOL(data_access, 0x300, 0x80)
|
||||
EXC_VIRT(data_access, 0x4300, 0x80, 0x300)
|
||||
TRAMP_KVM_SKIP(PACA_EXGEN, 0x300)
|
||||
|
||||
@@ -572,13 +572,16 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
|
||||
EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
|
||||
SET_SCRATCH0(r13)
|
||||
EXCEPTION_PROLOG_0(PACA_EXSLB)
|
||||
b tramp_data_access_slb
|
||||
EXC_REAL_END(data_access_slb, 0x380, 0x80)
|
||||
|
||||
TRAMP_REAL_BEGIN(tramp_data_access_slb)
|
||||
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
|
||||
mr r12,r3 /* save r3 */
|
||||
mfspr r3,SPRN_DAR
|
||||
mfspr r11,SPRN_SRR1
|
||||
crset 4*cr6+eq
|
||||
BRANCH_TO_COMMON(r10, slb_miss_common)
|
||||
EXC_REAL_END(data_access_slb, 0x380, 0x80)
|
||||
|
||||
EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
|
||||
SET_SCRATCH0(r13)
|
||||
@@ -593,7 +596,7 @@ EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
|
||||
TRAMP_KVM_SKIP(PACA_EXSLB, 0x380)
|
||||
|
||||
|
||||
EXC_REAL(instruction_access, 0x400, 0x80)
|
||||
EXC_REAL_OOL(instruction_access, 0x400, 0x80)
|
||||
EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400)
|
||||
TRAMP_KVM(PACA_EXGEN, 0x400)
|
||||
|
||||
@@ -616,13 +619,16 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
|
||||
EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
|
||||
SET_SCRATCH0(r13)
|
||||
EXCEPTION_PROLOG_0(PACA_EXSLB)
|
||||
b tramp_instruction_access_slb
|
||||
EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
|
||||
|
||||
TRAMP_REAL_BEGIN(tramp_instruction_access_slb)
|
||||
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480)
|
||||
mr r12,r3 /* save r3 */
|
||||
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
|
||||
mfspr r11,SPRN_SRR1
|
||||
crclr 4*cr6+eq
|
||||
BRANCH_TO_COMMON(r10, slb_miss_common)
|
||||
EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
|
||||
|
||||
EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
|
||||
SET_SCRATCH0(r13)
|
||||
@@ -883,13 +889,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
||||
|
||||
|
||||
EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED)
|
||||
EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED)
|
||||
EXC_VIRT_OOL_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED)
|
||||
TRAMP_KVM(PACA_EXGEN, 0x900)
|
||||
EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt)
|
||||
|
||||
|
||||
EXC_REAL_HV(hdecrementer, 0x980, 0x80)
|
||||
EXC_VIRT_HV(hdecrementer, 0x4980, 0x80, 0x980)
|
||||
EXC_REAL_OOL_HV(hdecrementer, 0x980, 0x80)
|
||||
EXC_VIRT_OOL_HV(hdecrementer, 0x4980, 0x80, 0x980)
|
||||
TRAMP_KVM_HV(PACA_EXGEN, 0x980)
|
||||
EXC_COMMON(hdecrementer_common, 0x980, hdec_interrupt)
|
||||
|
||||
@@ -1523,15 +1529,8 @@ TRAMP_REAL_BEGIN(stf_barrier_fallback)
|
||||
.endr
|
||||
blr
|
||||
|
||||
TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r1,PACA_EXRFI+EX_R12(r13)
|
||||
ld r1,PACAKSAVE(r13)
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
mfctr r9
|
||||
/* Clobbers r10, r11, ctr */
|
||||
.macro L1D_DISPLACEMENT_FLUSH
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SIZE(r13)
|
||||
srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */
|
||||
@@ -1542,7 +1541,7 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
sync
|
||||
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* The load addresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
@@ -1557,7 +1556,30 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
ld r11,(0x80 + 8)*7(r10)
|
||||
addi r10,r10,0x80*8
|
||||
bdnz 1b
|
||||
.endm
|
||||
|
||||
TRAMP_REAL_BEGIN(entry_flush_fallback)
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
mfctr r9
|
||||
L1D_DISPLACEMENT_FLUSH
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
blr
|
||||
|
||||
TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r1,PACA_EXRFI+EX_R12(r13)
|
||||
ld r1,PACAKSAVE(r13)
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
mfctr r9
|
||||
L1D_DISPLACEMENT_FLUSH
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
@@ -1575,32 +1597,7 @@ TRAMP_REAL_BEGIN(hrfi_flush_fallback)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SIZE(r13)
|
||||
srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */
|
||||
mtctr r11
|
||||
DCBT_BOOK3S_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
1:
|
||||
ld r11,(0x80 + 8)*0(r10)
|
||||
ld r11,(0x80 + 8)*1(r10)
|
||||
ld r11,(0x80 + 8)*2(r10)
|
||||
ld r11,(0x80 + 8)*3(r10)
|
||||
ld r11,(0x80 + 8)*4(r10)
|
||||
ld r11,(0x80 + 8)*5(r10)
|
||||
ld r11,(0x80 + 8)*6(r10)
|
||||
ld r11,(0x80 + 8)*7(r10)
|
||||
addi r10,r10,0x80*8
|
||||
bdnz 1b
|
||||
|
||||
L1D_DISPLACEMENT_FLUSH
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
@@ -1609,6 +1606,19 @@ TRAMP_REAL_BEGIN(hrfi_flush_fallback)
|
||||
GET_SCRATCH0(r13);
|
||||
hrfid
|
||||
|
||||
USE_TEXT_SECTION()
|
||||
|
||||
_GLOBAL(do_uaccess_flush)
|
||||
UACCESS_FLUSH_FIXUP_SECTION
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
blr
|
||||
L1D_DISPLACEMENT_FLUSH
|
||||
blr
|
||||
_ASM_NOKPROBE_SYMBOL(do_uaccess_flush)
|
||||
EXPORT_SYMBOL(do_uaccess_flush)
|
||||
|
||||
/*
|
||||
* Real mode exceptions actually use this too, but alternate
|
||||
* instruction code patches (which end up in the common .text area)
|
||||
|
||||
@@ -356,11 +356,9 @@ _ENTRY(ITLBMiss_cmp)
|
||||
/* Load the MI_TWC with the attributes for this "segment." */
|
||||
mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
|
||||
|
||||
#ifdef CONFIG_SWAP
|
||||
rlwinm r11, r10, 32-5, _PAGE_PRESENT
|
||||
rlwinm r11, r10, 32-7, _PAGE_PRESENT
|
||||
and r11, r11, r10
|
||||
rlwimi r10, r11, 0, _PAGE_PRESENT
|
||||
#endif
|
||||
li r11, RPN_PATTERN | 0x200
|
||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||
* Software indicator bits 20 and 23 must be clear.
|
||||
@@ -482,11 +480,9 @@ _ENTRY(DTLBMiss_jmp)
|
||||
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
|
||||
* r10 = (r10 & ~PRESENT) | r11;
|
||||
*/
|
||||
#ifdef CONFIG_SWAP
|
||||
rlwinm r11, r10, 32-5, _PAGE_PRESENT
|
||||
rlwinm r11, r10, 32-7, _PAGE_PRESENT
|
||||
and r11, r11, r10
|
||||
rlwimi r10, r11, 0, _PAGE_PRESENT
|
||||
#endif
|
||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||
* Software indicator bits 24, 25, 26, and 27 must be
|
||||
* set. All other Linux PTE bits control the behavior
|
||||
|
||||
@@ -1057,6 +1057,147 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS_FILTER
|
||||
|
||||
/*
|
||||
* The sys_rtas syscall, as originally designed, allows root to pass
|
||||
* arbitrary physical addresses to RTAS calls. A number of RTAS calls
|
||||
* can be abused to write to arbitrary memory and do other things that
|
||||
* are potentially harmful to system integrity, and thus should only
|
||||
* be used inside the kernel and not exposed to userspace.
|
||||
*
|
||||
* All known legitimate users of the sys_rtas syscall will only ever
|
||||
* pass addresses that fall within the RMO buffer, and use a known
|
||||
* subset of RTAS calls.
|
||||
*
|
||||
* Accordingly, we filter RTAS requests to check that the call is
|
||||
* permitted, and that provided pointers fall within the RMO buffer.
|
||||
* The rtas_filters list contains an entry for each permitted call,
|
||||
* with the indexes of the parameters which are expected to contain
|
||||
* addresses and sizes of buffers allocated inside the RMO buffer.
|
||||
*/
|
||||
struct rtas_filter {
|
||||
const char *name;
|
||||
int token;
|
||||
/* Indexes into the args buffer, -1 if not used */
|
||||
int buf_idx1;
|
||||
int size_idx1;
|
||||
int buf_idx2;
|
||||
int size_idx2;
|
||||
|
||||
int fixed_size;
|
||||
};
|
||||
|
||||
static struct rtas_filter rtas_filters[] __ro_after_init = {
|
||||
{ "ibm,activate-firmware", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,configure-connector", -1, 0, -1, 1, -1, 4096 }, /* Special cased */
|
||||
{ "display-character", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,display-message", -1, 0, -1, -1, -1 },
|
||||
{ "ibm,errinjct", -1, 2, -1, -1, -1, 1024 },
|
||||
{ "ibm,close-errinjct", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,open-errinct", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,get-config-addr-info2", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,get-dynamic-sensor-state", -1, 1, -1, -1, -1 },
|
||||
{ "ibm,get-indices", -1, 2, 3, -1, -1 },
|
||||
{ "get-power-level", -1, -1, -1, -1, -1 },
|
||||
{ "get-sensor-state", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,get-system-parameter", -1, 1, 2, -1, -1 },
|
||||
{ "get-time-of-day", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,get-vpd", -1, 0, -1, 1, 2 },
|
||||
{ "ibm,lpar-perftools", -1, 2, 3, -1, -1 },
|
||||
{ "ibm,platform-dump", -1, 4, 5, -1, -1 },
|
||||
{ "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,scan-log-dump", -1, 0, 1, -1, -1 },
|
||||
{ "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 },
|
||||
{ "ibm,set-eeh-option", -1, -1, -1, -1, -1 },
|
||||
{ "set-indicator", -1, -1, -1, -1, -1 },
|
||||
{ "set-power-level", -1, -1, -1, -1, -1 },
|
||||
{ "set-time-for-power-on", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,set-system-parameter", -1, 1, -1, -1, -1 },
|
||||
{ "set-time-of-day", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,suspend-me", -1, -1, -1, -1, -1 },
|
||||
{ "ibm,update-nodes", -1, 0, -1, -1, -1, 4096 },
|
||||
{ "ibm,update-properties", -1, 0, -1, -1, -1, 4096 },
|
||||
{ "ibm,physical-attestation", -1, 0, 1, -1, -1 },
|
||||
};
|
||||
|
||||
static bool in_rmo_buf(u32 base, u32 end)
|
||||
{
|
||||
return base >= rtas_rmo_buf &&
|
||||
base < (rtas_rmo_buf + RTAS_RMOBUF_MAX) &&
|
||||
base <= end &&
|
||||
end >= rtas_rmo_buf &&
|
||||
end < (rtas_rmo_buf + RTAS_RMOBUF_MAX);
|
||||
}
|
||||
|
||||
static bool block_rtas_call(int token, int nargs,
|
||||
struct rtas_args *args)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
|
||||
struct rtas_filter *f = &rtas_filters[i];
|
||||
u32 base, size, end;
|
||||
|
||||
if (token != f->token)
|
||||
continue;
|
||||
|
||||
if (f->buf_idx1 != -1) {
|
||||
base = be32_to_cpu(args->args[f->buf_idx1]);
|
||||
if (f->size_idx1 != -1)
|
||||
size = be32_to_cpu(args->args[f->size_idx1]);
|
||||
else if (f->fixed_size)
|
||||
size = f->fixed_size;
|
||||
else
|
||||
size = 1;
|
||||
|
||||
end = base + size - 1;
|
||||
if (!in_rmo_buf(base, end))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (f->buf_idx2 != -1) {
|
||||
base = be32_to_cpu(args->args[f->buf_idx2]);
|
||||
if (f->size_idx2 != -1)
|
||||
size = be32_to_cpu(args->args[f->size_idx2]);
|
||||
else if (f->fixed_size)
|
||||
size = f->fixed_size;
|
||||
else
|
||||
size = 1;
|
||||
end = base + size - 1;
|
||||
|
||||
/*
|
||||
* Special case for ibm,configure-connector where the
|
||||
* address can be 0
|
||||
*/
|
||||
if (!strcmp(f->name, "ibm,configure-connector") &&
|
||||
base == 0)
|
||||
return false;
|
||||
|
||||
if (!in_rmo_buf(base, end))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
err:
|
||||
pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n");
|
||||
pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n",
|
||||
token, nargs, current->comm);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool block_rtas_call(int token, int nargs,
|
||||
struct rtas_args *args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_RTAS_FILTER */
|
||||
|
||||
/* We assume to be passed big endian arguments */
|
||||
SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
{
|
||||
@@ -1094,6 +1235,9 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
args.rets = &args.args[nargs];
|
||||
memset(args.rets, 0, nret * sizeof(rtas_arg_t));
|
||||
|
||||
if (block_rtas_call(token, nargs, &args))
|
||||
return -EINVAL;
|
||||
|
||||
/* Need to handle ibm,suspend_me call specially */
|
||||
if (token == ibm_suspend_me_token) {
|
||||
|
||||
@@ -1155,6 +1299,9 @@ void __init rtas_initialize(void)
|
||||
unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
|
||||
u32 base, size, entry;
|
||||
int no_base, no_size, no_entry;
|
||||
#ifdef CONFIG_PPC_RTAS_FILTER
|
||||
int i;
|
||||
#endif
|
||||
|
||||
/* Get RTAS dev node and fill up our "rtas" structure with infos
|
||||
* about it.
|
||||
@@ -1190,6 +1337,12 @@ void __init rtas_initialize(void)
|
||||
#ifdef CONFIG_RTAS_ERROR_LOGGING
|
||||
rtas_last_error_token = rtas_token("rtas-last-error");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS_FILTER
|
||||
for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
|
||||
rtas_filters[i].token = rtas_token(rtas_filters[i].name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int __init early_init_dt_scan_rtas(unsigned long node,
|
||||
|
||||
@@ -863,7 +863,13 @@ early_initcall(disable_hardlockup_detector);
|
||||
static enum l1d_flush_type enabled_flush_types;
|
||||
static void *l1d_flush_fallback_area;
|
||||
static bool no_rfi_flush;
|
||||
static bool no_entry_flush;
|
||||
static bool no_uaccess_flush;
|
||||
bool rfi_flush;
|
||||
bool entry_flush;
|
||||
bool uaccess_flush;
|
||||
DEFINE_STATIC_KEY_FALSE(uaccess_flush_key);
|
||||
EXPORT_SYMBOL(uaccess_flush_key);
|
||||
|
||||
static int __init handle_no_rfi_flush(char *p)
|
||||
{
|
||||
@@ -873,6 +879,22 @@ static int __init handle_no_rfi_flush(char *p)
|
||||
}
|
||||
early_param("no_rfi_flush", handle_no_rfi_flush);
|
||||
|
||||
static int __init handle_no_entry_flush(char *p)
|
||||
{
|
||||
pr_info("entry-flush: disabled on command line.");
|
||||
no_entry_flush = true;
|
||||
return 0;
|
||||
}
|
||||
early_param("no_entry_flush", handle_no_entry_flush);
|
||||
|
||||
static int __init handle_no_uaccess_flush(char *p)
|
||||
{
|
||||
pr_info("uaccess-flush: disabled on command line.");
|
||||
no_uaccess_flush = true;
|
||||
return 0;
|
||||
}
|
||||
early_param("no_uaccess_flush", handle_no_uaccess_flush);
|
||||
|
||||
/*
|
||||
* The RFI flush is not KPTI, but because users will see doco that says to use
|
||||
* nopti we hijack that option here to also disable the RFI flush.
|
||||
@@ -904,6 +926,32 @@ void rfi_flush_enable(bool enable)
|
||||
rfi_flush = enable;
|
||||
}
|
||||
|
||||
void entry_flush_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
do_entry_flush_fixups(enabled_flush_types);
|
||||
on_each_cpu(do_nothing, NULL, 1);
|
||||
} else {
|
||||
do_entry_flush_fixups(L1D_FLUSH_NONE);
|
||||
}
|
||||
|
||||
entry_flush = enable;
|
||||
}
|
||||
|
||||
void uaccess_flush_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
do_uaccess_flush_fixups(enabled_flush_types);
|
||||
static_branch_enable(&uaccess_flush_key);
|
||||
on_each_cpu(do_nothing, NULL, 1);
|
||||
} else {
|
||||
static_branch_disable(&uaccess_flush_key);
|
||||
do_uaccess_flush_fixups(L1D_FLUSH_NONE);
|
||||
}
|
||||
|
||||
uaccess_flush = enable;
|
||||
}
|
||||
|
||||
static void __ref init_fallback_flush(void)
|
||||
{
|
||||
u64 l1d_size, limit;
|
||||
@@ -957,10 +1005,28 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable)
|
||||
|
||||
enabled_flush_types = types;
|
||||
|
||||
if (!no_rfi_flush && !cpu_mitigations_off())
|
||||
if (!cpu_mitigations_off() && !no_rfi_flush)
|
||||
rfi_flush_enable(enable);
|
||||
}
|
||||
|
||||
void setup_entry_flush(bool enable)
|
||||
{
|
||||
if (cpu_mitigations_off())
|
||||
return;
|
||||
|
||||
if (!no_entry_flush)
|
||||
entry_flush_enable(enable);
|
||||
}
|
||||
|
||||
void setup_uaccess_flush(bool enable)
|
||||
{
|
||||
if (cpu_mitigations_off())
|
||||
return;
|
||||
|
||||
if (!no_uaccess_flush)
|
||||
uaccess_flush_enable(enable);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int rfi_flush_set(void *data, u64 val)
|
||||
{
|
||||
@@ -988,9 +1054,63 @@ static int rfi_flush_get(void *data, u64 *val)
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
|
||||
|
||||
static int entry_flush_set(void *data, u64 val)
|
||||
{
|
||||
bool enable;
|
||||
|
||||
if (val == 1)
|
||||
enable = true;
|
||||
else if (val == 0)
|
||||
enable = false;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* Only do anything if we're changing state */
|
||||
if (enable != entry_flush)
|
||||
entry_flush_enable(enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int entry_flush_get(void *data, u64 *val)
|
||||
{
|
||||
*val = entry_flush ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_entry_flush, entry_flush_get, entry_flush_set, "%llu\n");
|
||||
|
||||
static int uaccess_flush_set(void *data, u64 val)
|
||||
{
|
||||
bool enable;
|
||||
|
||||
if (val == 1)
|
||||
enable = true;
|
||||
else if (val == 0)
|
||||
enable = false;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* Only do anything if we're changing state */
|
||||
if (enable != uaccess_flush)
|
||||
uaccess_flush_enable(enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uaccess_flush_get(void *data, u64 *val)
|
||||
{
|
||||
*val = uaccess_flush ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_uaccess_flush, uaccess_flush_get, uaccess_flush_set, "%llu\n");
|
||||
|
||||
static __init int rfi_flush_debugfs_init(void)
|
||||
{
|
||||
debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
|
||||
debugfs_create_file("entry_flush", 0600, powerpc_debugfs_root, NULL, &fops_entry_flush);
|
||||
debugfs_create_file("uaccess_flush", 0600, powerpc_debugfs_root, NULL, &fops_uaccess_flush);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(rfi_flush_debugfs_init);
|
||||
|
||||
@@ -29,29 +29,27 @@
|
||||
|
||||
static DEFINE_PER_CPU(struct cpu, cpu_devices);
|
||||
|
||||
/*
|
||||
* SMT snooze delay stuff, 64-bit only for now
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
/* Time in microseconds we delay before sleeping in the idle loop */
|
||||
static DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 };
|
||||
/*
|
||||
* Snooze delay has not been hooked up since 3fa8cad82b94 ("powerpc/pseries/cpuidle:
|
||||
* smt-snooze-delay cleanup.") and has been broken even longer. As was foretold in
|
||||
* 2014:
|
||||
*
|
||||
* "ppc64_util currently utilises it. Once we fix ppc64_util, propose to clean
|
||||
* up the kernel code."
|
||||
*
|
||||
* powerpc-utils stopped using it as of 1.3.8. At some point in the future this
|
||||
* code should be removed.
|
||||
*/
|
||||
|
||||
static ssize_t store_smt_snooze_delay(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
ssize_t ret;
|
||||
long snooze;
|
||||
|
||||
ret = sscanf(buf, "%ld", &snooze);
|
||||
if (ret != 1)
|
||||
return -EINVAL;
|
||||
|
||||
per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
|
||||
pr_warn_once("%s (%d) stored to unsupported smt_snooze_delay, which has no effect.\n",
|
||||
current->comm, current->pid);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -59,9 +57,9 @@ static ssize_t show_smt_snooze_delay(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
||||
|
||||
return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id));
|
||||
pr_warn_once("%s (%d) read from unsupported smt_snooze_delay\n",
|
||||
current->comm, current->pid);
|
||||
return sprintf(buf, "100\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
|
||||
@@ -69,16 +67,10 @@ static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
|
||||
|
||||
static int __init setup_smt_snooze_delay(char *str)
|
||||
{
|
||||
unsigned int cpu;
|
||||
long snooze;
|
||||
|
||||
if (!cpu_has_feature(CPU_FTR_SMT))
|
||||
return 1;
|
||||
|
||||
snooze = simple_strtol(str, NULL, 10);
|
||||
for_each_possible_cpu(cpu)
|
||||
per_cpu(smt_snooze_delay, cpu) = snooze;
|
||||
|
||||
pr_warn("smt-snooze-delay command line option has no effect\n");
|
||||
return 1;
|
||||
}
|
||||
__setup("smt-snooze-delay=", setup_smt_snooze_delay);
|
||||
|
||||
@@ -794,7 +794,7 @@ static void p9_hmi_special_emu(struct pt_regs *regs)
|
||||
{
|
||||
unsigned int ra, rb, t, i, sel, instr, rc;
|
||||
const void __user *addr;
|
||||
u8 vbuf[16], *vdst;
|
||||
u8 vbuf[16] __aligned(16), *vdst;
|
||||
unsigned long ea, msr, msr_mask;
|
||||
bool swap;
|
||||
|
||||
|
||||
@@ -140,6 +140,20 @@ SECTIONS
|
||||
__stop___stf_entry_barrier_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__uaccess_flush_fixup : AT(ADDR(__uaccess_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___uaccess_flush_fixup = .;
|
||||
*(__uaccess_flush_fixup)
|
||||
__stop___uaccess_flush_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___entry_flush_fixup = .;
|
||||
*(__entry_flush_fixup)
|
||||
__stop___entry_flush_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) {
|
||||
__start___stf_exit_barrier_fixup = .;
|
||||
|
||||
@@ -29,6 +29,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
||||
unsigned int csum;
|
||||
|
||||
might_sleep();
|
||||
allow_read_from_user(src, len);
|
||||
|
||||
*err_ptr = 0;
|
||||
|
||||
@@ -60,6 +61,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
||||
}
|
||||
|
||||
out:
|
||||
prevent_read_from_user(src, len);
|
||||
return (__force __wsum)csum;
|
||||
}
|
||||
EXPORT_SYMBOL(csum_and_copy_from_user);
|
||||
@@ -70,6 +72,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
||||
unsigned int csum;
|
||||
|
||||
might_sleep();
|
||||
allow_write_to_user(dst, len);
|
||||
|
||||
*err_ptr = 0;
|
||||
|
||||
@@ -97,6 +100,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
||||
}
|
||||
|
||||
out:
|
||||
prevent_write_to_user(dst, len);
|
||||
return (__force __wsum)csum;
|
||||
}
|
||||
EXPORT_SYMBOL(csum_and_copy_to_user);
|
||||
|
||||
@@ -232,6 +232,110 @@ void do_stf_barrier_fixups(enum stf_barrier_type types)
|
||||
do_stf_exit_barrier_fixups(types);
|
||||
}
|
||||
|
||||
void do_uaccess_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[4], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___uaccess_flush_fixup);
|
||||
end = PTRRELOC(&__stop___uaccess_flush_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
instrs[3] = 0x4e800020; /* blr */
|
||||
|
||||
i = 0;
|
||||
if (types == L1D_FLUSH_FALLBACK) {
|
||||
instrs[3] = 0x60000000; /* nop */
|
||||
/* fallthrough to fallback flush */
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_ORI) {
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
|
||||
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction(dest, instrs[0]);
|
||||
|
||||
patch_instruction((dest + 1), instrs[1]);
|
||||
patch_instruction((dest + 2), instrs[2]);
|
||||
patch_instruction((dest + 3), instrs[3]);
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i,
|
||||
(types == L1D_FLUSH_NONE) ? "no" :
|
||||
(types == L1D_FLUSH_FALLBACK) ? "fallback displacement" :
|
||||
(types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG)
|
||||
? "ori+mttrig type"
|
||||
: "ori type" :
|
||||
(types & L1D_FLUSH_MTTRIG) ? "mttrig type"
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
void do_entry_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___entry_flush_fixup);
|
||||
end = PTRRELOC(&__stop___entry_flush_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
|
||||
i = 0;
|
||||
if (types == L1D_FLUSH_FALLBACK) {
|
||||
instrs[i++] = 0x7d4802a6; /* mflr r10 */
|
||||
instrs[i++] = 0x60000000; /* branch patched below */
|
||||
instrs[i++] = 0x7d4803a6; /* mtlr r10 */
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_ORI) {
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
|
||||
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction(dest, instrs[0]);
|
||||
|
||||
if (types == L1D_FLUSH_FALLBACK)
|
||||
patch_branch((dest + 1), (unsigned long)&entry_flush_fallback,
|
||||
BRANCH_SET_LINK);
|
||||
else
|
||||
patch_instruction((dest + 1), instrs[1]);
|
||||
|
||||
patch_instruction((dest + 2), instrs[2]);
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i,
|
||||
(types == L1D_FLUSH_NONE) ? "no" :
|
||||
(types == L1D_FLUSH_FALLBACK) ? "fallback displacement" :
|
||||
(types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG)
|
||||
? "ori+mttrig type"
|
||||
: "ori type" :
|
||||
(types & L1D_FLUSH_MTTRIG) ? "mttrig type"
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
|
||||
@@ -17,7 +17,7 @@ CACHELINE_BYTES = L1_CACHE_BYTES
|
||||
LG_CACHELINE_BYTES = L1_CACHE_SHIFT
|
||||
CACHELINE_MASK = (L1_CACHE_BYTES-1)
|
||||
|
||||
_GLOBAL(__clear_user)
|
||||
_GLOBAL(__arch_clear_user)
|
||||
/*
|
||||
* Use dcbz on the complete cache lines in the destination
|
||||
* to set them to zero. This requires that the destination
|
||||
@@ -87,4 +87,4 @@ _GLOBAL(__clear_user)
|
||||
EX_TABLE(8b, 91b)
|
||||
EX_TABLE(9b, 91b)
|
||||
|
||||
EXPORT_SYMBOL(__clear_user)
|
||||
EXPORT_SYMBOL(__arch_clear_user)
|
||||
|
||||
@@ -29,7 +29,7 @@ PPC64_CACHES:
|
||||
.section ".text"
|
||||
|
||||
/**
|
||||
* __clear_user: - Zero a block of memory in user space, with less checking.
|
||||
* __arch_clear_user: - Zero a block of memory in user space, with less checking.
|
||||
* @to: Destination address, in user space.
|
||||
* @n: Number of bytes to zero.
|
||||
*
|
||||
@@ -70,7 +70,7 @@ err3; stb r0,0(r3)
|
||||
mr r3,r4
|
||||
blr
|
||||
|
||||
_GLOBAL_TOC(__clear_user)
|
||||
_GLOBAL_TOC(__arch_clear_user)
|
||||
cmpdi r4,32
|
||||
neg r6,r3
|
||||
li r0,0
|
||||
@@ -193,4 +193,4 @@ err1; dcbz 0,r3
|
||||
cmpdi r4,32
|
||||
blt .Lshort_clear
|
||||
b .Lmedium_clear
|
||||
EXPORT_SYMBOL(__clear_user)
|
||||
EXPORT_SYMBOL(__arch_clear_user)
|
||||
|
||||
@@ -183,14 +183,14 @@ static ssize_t raw_attr_read(struct file *filep, struct kobject *kobj,
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
|
||||
static void create_elog_obj(uint64_t id, size_t size, uint64_t type)
|
||||
{
|
||||
struct elog_obj *elog;
|
||||
int rc;
|
||||
|
||||
elog = kzalloc(sizeof(*elog), GFP_KERNEL);
|
||||
if (!elog)
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
elog->kobj.kset = elog_kset;
|
||||
|
||||
@@ -223,18 +223,37 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
|
||||
rc = kobject_add(&elog->kobj, NULL, "0x%llx", id);
|
||||
if (rc) {
|
||||
kobject_put(&elog->kobj);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* As soon as the sysfs file for this elog is created/activated there is
|
||||
* a chance the opal_errd daemon (or any userspace) might read and
|
||||
* acknowledge the elog before kobject_uevent() is called. If that
|
||||
* happens then there is a potential race between
|
||||
* elog_ack_store->kobject_put() and kobject_uevent() which leads to a
|
||||
* use-after-free of a kernfs object resulting in a kernel crash.
|
||||
*
|
||||
* To avoid that, we need to take a reference on behalf of the bin file,
|
||||
* so that our reference remains valid while we call kobject_uevent().
|
||||
* We then drop our reference before exiting the function, leaving the
|
||||
* bin file to drop the last reference (if it hasn't already).
|
||||
*/
|
||||
|
||||
/* Take a reference for the bin file */
|
||||
kobject_get(&elog->kobj);
|
||||
rc = sysfs_create_bin_file(&elog->kobj, &elog->raw_attr);
|
||||
if (rc) {
|
||||
if (rc == 0) {
|
||||
kobject_uevent(&elog->kobj, KOBJ_ADD);
|
||||
} else {
|
||||
/* Drop the reference taken for the bin file */
|
||||
kobject_put(&elog->kobj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kobject_uevent(&elog->kobj, KOBJ_ADD);
|
||||
/* Drop our reference */
|
||||
kobject_put(&elog->kobj);
|
||||
|
||||
return elog;
|
||||
return;
|
||||
}
|
||||
|
||||
static irqreturn_t elog_event(int irq, void *data)
|
||||
|
||||
@@ -125,12 +125,29 @@ static void pnv_setup_rfi_flush(void)
|
||||
type = L1D_FLUSH_ORI;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are non-Power9 bare metal, we don't need to flush on kernel
|
||||
* entry or after user access: they fix a P9 specific vulnerability.
|
||||
*/
|
||||
if (!pvr_version_is(PVR_POWER9)) {
|
||||
security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY);
|
||||
security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS);
|
||||
}
|
||||
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \
|
||||
(security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \
|
||||
security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV));
|
||||
|
||||
setup_rfi_flush(type, enable);
|
||||
setup_count_cache_flush();
|
||||
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
|
||||
security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY);
|
||||
setup_entry_flush(enable);
|
||||
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
|
||||
security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
|
||||
setup_uaccess_flush(enable);
|
||||
}
|
||||
|
||||
static void __init pnv_setup_arch(void)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#include <asm/udbg.h>
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#define DBG(fmt...) do { } while (0)
|
||||
#endif
|
||||
|
||||
static void pnv_smp_setup_cpu(int cpu)
|
||||
|
||||
@@ -565,6 +565,14 @@ void pseries_setup_rfi_flush(void)
|
||||
|
||||
setup_rfi_flush(types, enable);
|
||||
setup_count_cache_flush();
|
||||
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
|
||||
security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY);
|
||||
setup_entry_flush(enable);
|
||||
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
|
||||
security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
|
||||
setup_uaccess_flush(enable);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
|
||||
@@ -21,4 +21,7 @@
|
||||
/* vDSO location */
|
||||
#define AT_SYSINFO_EHDR 33
|
||||
|
||||
/* entries in ARCH_DLINFO */
|
||||
#define AT_VECTOR_SIZE_ARCH 1
|
||||
|
||||
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
|
||||
|
||||
@@ -2097,4 +2097,4 @@ out:
|
||||
return err;
|
||||
}
|
||||
arch_initcall(init_cpum_sampling_pmu);
|
||||
core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640);
|
||||
core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0644);
|
||||
|
||||
@@ -907,6 +907,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE_AUTO))
|
||||
nospec_auto_detect();
|
||||
|
||||
jump_label_init();
|
||||
parse_early_param();
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
/* Deactivate elfcorehdr= kernel parameter */
|
||||
|
||||
@@ -831,7 +831,7 @@ void __init smp_detect_cpus(void)
|
||||
*/
|
||||
static void smp_start_secondary(void *cpuvoid)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
int cpu = raw_smp_processor_id();
|
||||
|
||||
S390_lowcore.last_update_clock = get_tod_clock();
|
||||
S390_lowcore.restart_stack = (unsigned long) restart_stack;
|
||||
@@ -844,6 +844,7 @@ static void smp_start_secondary(void *cpuvoid)
|
||||
set_cpu_flag(CIF_ASCE_PRIMARY);
|
||||
set_cpu_flag(CIF_ASCE_SECONDARY);
|
||||
cpu_init();
|
||||
rcu_cpu_starting(cpu);
|
||||
preempt_disable();
|
||||
init_cpu_timer();
|
||||
vtime_init();
|
||||
|
||||
@@ -354,8 +354,9 @@ static DEFINE_PER_CPU(atomic_t, clock_sync_word);
|
||||
static DEFINE_MUTEX(clock_sync_mutex);
|
||||
static unsigned long clock_sync_flags;
|
||||
|
||||
#define CLOCK_SYNC_HAS_STP 0
|
||||
#define CLOCK_SYNC_STP 1
|
||||
#define CLOCK_SYNC_HAS_STP 0
|
||||
#define CLOCK_SYNC_STP 1
|
||||
#define CLOCK_SYNC_STPINFO_VALID 2
|
||||
|
||||
/*
|
||||
* The get_clock function for the physical clock. It will get the current
|
||||
@@ -592,6 +593,22 @@ void stp_queue_work(void)
|
||||
queue_work(time_sync_wq, &stp_work);
|
||||
}
|
||||
|
||||
static int __store_stpinfo(void)
|
||||
{
|
||||
int rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
|
||||
|
||||
if (rc)
|
||||
clear_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
|
||||
else
|
||||
set_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int stpinfo_valid(void)
|
||||
{
|
||||
return stp_online && test_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
|
||||
}
|
||||
|
||||
static int stp_sync_clock(void *data)
|
||||
{
|
||||
struct clock_sync_data *sync = data;
|
||||
@@ -613,8 +630,7 @@ static int stp_sync_clock(void *data)
|
||||
if (rc == 0) {
|
||||
sync->clock_delta = clock_delta;
|
||||
clock_sync_global(clock_delta);
|
||||
rc = chsc_sstpi(stp_page, &stp_info,
|
||||
sizeof(struct stp_sstpi));
|
||||
rc = __store_stpinfo();
|
||||
if (rc == 0 && stp_info.tmd != 2)
|
||||
rc = -EAGAIN;
|
||||
}
|
||||
@@ -659,7 +675,7 @@ static void stp_work_fn(struct work_struct *work)
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
|
||||
rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
|
||||
rc = __store_stpinfo();
|
||||
if (rc || stp_info.c == 0)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -696,10 +712,14 @@ static ssize_t stp_ctn_id_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online)
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%016llx\n",
|
||||
*(unsigned long long *) stp_info.ctnid);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid())
|
||||
ret = sprintf(buf, "%016llx\n",
|
||||
*(unsigned long long *) stp_info.ctnid);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
|
||||
@@ -708,9 +728,13 @@ static ssize_t stp_ctn_type_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online)
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", stp_info.ctn);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid())
|
||||
ret = sprintf(buf, "%i\n", stp_info.ctn);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
|
||||
@@ -719,9 +743,13 @@ static ssize_t stp_dst_offset_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online || !(stp_info.vbits & 0x2000))
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid() && (stp_info.vbits & 0x2000))
|
||||
ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
|
||||
@@ -730,9 +758,13 @@ static ssize_t stp_leap_seconds_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online || !(stp_info.vbits & 0x8000))
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid() && (stp_info.vbits & 0x8000))
|
||||
ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
|
||||
@@ -741,9 +773,13 @@ static ssize_t stp_stratum_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online)
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid())
|
||||
ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL);
|
||||
@@ -752,9 +788,13 @@ static ssize_t stp_time_offset_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online || !(stp_info.vbits & 0x0800))
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", (int) stp_info.tto);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid() && (stp_info.vbits & 0x0800))
|
||||
ret = sprintf(buf, "%i\n", (int) stp_info.tto);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
|
||||
@@ -763,9 +803,13 @@ static ssize_t stp_time_zone_offset_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online || !(stp_info.vbits & 0x4000))
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid() && (stp_info.vbits & 0x4000))
|
||||
ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(time_zone_offset, 0400,
|
||||
@@ -775,9 +819,13 @@ static ssize_t stp_timing_mode_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online)
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", stp_info.tmd);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid())
|
||||
ret = sprintf(buf, "%i\n", stp_info.tmd);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
|
||||
@@ -786,9 +834,13 @@ static ssize_t stp_timing_state_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (!stp_online)
|
||||
return -ENODATA;
|
||||
return sprintf(buf, "%i\n", stp_info.tst);
|
||||
ssize_t ret = -ENODATA;
|
||||
|
||||
mutex_lock(&stp_work_mutex);
|
||||
if (stpinfo_valid())
|
||||
ret = sprintf(buf, "%i\n", stp_info.tst);
|
||||
mutex_unlock(&stp_work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
|
||||
|
||||
@@ -1039,38 +1039,9 @@ void smp_fetch_global_pmu(void)
|
||||
* are flush_tlb_*() routines, and these run after flush_cache_*()
|
||||
* which performs the flushw.
|
||||
*
|
||||
* The SMP TLB coherency scheme we use works as follows:
|
||||
*
|
||||
* 1) mm->cpu_vm_mask is a bit mask of which cpus an address
|
||||
* space has (potentially) executed on, this is the heuristic
|
||||
* we use to avoid doing cross calls.
|
||||
*
|
||||
* Also, for flushing from kswapd and also for clones, we
|
||||
* use cpu_vm_mask as the list of cpus to make run the TLB.
|
||||
*
|
||||
* 2) TLB context numbers are shared globally across all processors
|
||||
* in the system, this allows us to play several games to avoid
|
||||
* cross calls.
|
||||
*
|
||||
* One invariant is that when a cpu switches to a process, and
|
||||
* that processes tsk->active_mm->cpu_vm_mask does not have the
|
||||
* current cpu's bit set, that tlb context is flushed locally.
|
||||
*
|
||||
* If the address space is non-shared (ie. mm->count == 1) we avoid
|
||||
* cross calls when we want to flush the currently running process's
|
||||
* tlb state. This is done by clearing all cpu bits except the current
|
||||
* processor's in current->mm->cpu_vm_mask and performing the
|
||||
* flush locally only. This will force any subsequent cpus which run
|
||||
* this task to flush the context from the local tlb if the process
|
||||
* migrates to another cpu (again).
|
||||
*
|
||||
* 3) For shared address spaces (threads) and swapping we bite the
|
||||
* bullet for most cases and perform the cross call (but only to
|
||||
* the cpus listed in cpu_vm_mask).
|
||||
*
|
||||
* The performance gain from "optimizing" away the cross call for threads is
|
||||
* questionable (in theory the big win for threads is the massive sharing of
|
||||
* address space state across processors).
|
||||
* mm->cpu_vm_mask is a bit mask of which cpus an address
|
||||
* space has (potentially) executed on, this is the heuristic
|
||||
* we use to limit cross calls.
|
||||
*/
|
||||
|
||||
/* This currently is only used by the hugetlb arch pre-fault
|
||||
@@ -1080,18 +1051,13 @@ void smp_fetch_global_pmu(void)
|
||||
void smp_flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
u32 ctx = CTX_HWBITS(mm->context);
|
||||
int cpu = get_cpu();
|
||||
|
||||
if (atomic_read(&mm->mm_users) == 1) {
|
||||
cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
|
||||
goto local_flush_and_out;
|
||||
}
|
||||
get_cpu();
|
||||
|
||||
smp_cross_call_masked(&xcall_flush_tlb_mm,
|
||||
ctx, 0, 0,
|
||||
mm_cpumask(mm));
|
||||
|
||||
local_flush_and_out:
|
||||
__flush_tlb_mm(ctx, SECONDARY_CONTEXT);
|
||||
|
||||
put_cpu();
|
||||
@@ -1114,17 +1080,15 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long
|
||||
{
|
||||
u32 ctx = CTX_HWBITS(mm->context);
|
||||
struct tlb_pending_info info;
|
||||
int cpu = get_cpu();
|
||||
|
||||
get_cpu();
|
||||
|
||||
info.ctx = ctx;
|
||||
info.nr = nr;
|
||||
info.vaddrs = vaddrs;
|
||||
|
||||
if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
|
||||
cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
|
||||
else
|
||||
smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
|
||||
&info, 1);
|
||||
smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
|
||||
&info, 1);
|
||||
|
||||
__flush_tlb_pending(ctx, nr, vaddrs);
|
||||
|
||||
@@ -1134,14 +1098,13 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long
|
||||
void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
|
||||
{
|
||||
unsigned long context = CTX_HWBITS(mm->context);
|
||||
int cpu = get_cpu();
|
||||
|
||||
if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
|
||||
cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
|
||||
else
|
||||
smp_cross_call_masked(&xcall_flush_tlb_page,
|
||||
context, vaddr, 0,
|
||||
mm_cpumask(mm));
|
||||
get_cpu();
|
||||
|
||||
smp_cross_call_masked(&xcall_flush_tlb_page,
|
||||
context, vaddr, 0,
|
||||
mm_cpumask(mm));
|
||||
|
||||
__flush_tlb_page(context, vaddr);
|
||||
|
||||
put_cpu();
|
||||
|
||||
@@ -36,14 +36,14 @@ int write_sigio_irq(int fd)
|
||||
}
|
||||
|
||||
/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */
|
||||
static DEFINE_SPINLOCK(sigio_spinlock);
|
||||
static DEFINE_MUTEX(sigio_mutex);
|
||||
|
||||
void sigio_lock(void)
|
||||
{
|
||||
spin_lock(&sigio_spinlock);
|
||||
mutex_lock(&sigio_mutex);
|
||||
}
|
||||
|
||||
void sigio_unlock(void)
|
||||
{
|
||||
spin_unlock(&sigio_spinlock);
|
||||
mutex_unlock(&sigio_mutex);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ struct perf_ibs {
|
||||
u64 max_period;
|
||||
unsigned long offset_mask[1];
|
||||
int offset_max;
|
||||
unsigned int fetch_count_reset_broken : 1;
|
||||
struct cpu_perf_ibs __percpu *pcpu;
|
||||
|
||||
struct attribute **format_attrs;
|
||||
@@ -346,11 +347,15 @@ static u64 get_ibs_op_count(u64 config)
|
||||
{
|
||||
u64 count = 0;
|
||||
|
||||
/*
|
||||
* If the internal 27-bit counter rolled over, the count is MaxCnt
|
||||
* and the lower 7 bits of CurCnt are randomized.
|
||||
* Otherwise CurCnt has the full 27-bit current counter value.
|
||||
*/
|
||||
if (config & IBS_OP_VAL)
|
||||
count += (config & IBS_OP_MAX_CNT) << 4; /* cnt rolled over */
|
||||
|
||||
if (ibs_caps & IBS_CAPS_RDWROPCNT)
|
||||
count += (config & IBS_OP_CUR_CNT) >> 32;
|
||||
count = (config & IBS_OP_MAX_CNT) << 4;
|
||||
else if (ibs_caps & IBS_CAPS_RDWROPCNT)
|
||||
count = (config & IBS_OP_CUR_CNT) >> 32;
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -375,7 +380,12 @@ perf_ibs_event_update(struct perf_ibs *perf_ibs, struct perf_event *event,
|
||||
static inline void perf_ibs_enable_event(struct perf_ibs *perf_ibs,
|
||||
struct hw_perf_event *hwc, u64 config)
|
||||
{
|
||||
wrmsrl(hwc->config_base, hwc->config | config | perf_ibs->enable_mask);
|
||||
u64 tmp = hwc->config | config;
|
||||
|
||||
if (perf_ibs->fetch_count_reset_broken)
|
||||
wrmsrl(hwc->config_base, tmp & ~perf_ibs->enable_mask);
|
||||
|
||||
wrmsrl(hwc->config_base, tmp | perf_ibs->enable_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -637,18 +647,24 @@ fail:
|
||||
perf_ibs->offset_max,
|
||||
offset + 1);
|
||||
} while (offset < offset_max);
|
||||
/*
|
||||
* Read IbsBrTarget, IbsOpData4, and IbsExtdCtl separately
|
||||
* depending on their availability.
|
||||
* Can't add to offset_max as they are staggered
|
||||
*/
|
||||
if (event->attr.sample_type & PERF_SAMPLE_RAW) {
|
||||
/*
|
||||
* Read IbsBrTarget and IbsOpData4 separately
|
||||
* depending on their availability.
|
||||
* Can't add to offset_max as they are staggered
|
||||
*/
|
||||
if (ibs_caps & IBS_CAPS_BRNTRGT) {
|
||||
rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
|
||||
size++;
|
||||
if (perf_ibs == &perf_ibs_op) {
|
||||
if (ibs_caps & IBS_CAPS_BRNTRGT) {
|
||||
rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
|
||||
size++;
|
||||
}
|
||||
if (ibs_caps & IBS_CAPS_OPDATA4) {
|
||||
rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
if (ibs_caps & IBS_CAPS_OPDATA4) {
|
||||
rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
|
||||
if (perf_ibs == &perf_ibs_fetch && (ibs_caps & IBS_CAPS_FETCHCTLEXTD)) {
|
||||
rdmsrl(MSR_AMD64_ICIBSEXTDCTL, *buf++);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
@@ -744,6 +760,13 @@ static __init void perf_event_ibs_init(void)
|
||||
{
|
||||
struct attribute **attr = ibs_op_format_attrs;
|
||||
|
||||
/*
|
||||
* Some chips fail to reset the fetch count when it is written; instead
|
||||
* they need a 0-1 transition of IbsFetchEn.
|
||||
*/
|
||||
if (boot_cpu_data.x86 >= 0x16 && boot_cpu_data.x86 <= 0x18)
|
||||
perf_ibs_fetch.fetch_count_reset_broken = 1;
|
||||
|
||||
perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
|
||||
|
||||
if (ibs_caps & IBS_CAPS_OPCNT) {
|
||||
|
||||
@@ -100,14 +100,14 @@
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \
|
||||
static ssize_t __cstate_##_var##_show(struct kobject *kobj, \
|
||||
struct kobj_attribute *attr, \
|
||||
static ssize_t __cstate_##_var##_show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *page) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
|
||||
return sprintf(page, _format "\n"); \
|
||||
} \
|
||||
static struct kobj_attribute format_attr_##_var = \
|
||||
static struct device_attribute format_attr_##_var = \
|
||||
__ATTR(_name, 0444, __cstate_##_var##_show, NULL)
|
||||
|
||||
static ssize_t cstate_get_attr_cpumask(struct device *dev,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user